module Typed.Pretty (
prettyTerm, prettyType, prettyTypedTerm, prettyC, prettyTC
) where
import Typed.Term ( Term(..), isNatVal )
import Typed.Type ( Type(..), Context )
import Typed.TypeSystem ( typeOf )
import Typed.Calculus ( Computation )
import Sidekick ( joinWith' )
type Pretty a = a -> String
prettyTerm :: Term -> String
prettyTerm term = case term of
TmUnit -> "unit"
TmTrue -> "true"
TmFalse -> "false"
TmIf t t1 t2 -> "(if " ++ s ++ " then " ++ s1 ++ " else " ++ s2 ++ ")"
where [s,s1,s2] = map prettyTerm [t,t1,t2]
TmZero -> "0"
TmSucc t
| isNatVal t -> (show . intFromNat) t
| otherwise -> "(succ " ++ prettyTerm t ++ ")"
TmPred t -> "(pred " ++ prettyTerm t ++ ")"
TmIsZero t -> "(iszero " ++ prettyTerm t ++ ")"
TmVar x -> "" ++ x ++ ""
TmAbs (x,p) t -> "(\\" ++ x ++ ":" ++ prettyType p ++ ". " ++ prettyTerm t ++ ")"
t1 `TmApp` t2 -> "(" ++ prettyTerm t1 ++ " " ++ prettyTerm t2 ++ ")"
TmWrong msg -> "(wrong: " ++ msg ++ ")"
TmStop -> "$stop$"
TmLoop -> "@loop@"
prettyType :: Type -> String
prettyType p = case p of
TpUnit -> "Unit"
TpBool -> "Bool"
TpNat -> "Nat"
p1 `TpArrow` p2 -> "(" ++ prettyType p1 ++ " -> " ++ prettyType p2 ++ ")"
TpCustom s -> "`" ++ s ++ "`"
TpBap s -> "?" ++ s ++ "?"
TpWrong s -> "<Wrong: " ++ s ++ ">"
prettyTypedTerm :: Context -> Term -> String
prettyTypedTerm ctx t = prettyTerm t ++ " :: " ++ (prettyType $ typeOf ctx t)
intFromNat :: Term -> Int
intFromNat TmZero = 0
intFromNat (TmSucc t) = 1 + intFromNat t
intFromNat t = error (show t ++ " is not a numeral")
prettyComputation :: String -> Pretty Term -> Computation -> String
prettyComputation sep termPrinter = (joinWith' "" "\n" sep) . map termPrinter
prettyC :: String -> Pretty Computation
prettyC sep = prettyComputation sep prettyTerm
prettyTC :: String -> Context -> Pretty Computation
prettyTC sep ctx = prettyComputation sep $ prettyTypedTerm ctx