1module Parse.Expression (def,term,typeAnnotation,expr) where
3import Control.Applicative ((<$>), (<*>))
4import Data.List (foldl')
5import Text.Parsec hiding (newline,spaces)
6import Text.Parsec.Indent
9import Parse.Helpers as Help
11import qualified Parse.Pattern as Pattern
12import qualified Parse.Type as Type
14import AST.Annotation as Annotation
15import AST.Expression.General
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
22-------- Basic Terms --------
24varTerm :: IParser Source.Expr'
25varTerm = toVar <$> var <?> "variable"
27toVar :: String -> Source.Expr'
28toVar v = case v of "True" -> Literal (L.Boolean True)
29 "False" -> Literal (L.Boolean False)
32accessor :: IParser Source.Expr'
34 (start, lbl, end) <- located (try (string "." >> rLabel))
35 let loc e = Annotation.at start end e
36 return (Lambda (P.Var "_") (loc $ Access (loc $ rawVar "_") lbl))
38negative :: IParser Source.Expr'
40 (start, nTerm, end) <-
41 located (try (char '-' >> notFollowedBy (char '.' <|> char '-')) >> term)
42 let loc e = Annotation.at start end e
43 return (Binop (Var.Raw "-") (loc $ Literal (L.IntNum 0)) nTerm)
46-------- Complex Terms --------
48listTerm :: IParser Source.Expr'
49listTerm = markdown' <|> shader' <|> braces (try range <|> ExplicitList <$> commaSep expr)
58 let uid = show (sourceLine pos) ++ ":" ++ show (sourceColumn pos)
59 (rawText, exprs) <- Help.markdown (interpolation uid)
60 return (Markdown uid (filter (/='\r') rawText) exprs)
64 let uid = show (sourceLine pos) ++ ":" ++ show (sourceColumn pos)
65 (rawSrc, tipe) <- Help.shader
66 return $ GLShader uid (filter (/='\r') rawSrc) tipe
69 "<span id=\"md-" ++ uid ++ "-" ++ show index ++
70 "\">{{ markdown interpolation is in the pipeline, but still needs more testing }}</span>"
72 interpolation uid exprs = do
76 return (span uid (length exprs), exprs ++ [e])
78parensTerm :: IParser Source.Expr
79parensTerm = try (parens opFn) <|> parens (tupleFn <|> parened)
82 (start, op, end) <- located anyOp
83 let loc = Annotation.at start end
84 return . loc . Lambda (P.Var "x") . loc . Lambda (P.Var "y") . loc $
85 Binop (Var.Raw op) (loc (rawVar "x")) (loc (rawVar "y"))
88 let comma = char ',' <?> "comma ','"
89 (start, commas, end) <- located (comma >> many (whitespace >> comma))
90 let vars = map (('v':) . show) [ 0 .. length commas + 1 ]
91 loc = Annotation.at start end
92 return $ foldr (\x e -> loc $ Lambda x e)
93 (loc . tuple $ map (loc . rawVar) vars) (map P.Var vars)
96 (start, es, end) <- located (commaSep expr)
99 _ -> Annotation.at start end (tuple es)
101recordTerm :: IParser Source.Expr
102recordTerm = brackets $ choice [ misc, addLocation record ]
106 patterns <- spacePrefix Pattern.term
109 return (label, makeFunction patterns body)
111 record = Record <$> commaSep field
118 remove r = addLocation (string "-" >> whitespace >> Remove r <$> rLabel)
120 insert r = addLocation $ do
121 string "|" >> whitespace
122 Insert r <$> rLabel <*> (padded equals >> expr)
125 addLocation (string "|" >> whitespace >> Modify r <$> commaSep1 change)
128 record <- addLocation (rawVar <$> rLabel)
129 opt <- padded (optionMaybe (remove record))
131 Just e -> try (insert e) <|> return e
132 Nothing -> try (insert record) <|> try (modify record)
135term :: IParser Source.Expr
136term = addLocation (choice [ Literal <$> literal, listTerm, accessor, negative ])
137 <|> accessible (addLocation varTerm <|> parensTerm <|> recordTerm)
138 <?> "basic term (4, x, 'c', etc.)"
140-------- Applications --------
142appExpr :: IParser Source.Expr
145 ts <- constrainedSpacePrefix term $ \str ->
146 if null str then notFollowedBy (char '-') else return ()
149 _ -> foldl' (\f x -> Annotation.merge f x $ App f x) t ts
151-------- Normal Expressions --------
153binaryExpr :: IParser Source.Expr
154binaryExpr = binops appExpr lastExpr anyOp
155 where lastExpr = addLocation (choice [ ifExpr, letExpr, caseExpr ])
158ifExpr :: IParser Source.Expr'
159ifExpr = reserved "if" >> whitespace >> (normal <|> multiIf)
163 padded (reserved "then")
165 whitespace <?> "an 'else' branch" ; reserved "else" <?> "an 'else' branch" ; whitespace
167 return $ MultiIf [(bool, thenBranch),
168 (Annotation.sameAs elseBranch (Literal . L.Boolean $ True), elseBranch)]
169 multiIf = MultiIf <$> spaceSep1 iff
170 where iff = do string "|" ; whitespace
171 b <- expr ; padded arrow
174lambdaExpr :: IParser Source.Expr
175lambdaExpr = do char '\\' <|> char '\x03BB' <?> "anonymous function"
177 args <- spaceSep1 Pattern.term
180 return (makeFunction args body)
182defSet :: IParser [Source.Def]
183defSet = block (do d <- def ; whitespace ; return d)
185letExpr :: IParser Source.Expr'
187 reserved "let" ; whitespace
189 padded (reserved "in")
192caseExpr :: IParser Source.Expr'
194 reserved "case"; e <- padded expr; reserved "of"; whitespace
195 Case e <$> (with <|> without)
196 where case_ = do p <- Pattern.expr
199 with = brackets (semiSep1 (case_ <?> "cases { x -> ... }"))
200 without = block (do c <- case_ ; whitespace ; return c)
202expr :: IParser Source.Expr
203expr = addLocation (choice [ ifExpr, letExpr, caseExpr ])
208defStart :: IParser [P.RawPattern]
210 choice [ do p1 <- try Pattern.term
211 infics p1 <|> func p1
212 , func =<< (P.Var <$> parens symOp)
213 , (:[]) <$> Pattern.expr
214 ] <?> "the definition of a variable (x = ...)"
218 P.Var _ -> (pattern:) <$> spacePrefix Pattern.term
219 _ -> do try (lookAhead (whitespace >> string "="))
223 o:p <- try (whitespace >> anyOp)
224 p2 <- (whitespace >> Pattern.term)
225 return $ if o == '`' then [ P.Var $ takeWhile (/='`') p, p1, p2 ]
226 else [ P.Var (o:p), p1, p2 ]
228makeFunction :: [P.RawPattern] -> Source.Expr -> Source.Expr
229makeFunction args body@(A ann _) =
230 foldr (\arg body' -> A ann $ Lambda arg body') body args
232definition :: IParser Source.Def
233definition = withPos $ do
234 (name:args) <- defStart
237 return . Source.Definition name $ makeFunction args body
239typeAnnotation :: IParser Source.Def
240typeAnnotation = Source.TypeAnnotation <$> try start <*> Type.expr
243 v <- lowVar <|> parens symOp
247def :: IParser Source.Def
248def = typeAnnotation <|> definition
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