1module Parse.Expression (term, annotation, definition, expr, def) 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.Type as T
19import qualified AST.Variable as Var
20import qualified Reporting.Annotation as A
24-------- Basic Terms --------
27varTerm :: IParser Source.Expr'
32toVar :: String -> Source.Expr'
36 E.Literal (L.Boolean True)
39 E.Literal (L.Boolean False)
45accessor :: IParser Source.Expr'
47 do (start, lbl, end) <- located (try (string "." >> rLabel))
55 (ann (E.Access (ann (E.rawVar "_")) lbl))
58negative :: IParser Source.Expr'
60 do (start, nTerm, end) <-
63 notFollowedBy (char '.' <|> char '-')
72 (ann (E.Literal (L.IntNum 0)))
77-------- Complex Terms --------
80listTerm :: IParser Source.Expr'
82 shader' <|> braces (try range <|> E.ExplicitList <$> commaSep expr)
91 let uid = show (sourceLine pos) ++ ":" ++ show (sourceColumn pos)
92 (rawSrc, tipe) <- Help.shader
93 return $ E.GLShader uid (filter (/='\r') rawSrc) tipe
96parensTerm :: IParser Source.Expr
99 mkFunc args realBody start end =
101 (\arg body -> A.at start end (E.Lambda (A.at start end (P.Var arg)) body))
102 (A.at start end (realBody (A.at start end . E.rawVar)))
106 mkFunc ["x","y"] (\var -> E.Binop (Var.Raw op) (var "x") (var "y"))
109 do commas <- many1 comma
110 let args = map (('v':) . show) [ 0 .. length commas ]
111 return $ mkFunc args (\var -> E.tuple (map var args))
114 do expressions <- padded (commaSep expr)
115 return $ \start end ->
120 A.at start end (E.tuple expressions)
122 do (start, mkExpr, end) <-
124 [ mkBinop <$> try (parens symOp)
125 , parens (tupleFn <|> parenedExpr)
127 return (mkExpr start end)
130recordTerm :: IParser Source.Expr
132 addLocation $ brackets $ choice $
133 [ do starter <- try (addLocation rLabel)
139 , return (E.Record [])
142 update (A.A ann starter) =
145 fields <- commaSep1 field
146 return (E.Update (A.A ann (E.rawVar starter)) fields)
148 literal (A.A _ starter) =
156 fields <- commaSep field
157 return (E.Record ((starter, value) : fields))
158 , return (E.Record [(starter, value)])
168term :: IParser Source.Expr
170 addLocation (choice [ E.Literal <$> Literal.literal, listTerm, accessor, negative ])
171 <|> accessible (addLocation varTerm <|> parensTerm <|> recordTerm)
176-------- Applications --------
179appExpr :: IParser Source.Expr
181 expecting "an expression" $
183 ts <- constrainedSpacePrefix term $ \str ->
184 if null str then notFollowedBy (char '-') else return ()
188 _ -> List.foldl' (\f x -> A.merge f x $ E.App f x) t ts
192-------- 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 start <- getMyPosition
238 char '\\' <|> char '\x03BB' <?> "an anonymous function"
240 args <- spaceSep1 Pattern.term
244 return (foldr (\a b -> A.at start end $ E.Lambda a b) body args)
247caseExpr :: IParser Source.Expr'
249 do try (reserved "case")
254 do firstBranch <- branch
257 try (whitespace >> Indent.checkIndent)
259 return $ E.Case exp (firstBranch : branches)
271letExpr :: IParser Source.Expr'
273 do try (reserved "let")
276 Indent.block (def <* whitespace)
283def :: IParser Source.Def
286 [ annotation Source.Annotation
287 , definition Source.Definition
295annotation :: (String -> T.Raw -> a) -> IParser (A.Located a)
299 do v <- lowVar <|> parens symOp
303 addLocation (creator <$> try start <*> Type.expr)
310definition :: (P.Raw -> Source.Expr -> a) -> IParser (A.Located a)
314 do (name, args) <- defStart
317 return . creator name $ makeFunction args body
320makeFunction :: [P.Raw] -> Source.Expr -> Source.Expr
321makeFunction args body@(A.A ann _) =
322 foldr (\arg body' -> A.A ann $ E.Lambda arg body') body args
325defStart :: IParser (P.Raw, [P.Raw])
327 expecting "the definition of a value (x = ...)" $
328 do starter <- try Pattern.term <|> addLocation (P.Var <$> parens symOp)
329 args <- spacePrefix Pattern.term
330 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