----------------------------------------------------------------
-- the Henk Abstract Syntax
-- Copyright 2000, Jan-Willem Roorda and Daan Leijen
----------------------------------------------------------------
module HenkAS where
import Text.PrettyPrint.HughesPJ
----------------------------------------------------------------
-- Abstract Syntax
----------------------------------------------------------------
data Program = Program [TypeDecl] [ValueDecl]
data TypeDecl = Data Var [Var]
data ValueDecl = Let Bind
| LetRec [Bind]
data Bind = Bind Var Expr
data Expr = Var Var
| Lit Lit
| Box
| Star
| Unknown
| App Expr Expr
| Case Expr [Alt] [Expr]
| In ValueDecl Expr
| Pi Var Expr
| Lam Var Expr
data Alt = Alt Pat Expr
data Pat = PatVar Var
| PatLit Lit
data Var = TVar Identifier Expr
data Lit = LitInt Integer
type Identifier = String
anonymous = "_"
isAnonymous s = (null s || (head s == head anonymous))
----------------------------------------------------------------
-- pretty print abstract syntax
----------------------------------------------------------------
instance Show Program where
showsPrec d program = shows (pprogram program)
vsep ds
= vcat (map ($$ text "") ds)
-- program
pprogram (Program tdecls vdecls)
= vsep ((map ptdecl tdecls) ++ (map pvdecl vdecls))
ptdecl (Data v vs)
= (text "data" <+> pbindvar v)
$$ indent (text "=" <+> braced (map ptvar vs))
pvdecl vdecl
= case vdecl of
Let bind -> text "let" <+> pbind bind
LetRec binds -> text "letrec" $$ indent (braced (map pbind binds))
pbind (Bind v e)
= pbindvar v $$ indent (text "=" <+> pexpr e)
-- expressions (are parenthesis correct ?)
parensExpr e
= case e of
In _ _ -> parens (pexpr e)
Pi _ _ -> parens (pexpr e)
Lam _ _ -> parens (pexpr e)
Case _ _ _ -> parens (pexpr e)
App _ _ -> parens (pexpr e)
Var (TVar i t) -> case t of
Unknown -> pexpr e
other -> parens (pexpr e)
other -> pexpr e
pexpr e
= case e of
Var v -> pboundvar v
Lit l -> plit l
Box -> text "[]"
Star -> text "*"
Unknown -> text "?"
App e1 e2 -> pexpr e1 <+> parensExpr e2
Case e as ts-> sep $ [text "case" <+> parensExpr e <+> text "of"
,nest 3 (braced (map palt as))
] ++
(if (null as)
then []
else [text "at"
,nest 3 (braced (map pexpr ts))
])
In v e -> sep[ pvdecl v, text "in" <+> pexpr e]
Pi v e -> case v of
TVar i t | isAnonymous i -> parensExpr t <+> text "->" <+> pexpr e
TVar i Star -> sep[ text "\\/" <> text i <> text ".", pexpr e]
other -> sep[ text "|~|" <> pbindvar v <> text ".", pexpr e]
Lam v e -> case v of
TVar i Star -> sep[ text "/\\" <> text i <> text ".", pexpr e]
other -> sep[ text "\\" <> pbindvar v <> text ".", pexpr e]
-- atomic stuff
palt (Alt p e)
= ppat p <+> text "=>" <+> pexpr e
ppat p
= case p of PatVar v -> pboundvar v
PatLit l -> plit l
pboundvar v@(TVar i e)
= case e of Unknown -> text i
other -> ptvar v
pbindvar v@(TVar i e)
= case e of Star -> text i
other -> ptvar v
ptvar (TVar i e)
= text i <> colon <+> pexpr e
plit l
= case l of LitInt i -> integer i
braced []
= empty
braced ds
= let prefix = map text $ ["{"] ++ repeat ";"
in cat ((zipWith (<+>) prefix ds) ++ [text "}"])
indent
= nest 4
|