1module Parse.Expression (term, typeAnnotation, definition, expr) where
3import Control.Applicative ((<$>), (<*>))
4import qualified Data.List as List
5import Text.Parsec hiding (newline, spaces)
6import Text.Parsec.Indent (block, withPos)
8import qualified Parse.Binop as Binop
10import qualified Parse.Helpers as Help
11import qualified Parse.Literal as Literal
12import qualified Parse.Pattern as Pattern
13import qualified Parse.Type as Type
15import qualified AST.Expression.General as E
16import qualified AST.Expression.Source as Source
17import qualified AST.Literal as L
18import qualified AST.Pattern as P
19import qualified AST.Variable as Var
20import qualified Reporting.Annotation as A
23-------- Basic Terms --------
25varTerm :: IParser Source.Expr'
27 toVar <$> var <?> "variable"
30toVar :: String -> Source.Expr'
34 E.Literal (L.Boolean True)
37 E.Literal (L.Boolean False)
43accessor :: IParser Source.Expr'
45 do (start, lbl, end) <- located (try (string "." >> rLabel))
53 (ann (E.Access (ann (E.rawVar "_")) lbl))
56negative :: IParser Source.Expr'
58 do (start, nTerm, end) <-
59 located (try (char '-' >> notFollowedBy (char '.' <|> char '-')) >> term)
67 (ann (E.Literal (L.IntNum 0)))
71-------- Complex Terms --------
73listTerm :: IParser Source.Expr'
75 shader' <|> braces (try range <|> E.ExplicitList <$> commaSep expr)
84 let uid = show (sourceLine pos) ++ ":" ++ show (sourceColumn pos)
85 (rawSrc, tipe) <- Help.shader
86 return $ E.GLShader uid (filter (/='\r') rawSrc) tipe
89parensTerm :: IParser Source.Expr
93 , parens (tupleFn <|> parened)
96 lambda start end x body =
97 A.at start end (E.Lambda (A.at start end (P.Var x)) body)
100 A.at start end (E.rawVar x)
103 do (start, op, end) <- located anyOp
105 lambda start end "x" $
106 lambda start end "y" $
108 E.Binop (Var.Raw op) (var start end "x") (var start end "y")
111 do (start, commas, end) <-
112 located (comma >> many (whitespace >> comma))
114 let vars = map (('v':) . show) [ 0 .. length commas + 1 ]
119 (A.at start end (E.tuple (map (var start end) vars)))
123 do (start, expressions, end) <- located (commaSep expr)
129 A.at start end (E.tuple expressions)
132recordTerm :: IParser Source.Expr
135 brackets $ choice [ misc, record ]
139 patterns <- spacePrefix Pattern.term
142 return (label, makeFunction patterns body)
145 E.Record <$> commaSep field
155 E.Remove r <$> rLabel
160 E.Insert r <$> rLabel <*> (padded equals >> expr)
165 E.Modify r <$> commaSep1 change
169 record <- addLocation (E.rawVar <$> rLabel)
170 opt <- padded (optionMaybe (addLocation (remove record)))
173 try (insert e) <|> return e'
175 try (insert record) <|> try (modify record)
178term :: IParser Source.Expr
180 addLocation (choice [ E.Literal <$> Literal.literal, listTerm, accessor, negative ])
181 <|> accessible (addLocation varTerm <|> parensTerm <|> recordTerm)
182 <?> "basic term (4, x, 'c', etc.)"
185-------- Applications --------
187appExpr :: IParser Source.Expr
190 ts <- constrainedSpacePrefix term $ \str ->
191 if null str then notFollowedBy (char '-') else return ()
195 _ -> List.foldl' (\f x -> A.merge f x $ E.App f x) t ts
198-------- Normal Expressions --------
200expr :: IParser Source.Expr
202 addLocation (choice [ ifExpr, letExpr, caseExpr ])
208binaryExpr :: IParser Source.Expr
210 Binop.binops appExpr lastExpr anyOp
212 lastExpr = addLocation (choice [ ifExpr, letExpr, caseExpr ])
216ifExpr :: IParser Source.Expr'
218 do try (reserved "if")
224 padded (reserved "then")
226 whitespace <?> "an 'else' branch"
227 reserved "else" <?> "an 'else' branch"
232 , (A.sameAs elseBranch (E.Literal . L.Boolean $ True), elseBranch)
236 E.MultiIf <$> spaceSep1 iff
239 do string "|" ; whitespace
240 b <- expr ; padded arrow
244lambdaExpr :: IParser Source.Expr
246 do char '\\' <|> char '\x03BB' <?> "anonymous function"
248 args <- spaceSep1 Pattern.term
251 return (makeFunction args body)
254caseExpr :: IParser Source.Expr'
256 do try (reserved "case")
260 E.Case e <$> (with <|> without)
268 brackets (semiSep1 (case_ <?> "cases { x -> ... }"))
271 block (do c <- case_ ; whitespace ; return c)
276letExpr :: IParser Source.Expr'
278 do try (reserved "let")
282 do def <- typeAnnotation <|> definition
285 padded (reserved "in")
291typeAnnotation :: IParser Source.Def
293 addLocation (Source.TypeAnnotation <$> try start <*> Type.expr)
296 do v <- lowVar <|> parens symOp
303definition :: IParser Source.Def
307 do (name:args) <- defStart
310 return . Source.Definition name $ makeFunction args body
313makeFunction :: [P.RawPattern] -> Source.Expr -> Source.Expr
314makeFunction args body@(A.A ann _) =
315 foldr (\arg body' -> A.A ann $ E.Lambda arg body') body args
318defStart :: IParser [P.RawPattern]
321 [ do pattern <- try Pattern.term
322 infics pattern <|> func pattern
323 , do opPattern <- addLocation (P.Var <$> parens symOp)
326 <?> "the definition of a variable (x = ...)"
331 (pattern:) <$> spacePrefix Pattern.term
337 do (start, o:p, end) <- try (whitespace >> located anyOp)
338 p2 <- (whitespace >> Pattern.term)
340 if o == '`' then takeWhile (/='`') p else o:p
341 return [ A.at start end (P.Var opName), p1, p2 ]
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