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
14import qualified AST.Annotation as Annotation
15import qualified AST.Helpers as Help
16import qualified AST.Literal as Literal
17import qualified AST.Pattern as Pattern
18import qualified AST.Type as Type
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 (PortImpl (Expr ann def var) var)
62 | GLShader String String Literal.GLShaderTipe
69 = In String (Type.PortType var)
70 | Out String expr (Type.PortType var)
71 | Task String expr (Type.PortType var)
75portName :: PortImpl expr var -> String
85rawVar :: String -> Expr' ann def Var.Raw
90localVar :: String -> Expr' ann def Var.Canonical
92 Var (Var.Canonical Var.Local x)
95tuple :: [Expr ann def var] -> Expr' ann def var
97 Data ("_Tuple" ++ show (length expressions)) expressions
102 "_save_the_environment!!!"
105dummyLet :: (Pretty def) => [def] -> Expr Annotation.Region def Var.Canonical
107 Annotation.none $ Let defs (Annotation.none $ Var (Var.builtin saveEnvName))
110instance (Pretty def, Pretty var, Var.ToString var) => Pretty (Expr' ann def var) where
119 Range lowExpr highExpr ->
120 P.brackets (pretty lowExpr <> P.text ".." <> pretty highExpr)
122 ExplicitList elements ->
123 P.brackets (commaCat (map pretty elements))
125 Binop op (Annotation.A _ (Literal (Literal.IntNum 0))) expr
126 | Var.toString op == "-" ->
127 P.text "-" <> prettyParens expr
129 Binop op leftExpr rightExpr ->
130 P.hang (prettyParens leftExpr) 2 (P.text op'' <+> prettyParens rightExpr)
132 op' = Var.toString op
133 op'' = if Help.isOp op' then op' else "`" ++ op' ++ "`"
135 Lambda pattern expr ->
136 P.text "\\" <> args <+> P.text "->" <+> pretty body
138 (patterns, body) = collectLambdas expr
139 args = P.sep (map Pattern.prettyParens (pattern : patterns))
142 P.hang func 2 (P.sep args)
145 map prettyParens (collectApps expr ++ [arg])
148 P.text "if" $$ nest 3 (vcat $ map iff branches)
150 iff (b,e) = P.text "|" <+> P.hang (pretty b <+> P.text "->") 2 (pretty e)
154 [ P.hang (P.text "let") 4 (P.vcat (map pretty defs))
155 , P.text "in" <+> pretty body
158 Case expr branches ->
159 P.hang pexpr 2 (P.vcat (map pretty' branches))
161 pexpr = P.sep [ P.text "case" <+> pretty expr, P.text "of" ]
162 pretty' (pattern, branch) =
163 pretty pattern <+> P.text "->" <+> pretty branch
166 pretty hd <+> P.text "::" <+> pretty tl
172 | Help.isTuple name ->
173 P.parens (commaCat (map pretty exprs))
175 P.hang (P.text name) 2 (P.sep (map prettyParens exprs))
177 Access record field ->
178 prettyParens record <> P.text "." <> variable field
180 Remove record field ->
181 P.braces (pretty record <+> P.text "-" <+> variable field)
183 Insert (Annotation.A _ (Remove record y)) x v ->
186 [ pretty record, P.text "-", variable y, P.text "|"
187 , variable x, P.equals, pretty v
190 Insert record field expr ->
191 P.braces (pretty record <+> P.text "|" <+> variable field <+> P.equals <+> pretty expr)
193 Modify record fields ->
196 (pretty record <+> P.text "|")
198 (commaSep $ map field fields)
200 field (k,v) = variable k <+> P.text "<-" <+> pretty v
204 [ P.cat (zipWith (<+>) (P.lbrace : repeat P.comma) (map field fields))
209 variable name <+> P.equals <+> pretty expr
212 P.text "[glsl| ... |]"
218instance (Pretty expr, Pretty var) => Pretty (PortImpl expr var) where
220 P.text ("<port:" ++ portName impl ++ ">")
223collectApps :: Expr ann def var -> [Expr ann def var]
224collectApps annExpr@(Annotation.A _ expr) =
226 App a b -> collectApps a ++ [b]
230collectLambdas :: Expr ann def var -> ([Pattern.Pattern var], Expr ann def var)
231collectLambdas lexpr@(Annotation.A _ expr) =
233 Lambda pattern body ->
234 let (ps, body') = collectLambdas body
235 in (pattern : ps, body')
240prettyParens :: (Pretty def, Pretty var, Var.ToString var) => Expr ann def var -> Doc
241prettyParens (Annotation.A _ expr) =
242 parensIf needed (pretty expr)
252 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