module Text.PrettyPrint(prettyPrint) where


import Data.SyntaxIR
import Data.List.Split


prettyPrint (Func fn)           = showFn fn
prettyPrint (Num num)           = showNumber num
prettyPrint (Boolean True)      = "#t"
prettyPrint (Boolean False)     = "#f"
prettyPrint (Err msg)           = "error: " ++ show msg
prettyPrint (Ref ref)           = ref
prettyPrint (Def ref body)      = showDefition ref body
prettyPrint (Compound elements) = showElements elements


showDefition name body = 
    let bodyrepr = prettyPrint body
    in "(define "++name++" "++bodyrepr++")"


showElements elements = 
    let bodyrepr = sepWith prettyPrint elements
    in "("++bodyrepr++")"


showFn (NatvFn f repr) = "(lambda (...) <native ["++repr++"]> )"
showFn (LangFn ps ast) = "(lambda ("++args++") "++body++")"
  where 
    args = sepWith id ps
    body = sepWith prettyPrint ast

showFn (ClojFn _ ps ast) = "(lambda ("++args++") "++body++")"
  where
    args = sepWith id ps
    body = sepWith prettyPrint ast


-- if int like, it will drop the trailing `.0'
showNumber n = 
    let shown = show n 
    in case splitOn "." shown of
          (num:"0":[]) -> num
          _            -> shown


sepWith f []          = ""
sepWith f (head:tail) = foldl (\acc e -> acc++" "++(f e)) (f head) tail


