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 qualified Parse.Pattern as Pattern
10import qualified Parse.Type as Type
14import SourceSyntax.Location as Location
15import SourceSyntax.Pattern hiding (tuple,list)
16import qualified SourceSyntax.Literal as Literal
17import SourceSyntax.Expression
20-------- Basic Terms --------
22varTerm :: IParser ParseExpr
23varTerm = toVar <$> var <?> "variable"
25toVar :: String -> ParseExpr
26toVar v = case v of "True" -> Literal (Literal.Boolean True)
27 "False" -> Literal (Literal.Boolean False)
30accessor :: IParser ParseExpr
32 (start, lbl, end) <- located (try (string "." >> rLabel))
33 let loc e = Location.at start end e
34 return (Lambda (PVar "_") (loc $ Access (loc $ Var "_") lbl))
36negative :: IParser ParseExpr
38 (start, nTerm, end) <-
39 located (try (char '-' >> notFollowedBy (char '.' <|> char '-')) >> term)
40 let loc e = Location.at start end e
41 return (Binop "-" (loc $ Literal (Literal.IntNum 0)) nTerm)
44-------- Complex Terms --------
46listTerm :: IParser ParseExpr
47listTerm = markdown' <|> braces (try range <|> ExplicitList <$> commaSep expr)
56 let uid = show (sourceLine pos) ++ ":" ++ show (sourceColumn pos)
57 (rawText, exprs) <- markdown (interpolation uid)
58 return (Markdown uid (filter (/='\r') rawText) exprs)
61 "<span id=\"md-" ++ uid ++ "-" ++ show index ++ "\">{{ markdown interpolation is in the pipeline, but still needs more testing }}</span>"
63 interpolation uid md exprs = do
67 return (md ++ span uid (length exprs), exprs ++ [e])
69parensTerm :: IParser LParseExpr
70parensTerm = try (parens opFn) <|> parens (tupleFn <|> parened)
73 (start, op, end) <- located anyOp
74 let loc = Location.at start end
75 return . loc . Lambda (PVar "x") . loc . Lambda (PVar "y") . loc $
76 Binop op (loc $ Var "x") (loc $ Var "y")
79 let comma = char ',' <?> "comma ','"
80 (start, commas, end) <- located (comma >> many (whitespace >> comma))
81 let vars = map (('v':) . show) [ 0 .. length commas + 1 ]
82 loc = Location.at start end
83 return $ foldr (\x e -> loc $ Lambda x e)
84 (loc . tuple $ map (loc . Var) vars) (map PVar vars)
87 (start, es, end) <- located (commaSep expr)
90 _ -> Location.at start end (tuple es)
92recordTerm :: IParser LParseExpr
93recordTerm = brackets $ choice [ misc, addLocation record ]
96 patterns <- spacePrefix Pattern.term
99 return (label, makeFunction patterns body)
101 record = Record <$> commaSep field
108 remove r = addLocation (string "-" >> whitespace >> Remove r <$> rLabel)
110 insert r = addLocation $ do
111 string "|" >> whitespace
112 Insert r <$> rLabel <*> (padded equals >> expr)
114 modify r = addLocation
115 (string "|" >> whitespace >> Modify r <$> commaSep1 change)
118 record <- addLocation (Var <$> rLabel)
119 opt <- padded (optionMaybe (remove record))
121 Just e -> try (insert e) <|> return e
122 Nothing -> try (insert record) <|> try (modify record)
125term :: IParser LParseExpr
126term = addLocation (choice [ Literal <$> literal, listTerm, accessor, negative ])
127 <|> accessible (addLocation varTerm <|> parensTerm <|> recordTerm)
128 <?> "basic term (4, x, 'c', etc.)"
130-------- Applications --------
132appExpr :: IParser LParseExpr
135 ts <- constrainedSpacePrefix term $ \str ->
136 if null str then notFollowedBy (char '-') else return ()
139 _ -> foldl' (\f x -> Location.merge f x $ App f x) t ts
141-------- Normal Expressions --------
143binaryExpr :: IParser LParseExpr
144binaryExpr = binops appExpr lastExpr anyOp
145 where lastExpr = addLocation (choice [ ifExpr, letExpr, caseExpr ])
148ifExpr :: IParser ParseExpr
149ifExpr = reserved "if" >> whitespace >> (normal <|> multiIf)
153 padded (reserved "then")
155 whitespace <?> "an 'else' branch" ; reserved "else" <?> "an 'else' branch" ; whitespace
157 return $ MultiIf [(bool, thenBranch),
158 (Location.sameAs elseBranch (Literal . Literal.Boolean $ True), elseBranch)]
159 multiIf = MultiIf <$> spaceSep1 iff
160 where iff = do string "|" ; whitespace
161 b <- expr ; padded arrow
164lambdaExpr :: IParser LParseExpr
165lambdaExpr = do char '\\' <|> char '\x03BB' <?> "anonymous function"
167 args <- spaceSep1 Pattern.term
170 return (makeFunction args body)
172defSet :: IParser [ParseDef]
173defSet = block (do d <- def ; whitespace ; return d)
175letExpr :: IParser ParseExpr
177 reserved "let" ; whitespace
179 padded (reserved "in")
182caseExpr :: IParser ParseExpr
184 reserved "case"; e <- padded expr; reserved "of"; whitespace
185 Case e <$> (with <|> without)
186 where case_ = do p <- Pattern.expr
189 with = brackets (semiSep1 (case_ <?> "cases { x -> ... }"))
190 without = block (do c <- case_ ; whitespace ; return c)
192expr :: IParser LParseExpr
193expr = addLocation (choice [ ifExpr, letExpr, caseExpr ])
198defStart :: IParser [Pattern]
200 choice [ do p1 <- try Pattern.term
201 infics p1 <|> func p1
202 , func =<< (PVar <$> parens symOp)
203 , (:[]) <$> Pattern.expr
204 ] <?> "the definition of a variable (x = ...)"
208 PVar _ -> (pattern:) <$> spacePrefix Pattern.term
209 _ -> do try (lookAhead (whitespace >> string "="))
213 o:p <- try (whitespace >> anyOp)
214 p2 <- (whitespace >> Pattern.term)
215 return $ if o == '`' then [ PVar $ takeWhile (/='`') p, p1, p2 ]
216 else [ PVar (o:p), p1, p2 ]
218makeFunction :: [Pattern] -> LParseExpr -> LParseExpr
219makeFunction args body@(L s _) =
220 foldr (\arg body' -> L s $ Lambda arg body') body args
222definition :: IParser ParseDef
223definition = withPos $ do
224 (name:args) <- defStart
227 return . Def name $ makeFunction args body
229typeAnnotation :: IParser ParseDef
230typeAnnotation = TypeAnnotation <$> try start <*> Type.expr
233 v <- lowVar <|> parens symOp
237def :: IParser ParseDef
238def = 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