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
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
23{-| This is a fully general Abstract Syntax Tree (AST) for expressions. It has
24"type holes" that allow us to enrich the AST with additional information as we
25move through the compilation process. The type holes are used to represent:
27 ann: Annotations for arbitrary expressions. Allows you to add information
28 to the AST like position in source code or inferred types.
30 def: Definition style. The source syntax separates type annotations and
31 definitions, but after parsing we check that they are well formed and
34 var: Representation of variables. Starts as strings, but is later enriched
35 with information about what module a variable came from.
38type Expr annotation definition variable =
39 Annotation.Annotated annotation (Expr' annotation definition variable)
42 = Literal Literal.Literal
44 | Range (Expr ann def var) (Expr ann def var)
45 | ExplicitList [Expr ann def var]
46 | Binop var (Expr ann def var) (Expr ann def var)
47 | Lambda (Pattern.Pattern var) (Expr ann def var)
48 | App (Expr ann def var) (Expr ann def var)
49 | MultiIf [(Expr ann def var,Expr ann def var)]
50 | Let [def] (Expr ann def var)
51 | Case (Expr ann def var) [(Pattern.Pattern var, Expr ann def var)]
52 | Data String [Expr ann def var]
53 | Access (Expr ann def var) String
54 | Remove (Expr ann def var) String
55 | Insert (Expr ann def var) String (Expr ann def var)
56 | Modify (Expr ann def var) [(String, Expr ann def var)]
57 | Record [(String, Expr ann def var)]
58 | Markdown String String [Expr ann def var]
59 -- for type checking and code gen only
60 | PortIn String (Type var)
61 | PortOut String (Type var) (Expr ann def var)
62 | GLShader String String Literal.GLShaderTipe
68rawVar :: String -> Expr' ann def Var.Raw
69rawVar x = Var (Var.Raw x)
71localVar :: String -> Expr' ann def Var.Canonical
72localVar x = Var (Var.Canonical Var.Local x)
74tuple :: [Expr ann def var] -> Expr' ann def var
75tuple es = Data ("_Tuple" ++ show (length es)) es
77delist :: Expr ann def var -> [Expr ann def var]
78delist (Annotation.A _ (Data "::" [h,t])) = h : delist t
82saveEnvName = "_save_the_environment!!!"
84dummyLet :: (Pretty def) => [def] -> Expr Annotation.Region def Var.Canonical
86 Annotation.none $ Let defs (Annotation.none $ Var (Var.builtin saveEnvName))
88instance (Pretty def, Pretty var, Var.ToString var) => Pretty (Expr' ann def var) where
91 Literal lit -> pretty lit
95 Range e1 e2 -> P.brackets (pretty e1 <> P.text ".." <> pretty e2)
97 ExplicitList es -> P.brackets (commaCat (map pretty es))
99 Binop op (Annotation.A _ (Literal (Literal.IntNum 0))) e
100 | Var.toString op == "-" ->
101 P.text "-" <> prettyParens e
103 Binop op e1 e2 -> P.sep [ prettyParens e1 <+> P.text op'', prettyParens e2 ]
105 op' = Var.toString op
106 op'' = if Help.isOp op' then op' else "`" ++ op' ++ "`"
108 Lambda p e -> P.text "\\" <> args <+> P.text "->" <+> pretty body
110 (ps,body) = collectLambdas (Annotation.A undefined $ Lambda p e)
111 args = P.sep (map Pattern.prettyParens ps)
113 App _ _ -> P.hang func 2 (P.sep args)
115 func:args = map prettyParens (collectApps (Annotation.A undefined expr))
117 MultiIf branches -> P.text "if" $$ nest 3 (vcat $ map iff branches)
119 iff (b,e) = P.text "|" <+> P.hang (pretty b <+> P.text "->") 2 (pretty e)
122 P.sep [ P.hang (P.text "let") 4 (P.vcat (map pretty defs))
123 , P.text "in" <+> pretty e ]
126 P.hang pexpr 2 (P.vcat (map pretty' pats))
128 pexpr = P.sep [ P.text "case" <+> pretty e, P.text "of" ]
129 pretty' (p,b) = pretty p <+> P.text "->" <+> pretty b
131 Data "::" [hd,tl] -> pretty hd <+> P.text "::" <+> pretty tl
132 Data "[]" [] -> P.text "[]"
134 | Help.isTuple name -> P.parens (commaCat (map pretty es))
135 | otherwise -> P.hang (P.text name) 2 (P.sep (map prettyParens es))
137 Access e x -> prettyParens e <> P.text "." <> variable x
139 Remove e x -> P.braces (pretty e <+> P.text "-" <+> variable x)
141 Insert (Annotation.A _ (Remove e y)) x v ->
142 P.braces $ P.hsep [ pretty e, P.text "-", variable y, P.text "|"
143 , variable x, P.equals, pretty v ]
146 P.braces (pretty e <+> P.text "|" <+> variable x <+> P.equals <+> pretty v)
149 P.braces $ P.hang (pretty e <+> P.text "|")
151 (commaSep $ map field fs)
153 field (k,v) = variable k <+> P.text "<-" <+> pretty v
156 P.braces $ P.nest 2 (commaSep $ map field fs)
158 field (x,e) = variable x <+> P.equals <+> pretty e
160 Markdown _ _ _ -> P.text "[markdown| ... |]"
162 GLShader _ _ _ -> P.text "[glsl| ... |]"
164 PortIn name _ -> P.text $ "<port:" ++ name ++ ">"
166 PortOut _ _ signal -> pretty signal
168collectApps :: Expr ann def var -> [Expr ann def var]
169collectApps annExpr@(Annotation.A _ expr) =
171 App a b -> collectApps a ++ [b]
174collectLambdas :: Expr ann def var -> ([Pattern.Pattern var], Expr ann def var)
175collectLambdas lexpr@(Annotation.A _ expr) =
177 Lambda pattern body ->
178 let (ps, body') = collectLambdas body
179 in (pattern : ps, body')
183prettyParens :: (Pretty def, Pretty var, Var.ToString var) => Expr ann def var -> Doc
184prettyParens (Annotation.A _ expr) = parensIf needed (pretty expr)
194 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