elm/compiler/SourceSyntax/Expression.hs
Evan Czaplicki 69ed7631fe Start switching over to an AST that uses patterns in lambdas and
pulls the arguments out of Definitions (placing them in lambdas).
2013-07-04 11:36:08 +02:00

98 lines
3.5 KiB
Haskell

{-# LANGUAGE DeriveDataTypeable #-}
module SourceSyntax.Expression where
import Data.Data
import Data.List (intercalate)
import qualified Text.Pandoc as Pandoc
import qualified SourceSyntax.Helpers as Help
import qualified SourceSyntax.Location as Location
import qualified SourceSyntax.Pattern as Pattern
import qualified SourceSyntax.Literal as Literal
import Types.Types
type LExpr tipe var = Location.Located (Expr tipe var)
data Expr t v
= Literal Literal.Literal
| Var String
| Range (LExpr t v) (LExpr t v)
| ExplicitList [LExpr t v]
| Binop String (LExpr t v) (LExpr t v)
| Lambda Pattern.Pattern (LExpr t v)
| App (LExpr t v) (LExpr t v)
| MultiIf [(LExpr t v,LExpr t v)]
| Let [Def t v] (LExpr t v)
| Case (LExpr t v) [(Pattern.Pattern, LExpr t v)]
| Data String [LExpr t v]
| Access (LExpr t v) String
| Remove (LExpr t v) String
| Insert (LExpr t v) String (LExpr t v)
| Modify (LExpr t v) [(String, LExpr t v)]
| Record [(String, LExpr t v)]
| Markdown Pandoc.Pandoc
deriving (Eq, Data, Typeable)
data Def tipe var
= Def Pattern.Pattern (LExpr tipe var)
| TypeAnnotation String Type
deriving (Eq, Data, Typeable)
tuple es = Data ("Tuple" ++ show (length es)) es
delist (Location.L _ _ (Data "::" [h,t])) = h : delist t
delist _ = []
instance Show (Expr t v) where
show e =
let show' (Location.L _ _ e) = Help.parensIf (needsParens e) (show e) in
case e of
Literal lit -> show lit
Range e1 e2 -> "[" ++ show e1 ++ ".." ++ show e2 ++ "]"
ExplicitList es -> "[" ++ intercalate "," (map show es) ++ "]"
Binop op e1 e2 -> show' e1 ++ " " ++ op ++ " " ++ show' e2
Lambda x e -> let (xs,e') = getLambdas (Location.none $ Lambda x e) in
concat [ "\\", intercalate " " xs, " -> ", show e' ]
App e1 e2 -> show' e1 ++ " " ++ show' e2
MultiIf (p:ps) -> concat [ "if | ", iff p, sep (map iff ps) ]
where iff (b,e) = show b ++ " -> " ++ show e
sep = concatMap ("\n | " ++)
Let defs e -> "let { "++intercalate " ; " (map show defs)++" } in "++show e
Var (c:cs) -> if Help.isOp c then Help.parens (c:cs) else c:cs
Case e pats -> "case "++ show e ++" of " ++ Help.brkt (intercalate " ; " pats')
where pats' = map (\(p,e) -> show p ++ " -> " ++ show e) pats
Data "::" [h,t] -> show h ++ " :: " ++ show t
Data "[]" [] -> "[]"
Data name es -> name ++ " " ++ intercalate " " (map show' es)
Access e x -> show' e ++ "." ++ x
Remove e x -> Help.brkt (show e ++ " - " ++ x)
Insert (Location.L _ _ (Remove e y)) x v ->
Help.brkt (show e ++ " - " ++ y ++ " | " ++ x ++ " = " ++ show v)
Insert e x v -> Help.brkt (show e ++ " | " ++ x ++ " = " ++ show v)
Modify e fs -> Help.brkt (show e ++" | "++ intercalate ", " (map field fs))
where field (x,e) = x ++ " <- " ++ show e
Record r -> Help.brkt (intercalate ", " (map fields r))
where fields (f,e) = f ++ " = " ++ show e
Markdown _ -> "[markdown| ... |]"
instance Show (Def t v) where
show e =
case e of
TypeAnnotation n t -> n ++ " : " ++ show t
Def pattern e ->
show pattern ++ " = " ++ show e
getLambdas (Location.L _ _ (Lambda x e)) = (show x:xs,e')
where (xs,e') = getLambdas e
getLambdas e = ([],e)
needsParens e =
case e of
Binop _ _ _ -> True
Lambda _ _ -> True
App _ _ -> True
MultiIf _ -> True
Let _ _ -> True
Case _ _ -> True
Data name (x:xs) -> name /= "::"
_ -> False