1{-# OPTIONS_GHC -Wall #-}
3{-| The Abstract Syntax Tree (AST) for expressions comes in a couple formats.
4The first is the fully general version and is labeled with a prime (Expr').
5The others are specialized versions of the AST that represent specific phases
6of the compilation process. I expect there to be more phases as we begin to
7enrich the AST with more information.
9module AST.Expression.General where
12import Text.PrettyPrint as P
13import AST.Type (PortDirection)
15import qualified AST.Annotation as Annotation
16import qualified AST.Helpers as Help
17import qualified AST.Literal as Literal
18import qualified AST.Pattern as Pattern
19import qualified AST.Variable as Var
24{-| This is a fully general Abstract Syntax Tree (AST) for expressions. It has
25"type holes" that allow us to enrich the AST with additional information as we
26move through the compilation process. The type holes are used to represent:
28 ann: Annotations for arbitrary expressions. Allows you to add information
29 to the AST like position in source code or inferred types.
31 def: Definition style. The source syntax separates type annotations and
32 definitions, but after parsing we check that they are well formed and
35 var: Representation of variables. Starts as strings, but is later enriched
36 with information about what module a variable came from.
39type Expr annotation definition variable =
40 Annotation.Annotated annotation (Expr' annotation definition variable)
44 = Literal Literal.Literal
46 | Range (Expr ann def var) (Expr ann def var)
47 | ExplicitList [Expr ann def var]
48 | Binop var (Expr ann def var) (Expr ann def var)
49 | Lambda (Pattern.Pattern var) (Expr ann def var)
50 | App (Expr ann def var) (Expr ann def var)
51 | MultiIf [(Expr ann def var,Expr ann def var)]
52 | Let [def] (Expr ann def var)
53 | Case (Expr ann def var) [(Pattern.Pattern var, Expr ann def var)]
54 | Data String [Expr ann def var]
55 | Access (Expr ann def var) String
56 | Remove (Expr ann def var) String
57 | Insert (Expr ann def var) String (Expr ann def var)
58 | Modify (Expr ann def var) [(String, Expr ann def var)]
59 | Record [(String, Expr ann def var)]
60 -- for type checking and code gen only
61 | Port String (PortDirection var)
62 | Perform (Expr ann def var)
63 | GLShader String String Literal.GLShaderTipe
69rawVar :: String -> Expr' ann def Var.Raw
74localVar :: String -> Expr' ann def Var.Canonical
76 Var (Var.Canonical Var.Local x)
79tuple :: [Expr ann def var] -> Expr' ann def var
81 Data ("_Tuple" ++ show (length expressions)) expressions
86 "_save_the_environment!!!"
89dummyLet :: (Pretty def) => [def] -> Expr Annotation.Region def Var.Canonical
91 Annotation.none $ Let defs (Annotation.none $ Var (Var.builtin saveEnvName))
94instance (Pretty def, Pretty var, Var.ToString var) => Pretty (Expr' ann def var) where
103 Range lowExpr highExpr ->
104 P.brackets (pretty lowExpr <> P.text ".." <> pretty highExpr)
106 ExplicitList elements ->
107 P.brackets (commaCat (map pretty elements))
109 Binop op (Annotation.A _ (Literal (Literal.IntNum 0))) expr
110 | Var.toString op == "-" ->
111 P.text "-" <> prettyParens expr
113 Binop op leftExpr rightExpr ->
114 P.hang (prettyParens leftExpr) 2 (P.text op'' <+> prettyParens rightExpr)
116 op' = Var.toString op
117 op'' = if Help.isOp op' then op' else "`" ++ op' ++ "`"
119 Lambda pattern expr ->
120 P.text "\\" <> args <+> P.text "->" <+> pretty body
122 (patterns, body) = collectLambdas expr
123 args = P.sep (map Pattern.prettyParens (pattern : patterns))
126 P.hang func 2 (P.sep args)
129 map prettyParens (collectApps expr ++ [arg])
132 P.text "if" $$ nest 3 (vcat $ map iff branches)
134 iff (b,e) = P.text "|" <+> P.hang (pretty b <+> P.text "->") 2 (pretty e)
138 [ P.hang (P.text "let") 4 (P.vcat (map pretty defs))
139 , P.text "in" <+> pretty body
142 Case expr branches ->
143 P.hang pexpr 2 (P.vcat (map pretty' branches))
145 pexpr = P.sep [ P.text "case" <+> pretty expr, P.text "of" ]
146 pretty' (pattern, branch) =
147 pretty pattern <+> P.text "->" <+> pretty branch
150 pretty hd <+> P.text "::" <+> pretty tl
156 | Help.isTuple name ->
157 P.parens (commaCat (map pretty exprs))
159 P.hang (P.text name) 2 (P.sep (map prettyParens exprs))
161 Access record field ->
162 prettyParens record <> P.text "." <> variable field
164 Remove record field ->
165 P.braces (pretty record <+> P.text "-" <+> variable field)
167 Insert (Annotation.A _ (Remove record y)) x v ->
170 [ pretty record, P.text "-", variable y, P.text "|"
171 , variable x, P.equals, pretty v
174 Insert record field expr ->
175 P.braces (pretty record <+> P.text "|" <+> variable field <+> P.equals <+> pretty expr)
177 Modify record fields ->
180 (pretty record <+> P.text "|")
182 (commaSep $ map field fields)
184 field (k,v) = variable k <+> P.text "<-" <+> pretty v
188 [ P.cat (zipWith (<+>) (P.lbrace : repeat P.comma) (map field fields))
193 variable name <+> P.equals <+> pretty expr
196 P.text "[glsl| ... |]"
199 P.text ("<port:" ++ name ++ ">")
202 P.text "perform" <+> pretty expr
205collectApps :: Expr ann def var -> [Expr ann def var]
206collectApps annExpr@(Annotation.A _ expr) =
208 App a b -> collectApps a ++ [b]
212collectLambdas :: Expr ann def var -> ([Pattern.Pattern var], Expr ann def var)
213collectLambdas lexpr@(Annotation.A _ expr) =
215 Lambda pattern body ->
216 let (ps, body') = collectLambdas body
217 in (pattern : ps, body')
222prettyParens :: (Pretty def, Pretty var, Var.ToString var) => Expr ann def var -> Doc
223prettyParens (Annotation.A _ expr) =
224 parensIf needed (pretty expr)
234 Data name (_:_) -> not (name == "::" || Help.isTuple name)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list