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
11import Text.PrettyPrint as P
13import qualified AST.Helpers as Help
14import qualified AST.Literal as Literal
15import qualified AST.Pattern as Pattern
16import qualified AST.Type as Type
17import qualified AST.Variable as Var
18import qualified Reporting.Annotation as A
19import qualified Reporting.Crash as Crash
20import qualified Reporting.PrettyPrint as P
25{-| This is a fully general Abstract Syntax Tree (AST) for expressions. It has
26"type holes" that allow us to enrich the AST with additional information as we
27move through the compilation process. The type holes are used to represent:
29 ann: Annotations for arbitrary expressions. Allows you to add information
30 to the AST like position in source code or inferred types.
32 def: Definition style. The source syntax separates type annotations and
33 definitions, but after parsing we check that they are well formed and
36 var: Representation of variables. Starts as strings, but is later enriched
37 with information about what module a variable came from.
40type Expr annotation definition variable tipe =
41 A.Annotated annotation (Expr' annotation definition variable tipe)
44data Expr' ann def var typ
45 = Literal Literal.Literal
47 | Range (Expr ann def var typ) (Expr ann def var typ)
48 | ExplicitList [Expr ann def var typ]
49 | Binop var (Expr ann def var typ) (Expr ann def var typ)
50 | Lambda (Pattern.Pattern ann var) (Expr ann def var typ)
51 | App (Expr ann def var typ) (Expr ann def var typ)
52 | MultiIf [(Expr ann def var typ, Expr ann def var typ)] (Expr ann def var typ)
53 | Let [def] (Expr ann def var typ)
54 | Case (Expr ann def var typ) [(Pattern.Pattern ann var, Expr ann def var typ)]
55 | Data String [Expr ann def var typ]
56 | Access (Expr ann def var typ) String
57 | Remove (Expr ann def var typ) String
58 | Insert (Expr ann def var typ) String (Expr ann def var typ)
59 | Modify (Expr ann def var typ) [(String, Expr ann def var typ)]
60 | Record [(String, Expr ann def var typ)]
61 -- for type checking and code gen only
62 | Port (PortImpl (Expr ann def var typ) typ)
63 | GLShader String String Literal.GLShaderTipe
70data PortImpl expr tipe
71 = In String (Type.Port tipe)
72 | Out String expr (Type.Port tipe)
73 | Task String expr (Type.Port tipe)
77portName :: PortImpl expr tipe -> String
87rawVar :: String -> Expr' ann def Var.Raw typ
92localVar :: String -> Expr' ann def Var.Canonical typ
94 Var (Var.Canonical Var.Local x)
97tuple :: [Expr ann def var typ] -> Expr' ann def var typ
99 Data ("_Tuple" ++ show (length expressions)) expressions
104 "_save_the_environment!!!"
107dummyLet :: (P.Pretty def) => [def] -> Expr ann def Var.Canonical typ
110 A.A undefined (Var (Var.builtin saveEnvName))
112 A.A undefined (Let defs body)
117instance (P.Pretty def, P.Pretty var, Var.ToString var) => P.Pretty (Expr' ann def var typ) where
118 pretty dealiaser needsParens expression =
121 P.pretty dealiaser needsParens literal
124 P.pretty dealiaser needsParens x
126 Range lowExpr highExpr ->
128 P.pretty dealiaser False lowExpr
130 <> P.pretty dealiaser False highExpr
132 ExplicitList elements ->
133 P.brackets (P.commaCat (map (P.pretty dealiaser False) elements))
135 Binop op (A.A _ (Literal (Literal.IntNum 0))) expr
136 | Var.toString op == "-" ->
137 P.text "-" <> P.pretty dealiaser True expr
139 Binop op leftExpr rightExpr ->
140 P.parensIf needsParens $
142 (P.pretty dealiaser True leftExpr)
144 (P.text op'' <+> P.pretty dealiaser True rightExpr)
146 op' = Var.toString op
147 op'' = if Help.isOp op' then op' else "`" ++ op' ++ "`"
149 Lambda pattern expr ->
150 P.parensIf needsParens $
151 P.text "\\" <> args <+> P.text "->" <+> P.pretty dealiaser False body
157 P.sep (map (P.pretty dealiaser True) (pattern : patterns))
160 P.parensIf needsParens $
161 P.hang func 2 (P.sep args)
164 map (P.pretty dealiaser True) (collectApps expr ++ [arg])
166 MultiIf [(condition, thenBranch)] elseBranch ->
167 P.parensIf needsParens $ P.sep $
168 [ P.text "if" <+> P.pretty dealiaser False condition <+> P.text "then"
169 , P.nest 4 (P.pretty dealiaser False thenBranch)
171 , P.nest 4 (P.pretty dealiaser False elseBranch)
174 MultiIf branches finally ->
175 P.parensIf needsParens $
176 P.text "if" $$ nest 3 (vcat $ map iff branches ++ [final])
178 iff (condition, branch) =
181 (P.pretty dealiaser False condition <+> P.text "->")
183 (P.pretty dealiaser False branch)
186 P.hang (P.text "| True -> ") 2 (P.pretty dealiaser False finally)
189 P.parensIf needsParens $
194 (P.vcat (map (P.pretty dealiaser False) defs))
195 , P.text "in" <+> P.pretty dealiaser False body
198 Case expr branches ->
199 P.parensIf needsParens $
200 P.hang pexpr 2 (P.vcat (map pretty' branches))
203 P.text "case" <+> P.pretty dealiaser False expr <+> P.text "of"
205 pretty' (pattern, branch) =
206 P.pretty dealiaser False pattern
208 <+> P.pretty dealiaser False branch
211 P.parensIf needsParens $
212 P.pretty dealiaser True hd <+> P.text "::" <+> P.pretty dealiaser True tl
220 P.parens (P.commaCat (map (P.pretty dealiaser False) exprs))
222 P.parensIf (needsParens && not (null exprs)) $
226 (P.sep (map (P.pretty dealiaser True) exprs))
228 Access record field ->
229 P.pretty dealiaser True record <> P.text "." <> P.text field
231 Remove record field ->
232 P.braces (P.pretty dealiaser False record <+> P.text "-" <+> P.text field)
234 Insert (A.A _ (Remove record oldField)) newField expr ->
237 [ P.pretty dealiaser False record
243 , P.pretty dealiaser False expr
246 Insert record field expr ->
248 P.pretty dealiaser False record
252 <+> P.pretty dealiaser False expr
254 Modify record fields ->
257 (P.pretty dealiaser False record <+> P.text "|")
259 (P.commaSep $ map prettyField fields)
261 prettyField (field, expr) =
262 P.text field <+> P.text "<-" <+> P.pretty dealiaser False expr
266 [ P.cat (zipWith (<+>) (P.lbrace : repeat P.comma) (map field fields))
271 P.text name <+> P.equals <+> P.pretty dealiaser False expr
274 P.text "[glsl| ... |]"
277 P.pretty dealiaser needsParens portImpl
280 P.text ("<crash:" ++ Crash.summary details ++ ">")
283instance P.Pretty (PortImpl expr tipe) where
285 P.text ("<port:" ++ portName impl ++ ">")
288collectApps :: Expr ann def var typ -> [Expr ann def var typ]
289collectApps annExpr@(A.A _ expr) =
291 App a b -> collectApps a ++ [b]
296 :: Expr ann def var typ
297 -> ([Pattern.Pattern ann var], Expr ann def var typ)
298collectLambdas lexpr@(A.A _ expr) =
300 Lambda pattern body ->
302 (ps, body') = collectLambdas body
304 (pattern : ps, body')
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