implementation module Sil.Util.Printer import _SystemArray import StdEnum from StdFunc import id import StdInt import StdList import StdOverloaded import StdString from Data.Func import $ import Data.List import Data.Maybe import Text import Sil.Parse import Sil.Syntax import Sil.Types :: PrintState = { indent :: Int } instance zero PrintState where zero = {indent=0} incIndent :: PrintState -> PrintState incIndent ps = {ps & indent=inc ps.indent} decIndent :: PrintState -> PrintState decIndent ps = {ps & indent=dec ps.indent} instance toString PrintState where toString st = {'\t' \\ _ <- [1..st.indent]} instance PrettyPrinter [Token] where print st [] = "" print st [t] = toString t print st [t:ts=:[t`:_]] = toString t +++ spaceBetween t t` +++ print st` ts where st` = {st & indent=indent`} indent` = newIndent t t` st.indent spaceBetween :: Token Token -> String spaceBetween _ TBraceClose = newline spaceBetween TParenOpen _ = "" spaceBetween TParenClose TBraceOpen = space spaceBetween TParenClose _ = "" spaceBetween TBraceOpen _ = newline spaceBetween TBraceClose _ = newline spaceBetween TComma _ = space spaceBetween TSemicolon _ = newline spaceBetween TAssign _ = space spaceBetween (TLit _) _ = space spaceBetween TIf _ = space spaceBetween TWhile _ = space spaceBetween TReturn _ = space spaceBetween (TName _) TParenClose = "" spaceBetween (TName _) TSemicolon = "" spaceBetween (TName _) _ = space newline = "\r\n" +++ {'\t' \\ _ <- [1..indent`]} space = " " newIndent :: Token Token -> Int -> Int newIndent TBraceOpen _ = inc newIndent _ TBraceClose = dec newIndent _ _ = id instance PrettyPrinter Program where print st prog = p st prog.p_funs where p :: PrintState [Function] -> String p _ [] = "" p st [f] = print st f p st [f:fs] = print st f <+ "\r\n\r\n" <+ p st fs instance PrettyPrinter Function where print st f = st <+ f.f_type <+ " " <+ f.f_name <+ "(" <+ printersperse ", " f.f_args <+ ") {\r\n" <+ print {st & indent=st.indent+1} f.f_code <+ "\r\n" <+ st <+ "}" instance PrettyPrinter CodeBlock where print st cb = concat $ intersperse "\r\n" $ [print st x \\ x <- cb.cb_init] ++ [print st x \\ x <- cb.cb_content] instance PrettyPrinter Initialisation where print st init = st <+ init.init_type <+ " " <+ init.init_name <+ ";" instance PrettyPrinter Statement where print st (If bs else) = st <+ printersperse " else " (map oneblock bs) <+ else` where st` = incIndent st oneblock (c,b) = "if (" <+ c <+ ") {\r\n" <+ print st` b <+ "\r\n" <+ st <+ "}" else` = case else of Nothing -> "" Just e -> " else {\r\n" <+ print st` e <+ "\r\n" <+ st <+ "}" print st (While c do) = st <+ "while (" <+ c <+ ") {\r\n" <+ print (incIndent st) do <+ "\r\n" <+ st <+ "}" print st stm = st <+ stm printersperse :: a [b] -> String | toString a & toString b printersperse _ [] = "" printersperse _ [x] = toString x printersperse g [x:xs] = x <+ g <+ printersperse g xs