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