packages feed

lhc-0.10: src/Grin/Pretty.hs

-- TODO: Use unicode for the symbols.
module Grin.Pretty
    ( ppGrin
    , ppExpression
    ) where

import CompactString
import Grin.Types

import Text.PrettyPrint.ANSI.Leijen

import qualified Data.Map as Map

type QualMap = Map.Map CompactString Bool

grinQualMap :: Grin -> QualMap
grinQualMap grin
    = Map.unionsWith (\_ _ -> True) [nodeMap, funcMap, argsMap]
    where nodeMap = Map.fromListWith (\_ _ -> True) [ (name, False) | NodeDef{nodeName = Aliased _ name} <- grinNodes grin ]
          funcMap = Map.fromListWith (\_ _ -> True) [ (name, False) | FuncDef{funcDefName = Aliased _ name} <- grinFunctions grin ]
          argsMap = Map.fromListWith (\_ _ -> True) [ (name, False) | func <- grinFunctions grin, Aliased _ name <- funcDefArgs func ]

instance Pretty Grin where
    pretty = ppGrin

ppGrin :: Grin -> Doc
ppGrin grin
    = dullblue (text "Nodes:") <$$>
      vsep (map (ppNodeDef qualMap) (grinNodes grin)) <$$>
      dullblue (text "CAFs:") <$$>
      vsep (map (ppCAF qualMap) (grinCAFs grin)) <$$>
      dullblue (text "Functions:") <$$>
      vsep (map (ppFuncDef qualMap) (grinFunctions grin))
    where qualMap = grinQualMap grin

ppNodeDef :: QualMap -> NodeDef -> Doc
ppNodeDef qual (NodeDef name nodeType args)
    = text "node" <+> ppNodeType qual nodeType 0 name <+> hsep (map ppType args)

ppType PtrType  = blue (text "*")
ppType WordType = white (text "#")
ppType NodeType = white (text "!")

ppNodeType qual nt n name
    = green (worker qual nt n name)
    where worker qual ConstructorNode 0 name  = char 'C' <> ppRenamed qual name
          worker qual ConstructorNode n name  = char 'P' <> int n <> ppRenamed qual name
          worker qual FunctionNode 0 name = char 'F' <> ppRenamed qual name
          worker qual FunctionNode n name = char 'P' <> int n <> ppRenamed qual name

ppRenamed qual (Aliased n var) = pretty var <> if True || Map.findWithDefault False var qual then char '_' <> pretty n else empty
ppRenamed qual (Anonymous n)   = char 'x' <> pretty n
ppRenamed qual (Builtin p)     = char '@' <> pretty p
ppRenamed qual (External e tys)= parens (text "foreign" <+> text e) -- FIXME: Show types.

ppCAF :: QualMap -> CAF -> Doc
ppCAF qual (CAF name value)
    = ppRenamed qual name <+> equals <+> ppValue qual value

ppFuncDef :: QualMap -> FuncDef -> Doc
ppFuncDef qual (FuncDef name args body)
    = hsep (ppRenamed qual name : map (ppRenamed qual) args) <+> equals <$$>
      indent 2 (ppBeginExpression qual body)

ppBeginExpression :: QualMap -> Expression -> Doc
ppBeginExpression qual e@(_ :>>= _)
    = hang 3 (text "do" <+> ppExpression qual e)
ppBeginExpression qual e = ppExpression qual e

ppExpression :: QualMap -> Expression -> Doc
ppExpression qual (Unit value) = blue (text "unit") <+> ppValue qual value
ppExpression qual (Case value alts)
    = blue (text "case") <+> ppValue qual (Variable value) <+> blue (text "of") <$$>
      indent 2 (vsep (map (ppAlt qual) alts))
ppExpression qual (Application fn args)
    = hsep (ppRenamed qual fn:map (ppRenamed qual) args)
ppExpression qual (Update size ptr val)
    = blue (text "update") <+> int size <+> ppRenamed qual ptr <+> ppRenamed qual val
ppExpression qual (Store v)
    = blue (text "store") <+> ppValue qual v
ppExpression qual (a :>> c)
    = ppExpression qual a <$$>
      ppExpression qual c
ppExpression qual (a :>>= b :-> c)
    = ppValue qual (Variable b) <+> text "<-" <+> hang 0 (ppBeginExpression qual a) <$$>
      ppExpression qual c

ppAlt qual (value :> exp) = ppValue qual value <$$>
                            indent 2 (text "->" <+> align (ppBeginExpression qual exp))

ppValue qual (Node name nodeType missing args)
    = parens (hsep (ppNodeType qual nodeType missing name : map (ppRenamed qual) args))
ppValue qual (Vector vs) = brackets (hsep (map (ppRenamed qual) vs))
ppValue qual (Hole size) = parens (text "@hole" <+> hsep (replicate size (char '_')))
ppValue qual Empty = text "()"
ppValue qual (Lit lit) = ppLit lit
ppValue qual (Variable variable) = ppRenamed qual variable

ppLit (Lint i) = integer i
ppLit (Lrational r) = text (show r)
ppLit (Lchar char) = text (show char)
ppLit (Lstring string) = text (show string)