1module Parse.Expression (term, typeAnnotation, definition, expr) where
3import qualified Data.List as List
4import Text.Parsec hiding (newline, spaces)
5import qualified Text.Parsec.Indent as Indent
7import qualified Parse.Binop as Binop
9import qualified Parse.Helpers as Help
10import qualified Parse.Literal as Literal
11import qualified Parse.Pattern as Pattern
12import qualified Parse.Type as Type
14import qualified AST.Expression.General as E
15import qualified AST.Expression.Source as Source
16import qualified AST.Literal as L
17import qualified AST.Pattern as P
18import qualified AST.Variable as Var
19import qualified Reporting.Annotation as A
22-------- Basic Terms --------
24varTerm :: IParser Source.Expr'
29toVar :: String -> Source.Expr'
33 E.Literal (L.Boolean True)
36 E.Literal (L.Boolean False)
42accessor :: IParser Source.Expr'
44 do (start, lbl, end) <- located (try (string "." >> rLabel))
52 (ann (E.Access (ann (E.rawVar "_")) lbl))
55negative :: IParser Source.Expr'
57 do (start, nTerm, end) <-
60 notFollowedBy (char '.' <|> char '-')
69 (ann (E.Literal (L.IntNum 0)))
73-------- Complex Terms --------
75listTerm :: IParser Source.Expr'
77 shader' <|> braces (try range <|> E.ExplicitList <$> commaSep expr)
86 let uid = show (sourceLine pos) ++ ":" ++ show (sourceColumn pos)
87 (rawSrc, tipe) <- Help.shader
88 return $ E.GLShader uid (filter (/='\r') rawSrc) tipe
91parensTerm :: IParser Source.Expr
95 , parens (tupleFn <|> parened)
98 lambda start end x body =
99 A.at start end (E.Lambda (A.at start end (P.Var x)) body)
102 A.at start end (E.rawVar x)
105 do (start, op, end) <- located symOp
107 lambda start end "x" $
108 lambda start end "y" $
110 E.Binop (Var.Raw op) (var start end "x") (var start end "y")
113 do (start, commas, end) <-
114 located (comma >> many (whitespace >> comma))
116 let vars = map (('v':) . show) [ 0 .. length commas + 1 ]
121 (A.at start end (E.tuple (map (var start end) vars)))
125 do (start, expressions, end) <- located (commaSep expr)
131 A.at start end (E.tuple expressions)
134recordTerm :: IParser Source.Expr
136 addLocation $ brackets $ choice $
137 [ do starter <- try (addLocation rLabel)
143 , return (E.Record [])
146 update (A.A ann starter) =
149 fields <- commaSep1 field
150 return (E.Update (A.A ann (E.rawVar starter)) fields)
152 literal (A.A _ starter) =
160 fields <- commaSep field
161 return (E.Record ((starter, value) : fields))
162 , return (E.Record [(starter, value)])
172term :: IParser Source.Expr
174 addLocation (choice [ E.Literal <$> Literal.literal, listTerm, accessor, negative ])
175 <|> accessible (addLocation varTerm <|> parensTerm <|> recordTerm)
179-------- Applications --------
181appExpr :: IParser Source.Expr
183 expecting "an expression" $
185 ts <- constrainedSpacePrefix term $ \str ->
186 if null str then notFollowedBy (char '-') else return ()
190 _ -> List.foldl' (\f x -> A.merge f x $ E.App f x) t ts
193-------- Normal Expressions --------
195expr :: IParser Source.Expr
197 addLocation (choice [ letExpr, caseExpr, ifExpr ])
203binaryExpr :: IParser Source.Expr
205 Binop.binops appExpr lastExpr anyOp
208 addLocation (choice [ letExpr, caseExpr, ifExpr ])
213ifExpr :: IParser Source.Expr'
218ifHelp :: [(Source.Expr, Source.Expr)] -> IParser Source.Expr'
220 do try (reserved "if")
223 padded (reserved "then")
225 whitespace <?> "an 'else' branch"
226 reserved "else" <?> "an 'else' branch"
228 let newBranches = (condition, thenBranch) : branches
231 , E.If (reverse newBranches) <$> expr
235lambdaExpr :: IParser Source.Expr
237 do char '\\' <|> char '\x03BB' <?> "an anonymous function"
239 args <- spaceSep1 Pattern.term
242 return (makeFunction args body)
245caseExpr :: IParser Source.Expr'
247 do try (reserved "case")
252 do firstBranch <- branch
255 try (whitespace >> Indent.checkIndent)
257 return $ E.Case exp (firstBranch : branches)
267letExpr :: IParser Source.Expr'
269 do try (reserved "let")
273 do def <- typeAnnotation <|> definition
276 padded (reserved "in")
282typeAnnotation :: IParser Source.Def
284 addLocation (Source.TypeAnnotation <$> try start <*> Type.expr)
287 do v <- lowVar <|> parens symOp
294definition :: IParser Source.Def
298 do (name, args) <- defStart
301 return . Source.Definition name $ makeFunction args body
304makeFunction :: [P.RawPattern] -> Source.Expr -> Source.Expr
305makeFunction args body@(A.A ann _) =
306 foldr (\arg body' -> A.A ann $ E.Lambda arg body') body args
309defStart :: IParser (P.RawPattern, [P.RawPattern])
311 expecting "the definition of a value (x = ...)" $
312 do starter <- try Pattern.term <|> addLocation (P.Var <$> parens symOp)
313 args <- spacePrefix Pattern.term
314 return (starter, args)
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