module Lvm.Core.Expr
( CoreModule, CoreDecl, Expr(..), Binds(..), Bind(..)
, Alts, Alt(..), Pat(..), Literal(..), Con(..)
) where
import Lvm.Common.Byte
import Lvm.Common.Id
import Lvm.Core.Module
import Lvm.Core.PrettyId
import Text.PrettyPrint.Leijen
type CoreModule = Module Expr
type CoreDecl = Decl Expr
data Expr = Let !Binds Expr
| Match !Id Alts
| Ap Expr Expr
| Lam !Id Expr
| Con !(Con Expr)
| Var !Id
| Lit !Literal
data Binds = Rec ![Bind]
| Strict !Bind
| NonRec !Bind
data Bind = Bind !Id Expr
type Alts = [Alt]
data Alt = Alt !Pat Expr
data Pat = PatCon !(Con Tag) ![Id]
| PatLit !Literal
| PatDefault
data Literal = LitInt !Int
| LitDouble !Double
| LitBytes !Bytes
data Con tag = ConId !Id
| ConTag tag !Arity
instance Pretty Expr where
pretty = ppExpr 0
ppExpr :: Int -> Expr -> Doc
ppExpr p expr
= case expr of
Match x as -> prec 0 $ align (text "match" <+> ppVarId x <+> text "with" <+> text "{" <$> indent 2 (pretty as)
<+> text "}")
Let bs x -> prec 0 $ align (ppLetBinds bs (text "in" <+> ppExpr 0 x))
Lam x e -> prec 0 $ text "\\" <> ppVarId x <+> ppLams "->" (</>) e
Ap e1 e2 -> prec 9 $ ppExpr 9 e1 <+> ppExpr 10 e2
Var x -> ppVarId x
Con con -> pretty con
Lit lit -> pretty lit
where
prec p' | p' >= p = id
| otherwise = parens
instance Pretty a => Pretty (Con a) where
pretty con =
case con of
ConId x -> ppConId x
ConTag tag arity -> parens (char '@' <> pretty tag <> comma <> pretty arity)
ppLams :: String -> (Doc -> Doc -> Doc) -> Expr -> Doc
ppLams arrow next expr
= case expr of
Lam x e -> ppVarId x <+> ppLams arrow next e
_ -> text arrow `next` ppExpr 0 expr
ppLetBinds :: Binds -> Doc -> Doc
ppLetBinds binds doc
= case binds of
NonRec bind -> nest 4 (text "let" <+> pretty bind) <$> doc
Strict bind -> nest 5 (text "let!" <+> pretty bind) <$> doc
Rec recs -> nest 4 (text "let" <+> pretty recs) <$> doc
instance Pretty Bind where
pretty (Bind x expr) =
nest 2 (ppId x <+> ppLams "=" (</>) expr <> semi)
prettyList = vcat . map pretty
instance Pretty Alt where
pretty (Alt pat expr) =
nest 4 (pretty pat <+> text "->" </> ppExpr 0 expr <> semi)
prettyList = vcat . map pretty
instance Pretty Pat where
pretty pat =
case pat of
PatCon con ids -> hsep (pretty con : map ppVarId ids)
PatLit lit -> pretty lit
PatDefault -> text "_"
instance Pretty Literal where
pretty lit =
case lit of
LitInt i -> pretty i
LitDouble d -> pretty d
LitBytes s -> text (show (stringFromBytes s))