module Generic.Examples.Printing where
open import Size
open import Coinduction hiding (∞)
open import Data.Unit
open import Data.Bool
open import Data.Product
open import Data.Nat.Base
open import Data.Nat.Show as Nat
open import Data.List.Base as L hiding ([_] ; _++_ ; lookup)
open import Data.Char
open import Data.String using (String ; _++_ ; fromList ; toList)
open import Data.Stream as Str hiding (_++_ ; lookup)
open import Category.Monad
open import Category.Monad.State
open import Function
module ST = RawMonadState (StateMonadState (Stream String))
open ST
M = State (Stream String)
open import var hiding (get)
open import environment as E
open import varlike
open import Generic.Syntax as S
open import Generic.Semantics
module _ {I : Set} where
record Name (i : I) (Γ : List I) : Set where
constructor mkN; field getN : String
record Printer (i : I) (Γ : List I) : Set where
constructor mkP; field getP : M String
open Name
open Printer
module _ {I : Set} where
fresh : {i : I} {Γ : List I} → M (Name i Γ)
fresh = get >>= λ nms →
put (tail nms) >>= λ _ →
return $ mkN $ head nms
module _ {I : Set} (d : Desc I) where
Pieces : List I → I ─Scoped
Pieces [] i Γ = String
Pieces Δ i Γ = (Δ ─Env) (λ _ _ → String) [] × String
record Display : Set where
constructor mkD
field getD : ∀ {i Γ} → ⟦ d ⟧ Pieces i Γ → String
open Display
module _ {I : Set} {d : Desc I} where
printing : Display d → Sem d Name Printer
printing dis = record
{ th^𝓥 = λ n _ → mkN (getN n)
; var = λ n → mkP (return (getN n))
; alg = λ {i} {Γ} v → mkP
$ let p : M (⟦ d ⟧ (Pieces d) i Γ)
p = S.traverse rawIApplicative d (fmap d reify^M v)
in getD dis ST.<$> p
} where
vl^StName : VarLike {I} (λ i Γ → State (Stream String) (Name i Γ))
vl^StName = record
{ new = fresh
; th^𝓥 = λ st _ → mkN ∘ getN ST.<$> st }
reify^M : {Γ : List I} (Δ : List I) (i : I) →
Kripke Name Printer Δ i Γ →
M (Pieces d Δ i Γ)
reify^M [] i = getP
reify^M Δ@(_ ∷ _) i = λ f → let σ = freshˡ vl^StName _
in E.traverse rawIApplicative σ >>= λ ρ →
getP (f (freshʳ vl^Var Δ) ρ) >>= λ b →
return ((getN E.<$> ρ) , b)
print : Display d → {i : I} → Tm d ∞ i [] → String
print dis t = proj₁ $ getP (Sem.closed (printing dis) t) names where
flatten : {A : Set} → Stream (A × List A) → Stream A
flatten ((a , as) Str.∷ aass) = go a as (♭ aass) where
go : {A : Set} → A → List A → Stream (A × List A) → Stream A
go a [] aass = a ∷ ♯ flatten aass
go a (b ∷ as) aass = a ∷ ♯ go b as aass
names : Stream String
names = flatten $ Str.zipWith cons letters
$ "" ∷ ♯ Str.map Nat.show (allNatsFrom 0)
where
cons : (Char × List Char) → String → (String × List String)
cons (c , cs) suffix = appendSuffix c , L.map appendSuffix cs where
appendSuffix : Char → String
appendSuffix c = fromList (c ∷ []) ++ suffix
letters = Str.repeat $ 'a' , toList "bcdefghijklmnopqrstuvwxyz"
allNatsFrom : ℕ → Stream ℕ
allNatsFrom k = k ∷ ♯ allNatsFrom (1 + k)
open import Generic.Examples.UntypedLC
printLC : Display UTLC
getD printLC = case (λ { (f , t , _) → f ++ "(" ++ t ++ ")" })
(λ { ((x , b) , _) → "λ" ++ lookup x z ++ ". " ++ b })
open import Agda.Builtin.Equality
_ : print printLC `id ≡ "λa. a"
_ = refl
open import Generic.Examples.HuttonsRazor
printHR : Display HuttRaz
getD printHR = case (Nat.show ∘ proj₁)
(λ { (m , n , _) → m ++ " + " ++ n })
_ : print printHR ((lit 2 [+] lit 6) [+] lit 0) ≡ "2 + 6 + 0"
_ = refl
open import Generic.Examples.SystemF as SystemF
printSF : Display system-F
getD printSF = case (λ { (σ , τ , _) → σ ++ " → " ++ τ })
$ case (λ { ((x , b) , _) → "∀" ++ lookup x z ++ ". " ++ b })
$ case (λ { (f , t , _) → f ++ "(" ++ t ++ ")" })
$ case (λ { ((x , b) , _) → "λ" ++ lookup x z ++ ". " ++ b })
$ case (λ { (f , T , _) → f ++ "(" ++ T ++ ")" })
(λ { ((x , b) , _) → "Λ" ++ lookup x z ++ ". " ++ b })
_ : print printSF SystemF.`id ≡ "Λa. λb. b"
_ = refl