@@ -1,333 +1,499 @@
1−module Parse.Expression (term, expr, def) where
1+{-# OPTIONS_GHC -Wall -fno-warn-unused-do-bind #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+module Parse.Expression (term, expression, definition) where
24
5+import Control.Monad (guard)
36import qualified Data.List as List
4−import Text.Parsec hiding (newline, spaces)
7+import qualified Data.Text as Text
8+import Data.Text (Text)
59
6−import qualified Parse.Binop as Binop
710import Parse.Helpers
8−import qualified Parse.Helpers as Help
911import qualified Parse.Literal as Literal
1012import qualified Parse.Pattern as Pattern
1113import qualified Parse.Type as Type
1214
1315import qualified AST.Expression.Source as Src
14−import qualified AST.Literal as L
1516import qualified AST.Pattern as P
1617import qualified Reporting.Annotation as A
18+import qualified Reporting.Region as R
1719
1820
1921
20−-------- Basic Terms --------
22+-- TERMS
2123
2224
23−varTerm :: IParser Src.RawExpr'
24−varTerm =
25− toVar <$> Help.var
25+term :: Parser Src.RawExpr
26+term =
27+ do start <- getPosition
28+ oneOf
29+ [ do literal <- Literal.literal
30+ end <- getPosition
31+ return (A.at start end (Src.Literal literal))
32+ , list start
33+ , tuple start
34+ , record start
35+ , do var <- qualifiedVar
36+ end <- getPosition
37+ return (A.at start end (Src.var var))
38+ ]
2639
2740
28−toVar :: String -> Src.RawExpr'
29−toVar v =
30− case v of
31− "True" ->
32− Src.Literal (L.Boolean True)
3341
34− "False" ->
35− Src.Literal (L.Boolean False)
42+-- LISTS
3643
37− _ ->
38− Src.var v
3944
45+list :: R.Position -> Parser Src.RawExpr
46+list start =
47+ do leftSquare
48+ spaces
49+ oneOf
50+ [ do (entry, _, space) <- expression
51+ checkSpaces space
52+ listHelp start [entry]
53+ , do rightSquare
54+ end <- getPosition
55+ return (A.at start end (Src.List []))
56+ ]
4057
41−accessor :: IParser Src.RawExpr'
42−accessor =
43− do start <- getMyPosition
44− label <- try (char '.' >> rLabel)
45− end <- getMyPosition
4658
47− let ann value =
48− A.at start end value
59+listHelp :: R.Position -> [Src.RawExpr] -> Parser Src.RawExpr
60+listHelp start entries =
61+ oneOf
62+ [ do comma
63+ spaces
64+ (entry, _, space) <- expression
65+ checkSpaces space
66+ listHelp start (entry:entries)
67+ , do rightSquare
68+ end <- getPosition
69+ return (A.at start end (Src.List (reverse entries)))
70+ ]
4971
50− return $
51− Src.Lambda
52− (ann (P.Var "_"))
53− (ann (Src.Access (ann (Src.var "_")) label))
5472
5573
56−negative :: IParser Src.RawExpr'
57−negative =
58− try $
59− do (A.A region _) <- addLocation (char '-')
60− notFollowedBy (char '.' <|> char '-')
61− negativeTerm <- term
74+-- TUPLES
6275
63− let zero = A.A region (Src.Literal (L.IntNum 0))
64− let minus = A.A region "-"
6576
66− return $ Src.Binop [(zero, minus)] negativeTerm
77+tuple :: R.Position -> Parser Src.RawExpr
78+tuple start =
79+ do leftParen
80+ oneOf
81+ [ do op <- infixOp
82+ rightParen
83+ end <- getPosition
84+ let x = A.at start end (Src.var "x")
85+ let y = A.at start end (Src.var "y")
86+ return $ mkLambda start end "x" $ mkLambda start end "y" $
87+ A.at start end (Src.Binop [(x, A.at start end op)] y)
6788
89+ , do comma
90+ arity <- chompCommas 2
91+ rightParen
92+ end <- getPosition
93+ let args = map (\n -> Text.pack ("v" ++ show n)) [ 1 .. arity ]
94+ return (A.at start end (error "TODO" args))
6895
96+ , do spaces
97+ (entry, _, space) <- expression
98+ checkSpaces space
99+ tupleHelp start [entry]
100+ ]
69101
70102
71−-------- Complex Terms --------
103+mkLambda :: R.Position -> R.Position -> Text -> Src.RawExpr -> Src.RawExpr
104+mkLambda start end arg body =
105+ A.at start end (Src.Lambda (A.at start end (P.Var arg)) body)
72106
73107
74−listTerm :: IParser Src.RawExpr'
75−listTerm =
76− choice
77− [ do pos <- getPosition
78− let uid = show (sourceLine pos) ++ ":" ++ show (sourceColumn pos)
79− (rawSrc, tipe) <- Literal.shader
80− return $ Src.GLShader uid (filter (/='\r') rawSrc) tipe
81− , braces (Src.List <$> commaSep expr)
108+chompCommas :: Int -> Parser Int
109+chompCommas n =
110+ oneOf
111+ [ comma >> chompCommas (n + 1)
112+ , return n
82113 ]
83114
84115
85−parensTerm :: IParser Src.RawExpr
86−parensTerm =
87− let
88− mkFunc args realBody start end =
89− foldr
90− (\arg body -> A.at start end (Src.Lambda (A.at start end (P.Var arg)) body))
91− (A.at start end (realBody (A.at start end . Src.var)))
92− args
93−
94− mkBinop op =
95− mkFunc ["x","y"] $ \var -> Src.Binop [(var "x", op)] (var "y")
96−
97− tupleFn =
98− do commas <- many1 comma
99− let args = map (('v':) . show) [ 0 .. length commas ]
100− return $ mkFunc args (\var -> Src.tuple (map var args))
101−
102− parenedExpr =
103− do expressions <- padded (commaSep expr)
104− return $ \start end ->
105− case expressions of
106− [expression] ->
107− expression
108− _ ->
109− A.at start end (Src.tuple expressions)
110− in
111− do char '('
112− start <- getMyPosition
113− mkExpr <-
114− choice
115− [ mkBinop <$> try (addLocation Binop.infixOp)
116− , tupleFn
117− , parenedExpr
118− ]
119− end <- getMyPosition
120− char ')'
121− return (mkExpr start end)
122−
123−
124−recordTerm :: IParser Src.RawExpr
125−recordTerm =
126− addLocation $ brackets $ choice $
127− [ do starter <- try (addLocation rLabel)
128− whitespace
129− choice
130− [ update starter
131− , literal starter
132− ]
133− , return (Src.Record [])
116+tupleHelp :: R.Position -> [Src.RawExpr] -> Parser Src.RawExpr
117+tupleHelp start entries =
118+ oneOf
119+ [ do comma
120+ spaces
121+ (entry, _, space) <- expression
122+ checkSpaces space
123+ tupleHelp start (entry:entries)
124+ , do rightParen
125+ end <- getPosition
126+ case entries of
127+ [entry] ->
128+ return entry
129+
130+ _ ->
131+ return (A.at start end (Src.tuple (reverse entries)))
134132 ]
135− where
136− update (A.A ann starter) =
137− do try (string "|")
138− whitespace
139− fields <- commaSep1 field
140− return (Src.Update (A.A ann (Src.var starter)) fields)
141−
142− literal key =
143− do try equals
144− whitespace
145− value <- expr
146− whitespace
147− choice
148− [ do comma
149− whitespace
150− fields <- commaSep field
151− return (Src.Record ((key, value) : fields))
152− , return (Src.Record [(key, value)])
153− ]
154133
155− field =
156− do key <- addLocation rLabel
157− padded equals
158− value <- expr
159− return (key, value)
160134
161135
162−term :: IParser Src.RawExpr
163−term =
164− choice
165− [ addLocation $ choice $
166− [ Src.Literal <$> Literal.literal
167− , listTerm
168− , accessor
169− , negative
170− ]
171− , accessible $ choice $
172− [ addLocation varTerm
173− , parensTerm
174− , recordTerm
136+-- RECORDS
137+
138+
139+record :: R.Position -> Parser Src.RawExpr
140+record start =
141+ do leftCurly
142+ spaces
143+ oneOf
144+ [ do rightCurly
145+ end <- getPosition
146+ return (A.at start end (Src.Record []))
147+ , do starter <- addLocation lowVar
148+ spaces
149+ oneOf
150+ [ do pipe
151+ spaces
152+ firstField <- chompField
153+ fields <- chompFields [firstField]
154+ end <- getPosition
155+ return (A.at start end (Src.Update (A.map Src.var starter) fields))
156+ , do equals
157+ spaces
158+ (value, _, nextSpace) <- expression
159+ checkSpaces nextSpace
160+ fields <- chompFields [(starter, value)]
161+ end <- getPosition
162+ return (A.at start end (Src.Record fields))
163+ ]
175164 ]
165+
166+
167+type Field = ( A.Located Text, Src.RawExpr )
168+
169+
170+chompFields :: [Field] -> Parser [Field]
171+chompFields fields =
172+ oneOf
173+ [ do comma
174+ spaces
175+ f <- chompField
176+ chompFields (f : fields)
177+ , do rightCurly
178+ return fields
176179 ]
177− <?> "an expression"
178180
179181
182+chompField :: Parser Field
183+chompField =
184+ do key <- addLocation lowVar
185+ spaces
186+ equals
187+ spaces
188+ (value, _, endSpace) <- expression
189+ checkSpaces endSpace
190+ return (key, value)
191+
180192
181−-------- Applications --------
182193
194+-- EXPRESSIONS
183195
184−appExpr :: IParser Src.RawExpr
185−appExpr =
186− expecting "an expression" $
187− do t <- term
188− ts <- constrainedSpacePrefix term $ \hasSpace ->
189− if hasSpace then return () else notFollowedBy (char '-')
190− return $
191− case ts of
192− [] -> t
193− _ -> List.foldl' (\f x -> A.merge f x $ Src.App f x) t ts
194196
197+type ExprParser =
198+ SParser Src.RawExpr
199+
200+
201+expression :: ExprParser
202+expression =
203+ do start <- getPosition
204+ oneOf
205+ [ let_ start
206+ , if_ start
207+ , case_ start
208+ , function start
209+ , do starter <- term
210+ end <- getPosition
211+ space <- whitespace
212+ exprHelp start (State [] starter end space)
213+ ]
195214
196215
197−-------- Normal Expressions --------
216+data State =
217+ State
218+ { _ops :: ![(Src.RawExpr, A.Located Text)]
219+ , _last :: !Src.RawExpr
220+ , _end :: !R.Position
221+ , _space :: !Space
222+ }
223+
224+
225+exprHelp :: R.Position -> State -> ExprParser
226+exprHelp start (State ops lastExpr end space) =
227+ oneOf
228+ [ -- infix operator
229+ do checkSpaces space
230+ op <- addLocation infixOp
231+ opSpace <- whitespace
232+ oneOf
233+ [ -- negative terms
234+ do guard (space /= None && opSpace == None && A.drop op == "-")
235+ rawTerm <- term
236+ newEnd <- getPosition
237+ newSpace <- whitespace
238+
239+ let ann x = A.merge op rawTerm x
240+ let negatedTerm = ann (Src.Binop [(ann Src.zero, op)] rawTerm)
241+ let newLast = A.merge lastExpr rawTerm (Src.App lastExpr negatedTerm)
242+
243+ exprHelp start (State ops newLast newEnd newSpace)
244+
245+ , -- accessor
246+ do guard (space /= None && opSpace == None && A.drop op == ".")
247+ field <- lowVar
248+ newEnd <- getPosition
249+ newSpace <- whitespace
250+
251+ let (A.A (R.Region opStart _) _) = op
252+ let ann x = A.at opStart newEnd x
253+ let body = ann (Src.Access (ann (Src.var "r")) field)
254+ let accessor = mkLambda opStart newEnd "r" body
255+ let newLast = A.merge lastExpr accessor (Src.App lastExpr accessor)
256+
257+ exprHelp start (State ops newLast newEnd newSpace)
258+
259+ , -- access
260+ do guard (space == None && opSpace == None && A.drop op == ".")
261+ field <- lowVar
262+ newEnd <- getPosition
263+ newSpace <- whitespace
264+ let (A.A (R.Region lastStart _) _) = lastExpr
265+ let newLast = A.at lastStart newEnd (Src.Access lastExpr field)
266+ exprHelp start (State ops newLast newEnd newSpace)
267+
268+ , -- term
269+ do checkSpaces opSpace
270+ newLast <- term
271+ newEnd <- getPosition
272+ newSpace <- whitespace
273+ let newOps = (lastExpr, op) : ops
274+ exprHelp start (State newOps newLast newEnd newSpace)
275+
276+ , -- final term
277+ do checkSpaces opSpace
278+ newStart <- getPosition
279+ (newLast, newEnd, newSpace) <-
280+ oneOf
281+ [ let_ newStart
282+ , case_ newStart
283+ , if_ newStart
284+ , function newStart
285+ ]
286+ let newOps = (lastExpr, op) : ops
287+ let finalExpr = A.at start newEnd (Src.Binop (reverse newOps) newLast)
288+ return ( finalExpr, newEnd, newSpace )
289+ ]
198290
291+ , -- argument
292+ do checkSpaces space
293+ arg <- term
294+ newEnd <- getPosition
295+ newSpace <- whitespace
296+ let newLast = A.merge lastExpr arg (Src.App lastExpr arg)
297+ exprHelp start (State ops newLast newEnd newSpace)
298+
299+ , -- done
300+ case ops of
301+ [] ->
302+ return ( lastExpr, end, space )
303+
304+ _ ->
305+ let
306+ finalExpr =
307+ A.at start end (Src.Binop (reverse ops) lastExpr)
308+ in
309+ return ( finalExpr, end, space )
310+ ]
199311
200−expr :: IParser Src.RawExpr
201−expr =
202− addLocation (choice [ letExpr, caseExpr, ifExpr ])
203− <|> lambdaExpr
204− <|> binaryExpr
205− <?> "an expression"
206312
207313
208−binaryExpr :: IParser Src.RawExpr
209−binaryExpr =
210− Binop.binops appExpr lastExpr
211− where
212− lastExpr =
213− addLocation (choice [ letExpr, caseExpr, ifExpr ])
214− <|> lambdaExpr
215− <?> "an expression"
314+-- IF EXPRESSION
216315
217316
218−ifExpr :: IParser Src.RawExpr'
219−ifExpr =
220− ifHelp []
317+if_ :: R.Position -> ExprParser
318+if_ start =
319+ ifHelp start []
221320
222321
223−ifHelp :: [(Src.RawExpr, Src.RawExpr)] -> IParser Src.RawExpr'
224−ifHelp branches =
225− do try (reserved "if")
226− whitespace
227− condition <- expr
228− padded (reserved "then")
229− thenBranch <- expr
230− whitespace <?> "an 'else' branch"
231− reserved "else" <?> "an 'else' branch"
232− whitespace
322+ifHelp :: R.Position -> [(Src.RawExpr, Src.RawExpr)] -> ExprParser
323+ifHelp start branches =
324+ do keyword "if"
325+ spaces
326+ (condition, _, condSpace) <- expression
327+ checkSpaces condSpace
328+ keyword "then"
329+ spaces
330+ (thenBranch, _, thenSpace) <- expression
331+ checkSpaces thenSpace
332+ keyword "else"
333+ spaces
233334 let newBranches = (condition, thenBranch) : branches
234− choice
235− [ ifHelp newBranches
236− , Src.If (reverse newBranches) <$> expr
335+ oneOf
336+ [ ifHelp start newBranches
337+ , do (elseBranch, elseEnd, elseSpace) <- expression
338+ let ifExpr = A.at start elseEnd (Src.If (reverse newBranches) elseBranch)
339+ return ( ifExpr, elseEnd, elseSpace )
237340 ]
238341
239342
240−lambdaExpr :: IParser Src.RawExpr
241−lambdaExpr =
242− do start <- getMyPosition
243− char '\\' <|> char '\x03BB' <?> "an anonymous function"
244− whitespace
245− args <- spaceSep1 Pattern.term
246− padded rightArrow
247− body <- expr
248− end <- getMyPosition
249− return (foldr (\a b -> A.at start end $ Src.Lambda a b) body args)
250−
251−
252−caseExpr :: IParser Src.RawExpr'
253−caseExpr =
254− do try (reserved "case")
255− exp <- padded expr
256− reserved "of"
257− whitespace
258− Help.withPos $
259− do firstBranch <- branch
260− branches <-
261− many $ do
262− try (whitespace >> Help.checkIndent)
263− branch
264− return $ Src.Case exp (firstBranch : branches)
265− where
266− branch =
267− do p <- Pattern.expr
268− padded rightArrow
269− (,) p <$> expr
270−
271−
272−
273−-- LET
274−
275−
276−letExpr :: IParser Src.RawExpr'
277−letExpr =
278− do try (reserved "let")
279− whitespace
280− defs <- Help.block (def <* whitespace)
281− whitespace
282− reserved "in"
283− whitespace
284− Src.Let defs <$> expr
285−
286−
287−def :: IParser Src.RawDef
288−def =
289− addLocation $ Help.withPos $
290− do start <- defStart
291− whitespace
292− case start of
293− A.A _ (P.Var name) ->
294− choice
295− [ do hasType
296− whitespace
297− tipe <- Type.expr
298− return $ Src.Annotation name tipe
299− , defEnd start []
300− ]
301−
302− _ ->
303− defEnd start []
304−
305−
306−defStart :: IParser P.Raw
307−defStart =
308− choice
309− [ addLocation $ try $
310− do char '('
311− op <- Binop.infixOp
312− char ')'
313− return (P.Var op)
343+
344+-- LAMBDA EXPRESSION
345+
346+
347+function :: R.Position -> ExprParser
348+function start =
349+ do lambda
350+ spaces
351+ arg <- Pattern.term
352+ spaces
353+ revArgs <- gatherArgs [arg]
354+ spaces
355+ (body, end, space) <- expression
356+ let func = List.foldl' (\e x -> A.at start end (Src.Lambda x e)) body revArgs
357+ return ( func, end, space )
358+
359+
360+gatherArgs :: [P.Raw] -> Parser [P.Raw]
361+gatherArgs args =
362+ oneOf
363+ [ do arg <- Pattern.term
364+ spaces
365+ gatherArgs (arg:args)
366+ , do rightArrow
367+ return args
368+ ]
369+
370+
371+
372+-- CASE EXPRESSIONS
373+
374+
375+case_ :: R.Position -> ExprParser
376+case_ start =
377+ do keyword "case"
378+ spaces
379+ (switcher, _, switcherSpace) <- expression
380+ checkSpaces switcherSpace
381+ keyword "of"
382+ spaces
383+ oldIndent <- getIndent
384+ newIndent <- getCol
385+ setIndent newIndent
386+ (firstBranch, firstEnd, firstSpace) <- branchHelp
387+ (branches, end, space) <- caseHelp [firstBranch] firstEnd firstSpace
388+ setIndent oldIndent
389+ return
390+ ( A.at start end (Src.Case switcher branches)
391+ , end
392+ , space
393+ )
394+
395+
396+branchHelp :: SParser (P.Raw, Src.RawExpr)
397+branchHelp =
398+ do (pattern, patternSpace) <- Pattern.expression
399+ checkSpaces patternSpace
400+ rightArrow
401+ spaces
402+ (branchExpr, end, space) <- expression
403+ return ( (pattern, branchExpr), end, space )
404+
405+
406+caseHelp :: [(P.Raw, Src.RawExpr)] -> R.Position -> Space -> SParser [(P.Raw, Src.RawExpr)]
407+caseHelp branches end space =
408+ case space of
409+ Aligned ->
410+ do (branch, newEnd, newSpace) <- branchHelp
411+ caseHelp (branch:branches) newEnd newSpace
412+
413+ _ ->
414+ return ( reverse branches, end, space )
415+
416+
417+
418+-- LET EXPRESSION
419+
420+
421+let_ :: R.Position -> ExprParser
422+let_ start =
423+ do oldIndent <- getIndent
424+ letIndent <- getCol
425+ keyword "let"
426+ setIndent letIndent
427+ spaces
428+ defIndent <- getCol
429+ setIndent defIndent
430+ (def, end, space) <- definition
431+ letHelp start oldIndent [def] end space
432+
433+
434+letHelp :: R.Position -> Int -> [Src.RawDef] -> R.Position -> Space -> ExprParser
435+letHelp start oldIndent defs end space =
436+ case space of
437+ Aligned ->
438+ do (def, newEnd, newSpace) <- definition
439+ letHelp start oldIndent (def:defs) newEnd newSpace
440+
441+ Freshline ->
442+ failure (error "TODO missing `in`")
443+
444+ _ ->
445+ do keyword "in"
446+ setIndent oldIndent
447+ spaces
448+ (body, newEnd, newSpace) <- expression
449+ let letExpr = A.at start end (Src.Let defs body)
450+ return ( letExpr, newEnd, newSpace )
451+
452+
453+
454+-- DEFINITIONS
455+
456+
457+definition :: SParser Src.RawDef
458+definition =
459+ do start <- getPosition
460+ root <- rootPattern start
461+ spaces
462+ case A.drop root of
463+ P.Var name ->
464+ oneOf
465+ [ do hasType
466+ spaces
467+ (tipe, end, space) <- Type.expression
468+ return ( A.at start end (Src.Annotation name tipe), end, space )
469+ , definitionHelp start root []
470+ ]
471+
472+ _ ->
473+ definitionHelp start root []
474+
475+
476+rootPattern :: R.Position -> Parser P.Raw
477+rootPattern start =
478+ oneOf
479+ [ do op <- try (leftParen >> infixOp)
480+ rightParen
481+ end <- getPosition
482+ return (A.at start end (P.Var op))
314483 , Pattern.term
315484 ]
316485
317486
318−defEnd :: P.Raw -> [P.Raw] -> IParser Src.RawDef'
319−defEnd start revArgs =
320− choice
487+definitionHelp :: R.Position -> P.Raw -> [P.Raw] -> SParser Src.RawDef
488+definitionHelp start root revArgs =
489+ oneOf
321490 [ do arg <- Pattern.term
322− whitespace
323− defEnd start (arg : revArgs)
491+ spaces
492+ definitionHelp start root (arg : revArgs)
324493 , do equals
325− whitespace
326− body <- expr
327− return $ Src.Definition start (makeFunction revArgs body)
494+ spaces
495+ (expr, end, space) <- expression
496+ let body = List.foldl' (\e x -> A.at start end (Src.Lambda x e)) expr revArgs
497+ let def = A.at start end (Src.Definition root body)
498+ return ( def, end, space )
328499 ]
329−
330−
331−makeFunction :: [P.Raw] -> Src.RawExpr -> Src.RawExpr
332−makeFunction revArgs body@(A.A ann _) =
333− List.foldl' (\expr arg -> A.A ann $ Src.Lambda arg expr) body revArgs