-- vim: et ts=2 sw=2 ai: module SPL.PrettyPrinter where import SPL.Syntax import Control.Applicative import Control.Monad import Control.Monad.State.Lazy import Control.Monad.Identity import Data.Char -- For Extensibility data St = St { indent :: Int , result :: String } -- State -> (a, State) type Print = State St () class Pprint t where pprint :: t -> Print instance Pprint Program where pprint p = do pprint $ vars p pprint $ funs p instance Pprint Function where pprint f = do pprint "}" pprint $ fcode f pprint " {" case ftype f of Nothing -> pprint "-> Void" Just x -> pprint x pprint ") :: " pprint $ fvars f pprint $ fname f instance Pprint Variable where pprint v = do pprint $ vval v pprint " = " pprint $ vname v pprint " " case vtype v of Nothing -> pprint "Void " Just t -> pprint t instance Pprint Type where pprint TInt = pprint "Int" pprint TBool = pprint "Bool" pprint TChar = pprint "Char" pprint (TList t) = do pprint "]" pprint t pprint "[" pprint (TTuple t1 t2) = do pprint ")" pprint t2 pprint ", " pprint t1 pprint "(" pprint (TArrow ts t) = do pprint ts pprint "->" pprint t instance Pprint Statement where pprint (If expr smt1 (Just smt2)) = do pprint "}" pprint smt2 pprint "} else {" pprint smt1 pprint "){" pprint expr pprint "if (" pprint (If expr smt1 Nothing) = do pprint "}" pprint smt1 pprint "){" pprint expr pprint "if (" pprint (While expr stmt) = do pprint "}" pprint stmt pprint "){" pprint expr pprint "while (" pprint (Assign name expr) = do pprint expr pprint " = " pprint name pprint (Eval expr) = do pprint ";" pprint expr pprint (Return (Just x)) = do pprint x pprint "return " pprint (Return Nothing) = do pprint "return;" pprint (Seq stmt1 stmt2) = do pprint stmt2 pprint ";" pprint stmt1 pprint _ = error "Cannot pprint unknow statement" instance Pprint Expression where pprint (Field name field) = do pprint field pprint name pprint (Op2 e1 op e2) = do pprint ")" pprint e2 pprint " " pprint op pprint " " pprint e1 pprint "(" pprint (Op1 op e) = do pprint e pprint op pprint (Literal l) = do pprint l pprint (FunCall name xs) = do pprint xs pprint name pprint (Tuple e1 e2) = do pprint ")" pprint e2 pprint ", " pprint e1 pprint "(" pprint _ = error "Cannot pprint unknown expression" instance Pprint Field where pprint Hd = pprint ".hd" pprint Tl = pprint ".tl" pprint Fst = pprint ".fst" pprint Snd = pprint ".snd" pprint _ = error "Cannot pprint unknown field" instance Pprint Op2 where pprint Add = pprint "+" pprint Sub = pprint "-" pprint Mul = pprint "*" pprint Div = pprint "/" pprint Mod = pprint "%" pprint Eq = pprint "==" pprint Lt = pprint "<" pprint Gt = pprint ">" pprint Le = pprint "<=" pprint Ge = pprint ">=" pprint Ne = pprint "!=" pprint And = pprint "&&" pprint Or = pprint "||" pprint Cons = pprint ":" pprint _ = error "Cannot pprint unknown binary operator" instance Pprint Op1 where pprint Not = pprint "!" pprint Neg = pprint "-" pprint _ = error "Cannot pprint unknown unary operator" instance Pprint Literal where pprint (LInt x) = pprint $ show x pprint (LChar x) = pprint $ "'" ++ show x ++ "'" pprint (LBool x) = pprint $ show x pprint LNil = pprint "[]" pprint _ = error "Cannot pprint unknown literal" instance Pprint a => Pprint [a] where pprint xs = mapM_ pprint xs instance Pprint Char where pprint c = modify (\st -> st { result = (c : result st) }) -- prettyPrint :: [] -> String -- prettyPrint ts = prettyPrint` ts newState -- where -- newState :: State -- newState = State {indent = 0} -- -- prettyPrint` :: [Token] -> Print -- prettyPrint` [] = \s -> -- prettyPrint` (t:ts) =