1{-# OPTIONS_GHC -Wall -fno-warn-unused-do-bind #-}
2{-# LANGUAGE OverloadedStrings #-}
9import Control.Monad (guard)
10import qualified Data.List as List
11import Data.Text (Text)
13import Parse.Primitives
14import qualified Parse.Primitives.Keyword as Keyword
15import qualified Parse.Primitives.Symbol as Symbol
16import qualified Parse.Primitives.Variable as Var
17import qualified Parse.Primitives.Whitespace as W
18import qualified Parse.Literal as Literal
19import qualified Parse.Pattern as Pattern
20import qualified Parse.Type as Type
22import qualified AST.Expression.Source as Src
23import qualified AST.Pattern as P
24import qualified Reporting.Annotation as A
25import qualified Reporting.Error.Syntax as E
26import qualified Reporting.Region as R
33term :: Parser Src.Expr
36 do start <- getPosition
38 [ variable start >>= accessible start
40 , Literal.shader start
42 , record start >>= accessible start
43 , tuple start >>= accessible start
48literal :: R.Position -> Parser Src.Expr
50 do value <- Literal.literal
52 return (A.at start end (Src.Literal value))
55accessor :: R.Position -> Parser Src.Expr
60 return (A.at start end (Src.Accessor field))
63variable :: R.Position -> Parser Src.Expr
65 do (maybePrefix, name) <- Var.foreignAlpha
67 return (A.at start end (Src.Var maybePrefix name))
70accessible :: R.Position -> Src.Expr -> Parser Src.Expr
71accessible start expr =
76 let newExpr = A.at start end (Src.Access expr field)
77 accessible start newExpr
86list :: R.Position -> Parser Src.Expr
89 inContext start E.ExprList $
92 [ do (entry, _, pos) <- expression
94 listHelp start [entry]
95 , do Symbol.rightSquare
97 return (A.at start end (Src.List []))
101listHelp :: R.Position -> [Src.Expr] -> Parser Src.Expr
102listHelp start entries =
106 (entry, _, pos) <- expression
108 listHelp start (entry:entries)
109 , do Symbol.rightSquare
111 return (A.at start end (Src.List (reverse entries)))
119tuple :: R.Position -> Parser Src.Expr
124 inContext start E.ExprTuple $ oneOf $
125 [ do noSpace pos spos
126 try (Symbol.minus >> Symbol.rightParen)
128 return $ A.at start end (Src.Op "-")
131 (entry, _, spos2) <- expression
133 tupleHelp start entry []
135 , do noSpace pos spos
139 return $ A.at start end (Src.Op op)
141 , do noSpace pos spos
144 return (A.at start end Src.Unit)
149tupleHelp :: R.Position -> Src.Expr -> [Src.Expr] -> Parser Src.Expr
150tupleHelp start firstExpr revExprs =
154 (entry, _, pos) <- expression
156 tupleHelp start firstExpr (entry : revExprs)
157 , do Symbol.rightParen
159 case reverse revExprs of
163 secondExpr : others ->
164 return (A.at start end (Src.Tuple firstExpr secondExpr others))
172record :: R.Position -> Parser Src.Expr
175 inContext start E.ExprRecord $
178 [ do Symbol.rightCurly
180 return (A.at start end (Src.Record []))
181 , do starter <- addLocation Var.lower
186 firstField <- chompField
187 fields <- chompFields [firstField]
189 return (A.at start end (Src.Update starter fields))
192 (value, _, nextPos) <- expression
194 fields <- chompFields [(starter, value)]
196 return (A.at start end (Src.Record fields))
201type Field = ( A.Located Text, Src.Expr )
204chompFields :: [Field] -> Parser [Field]
210 chompFields (f : fields)
211 , do Symbol.rightCurly
212 return (reverse fields)
216chompField :: Parser Field
218 do key <- addLocation Var.lower
222 (value, _, pos) <- expression
235expression :: ExprParser
238 do start <- getPosition
244 , do expr <- possiblyNegativeTerm start
246 space <- W.whitespace
247 exprHelp start (State [] expr [] end space)
253 { _ops :: ![(Src.Expr, A.Located Text)]
255 , _args :: ![Src.Expr]
256 , _end :: !R.Position
261exprHelp :: R.Position -> State -> ExprParser
262exprHelp start (State ops expr args end pos) =
268 newEnd <- getPosition
269 newPos <- W.whitespace
270 exprHelp start (State ops expr (arg:args) newEnd newPos)
274 opStart <- getPosition
275 opName <- Symbol.binop
277 let op = A.at opStart opEnd opName
279 hint (E.AfterOpExpr opName) (checkSpace spos)
280 newStart <- getPosition
281 hint (E.AfterOpExpr opName) $ oneOf $
283 do guard ("-" == opName && end /= opStart && opEnd == newStart)
285 newEnd <- getPosition
286 newPos <- W.whitespace
287 let arg = A.at opStart newEnd (Src.Negate rawTerm)
288 exprHelp start (State ops expr (arg:args) newEnd newPos)
291 do newExpr <- possiblyNegativeTerm newStart
292 newEnd <- getPosition
293 newPos <- W.whitespace
294 let newOps = (toCall expr args, op) : ops
295 exprHelp start (State newOps newExpr [] newEnd newPos)
298 do (newLast, newEnd, newPos) <-
305 let newOps = (toCall expr args, op) : ops
306 let finalExpr = A.at start newEnd (Src.Binops (reverse newOps) newLast)
307 return ( finalExpr, newEnd, newPos )
311 let finalExpr = toCall expr args in
314 return ( finalExpr, end, pos )
317 return ( A.at start end (Src.Binops (reverse ops) finalExpr), end, pos )
321possiblyNegativeTerm :: R.Position -> Parser Src.Expr
322possiblyNegativeTerm start =
327 return (A.at start end (Src.Negate expr))
332toCall :: Src.Expr -> [Src.Expr] -> Src.Expr
339 A.merge func lastArg (Src.Call func (reverse revArgs))
346if_ :: R.Position -> ExprParser
349 inContext start E.ExprIf $ ifHelp start []
352ifHelp :: R.Position -> [(Src.Expr, Src.Expr)] -> ExprParser
353ifHelp start branches =
355 (condition, _, condPos) <- expression
359 (thenBranch, _, thenPos) <- expression
360 hint E.ElseBranch $ checkSpace thenPos
361 hint E.ElseBranch $ Keyword.else_
363 let newBranches = (condition, thenBranch) : branches
366 ifHelp start newBranches
367 , do (elseBranch, elseEnd, elseSpace) <- expression
368 let ifExpr = A.at start elseEnd (Src.If (reverse newBranches) elseBranch)
369 return ( ifExpr, elseEnd, elseSpace )
377function :: R.Position -> ExprParser
380 inContext start E.ExprFunc $
384 revArgs <- gatherArgs [arg]
386 (body, end, space) <- expression
387 let func = List.foldl' (\e x -> A.at start end (Src.Lambda x e)) body revArgs
388 return ( func, end, space )
391gatherArgs :: [P.Raw] -> Parser [P.Raw]
394 [ do arg <- Pattern.term
396 gatherArgs (arg:args)
397 , do Symbol.rightArrow
406case_ :: R.Position -> ExprParser
409 inContext start E.ExprCase $
411 (switcher, _, switcherPos) <- expression
412 checkSpace switcherPos
415 oldIndent <- getIndent
418 (firstBranch, firstEnd, firstPos) <- branchHelp
419 (branches, end, pos) <- caseHelp [firstBranch] firstEnd firstPos
422 ( A.at start end (Src.Case switcher branches)
428branchHelp :: SParser (P.Raw, Src.Expr)
430 do (pattern, patternPos) <- Pattern.expression
431 checkSpace patternPos
434 (branchExpr, end, pos) <- expression
435 return ( (pattern, branchExpr), end, pos )
438caseHelp :: [(P.Raw, Src.Expr)] -> R.Position -> SPos -> SParser [(P.Raw, Src.Expr)]
439caseHelp branches end pos =
441 [ do checkAligned pos
442 (branch, newEnd, newPos) <- branchHelp
443 caseHelp (branch:branches) newEnd newPos
444 , return ( reverse branches, end, pos )
452let_ :: R.Position -> ExprParser
454 do oldIndent <- getIndent
457 pushContext start E.ExprLet
462 (def, end, space) <- letDef
463 letHelp start oldIndent [def] end space
466letHelp :: R.Position -> Int -> [A.Located Src.Def] -> R.Position -> SPos -> ExprParser
467letHelp start oldIndent revDefs end pos =
469 [ do checkAligned pos
470 (def, newEnd, newPos) <- letDef
471 letHelp start oldIndent (def:revDefs) newEnd newPos
473 , do setIndent oldIndent
478 (body, newEnd, newPos) <- expression
479 let letExpr = A.at start end (Src.Let (reverse revDefs) body)
480 return ( letExpr, newEnd, newPos )
488letDef :: SParser (A.Located Src.Def)
500definition :: SParser (A.Located Src.Def)
502 do start <- getPosition
507 inContext start (E.Annotation name) $
509 (tipe, end, space) <- Type.expression
510 return ( A.at start end (Src.Annotate name tipe), end, space )
511 , inContext start (E.Definition name) $
512 definitionHelp start name []
516definitionHelp :: R.Position -> Text -> [P.Raw] -> SParser (A.Located Src.Def)
517definitionHelp start name revArgs =
519 [ do arg <- hint E.Arg Pattern.term
521 definitionHelp start name (arg : revArgs)
524 (body, end, space) <- expression
525 let def = A.at start end (Src.Define name (reverse revArgs) body)
526 return ( def, end, space )
534destructure :: SParser (A.Located Src.Def)
536 do start <- getPosition
537 pattern <- Pattern.term
541 (expr, end, space) <- expression
542 return ( A.at start end (Src.Destruct pattern expr), end, space )
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