module C where import Data.List import Text.PrettyPrint.HughesPJ newtype Program = Program [TopLevel] data TopLevel = Function Type Var [Var] [Body] | Include FilePath | GlobalVar Type Var (Maybe (Maybe Int)) (Maybe Atom) | TVerbatim String deriving Show data Body = App Var [Atom] | Assign Var Atom | Verbatim String deriving Show data Atom = AtomVar String | AtomChar Char deriving Show type Var = String type Type = String data TypeSpecifier = Void | Char | Short | Int | Long | Float | Double | Signed | Unsigned | Struct | Enum | TypeDef deriving Show ppProgram :: Program -> Doc ppProgram (Program tl) = vcat $ map ppTopLevel tl ppTopLevel :: TopLevel -> Doc ppTopLevel (Include fp) = text "#include" <+> text fp ppTopLevel (Function retType name args body) = text retType <+> text name <+> parens (commaSep text args) $+$ lbrace $+$ nest 2 (vcat (map ppBody body)) $+$ rbrace ppTopLevel (GlobalVar vtype name arraySize val) = text vtype <+> text name <> ppArraySize arraySize <> maybe empty (\v -> space <> equals <+> ppAtom v) val <> semi ppTopLevel (TVerbatim str) = text str ppArraySize :: Maybe (Maybe Int) -> Doc ppArraySize Nothing = empty ppArraySize (Just Nothing) = text "[]" ppArraySize (Just (Just n)) = brackets (int n) ppBody :: Body -> Doc ppBody (App var atoms) = text var <+> parens (commaSep ppAtom atoms) <> semi ppBody (Assign var atom) = text var <+> equals <+> ppAtom atom <> semi ppBody (Verbatim str) = text str ppAtom :: Atom -> Doc ppAtom (AtomVar var) = text var ppAtom (AtomChar c) = text (show c) commaSep :: (a -> Doc) -> [a] -> Doc commaSep pp = hcat . punctuate comma . map pp