summaryrefslogblamecommitdiff
path: root/src/SPL/PrettyPrinter.hs
blob: d7112037c186a89c99f2c6cb4d7b39f1c8c27345 (plain) (tree)























                               

                   
                              








                                 
                              






                               
                          















                              
                               
                                        
               
                     
               






























                                                     



                                






                            

                        
                         

                               




                           
                                                       



















































                                                             
-- 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) =