on master help sign in
Split Parser.hs into several files

In order to help cut down rebuild time. We have 'Helpers', 'Ops' and 'Exprs' with Parser.hs now containing top level declarations.

commit67fb9ccd9bda78879cead0761d0f76fff1653f7f authorEdwin Brady <ecb10@st-andrews.ac.uk> dateSat 5 Oct 2013, 17:05 (13 years ago) parent4be67f7
8 files changed+1543−1427
idris.cabal+3 src/Idris/AbsSyntaxTree.hs+1 src/Idris/ParseExpr.hs+1030 src/Idris/ParseHelpers.hs+403 src/Idris/ParseOps.hs+88 src/Idris/Parser.hs+9−1427 src/Idris/REPL.hs+8 src/Idris/REPLParser.hs+1
idris.cabal+3
@@ -309,6 +309,9 @@ Executable idris
309309 , Idris.Imports
310310 , Idris.Inliner
311311 , Idris.Parser
312+ , Idris.ParseHelpers
313+ , Idris.ParseOps
314+ , Idris.ParseExpr
312315 , Idris.PartialEval
313316 , Idris.Primitives
314317 , Idris.Prover
src/Idris/AbsSyntaxTree.hs+1
@@ -225,6 +225,7 @@ data Command = Quit
225225 | LogLvl Int
226226 | Spec PTerm
227227 | HNF PTerm
228+ | TestInline PTerm
228229 | Defn Name
229230 | Info Name
230231 | Missing Name
src/Idris/ParseExpr.hsnew file+1030
@@ -0,0 +1,1030 @@
1+{-# LANGUAGE GeneralizedNewtypeDeriving, ConstraintKinds, PatternGuards #-}
2+module Idris.ParseExpr where
3+
4+import Prelude hiding (pi)
5+
6+import Text.Trifecta.Delta
7+import Text.Trifecta hiding (span, stringLiteral, charLiteral, natural, symbol, char, string, whiteSpace)
8+import Text.Parser.LookAhead
9+import Text.Parser.Expression
10+import qualified Text.Parser.Token as Tok
11+import qualified Text.Parser.Char as Chr
12+import qualified Text.Parser.Token.Highlight as Hi
13+
14+import Idris.AbsSyntax
15+import Idris.ParseHelpers
16+import Idris.ParseOps
17+import Idris.DSL
18+
19+import Core.TT
20+
21+import Control.Applicative
22+import Control.Monad
23+import Control.Monad.State.Strict
24+
25+import Data.Maybe
26+import qualified Data.List.Split as Spl
27+import Data.List
28+import Data.Monoid
29+import Data.Char
30+import qualified Data.HashSet as HS
31+import qualified Data.Text as T
32+import qualified Data.ByteString.UTF8 as UTF8
33+
34+-- | Allow implicit type declarations
35+allowImp :: SyntaxInfo -> SyntaxInfo
36+allowImp syn = syn { implicitAllowed = True }
37+
38+-- | Disallow implicit type declarations
39+disallowImp :: SyntaxInfo -> SyntaxInfo
40+disallowImp syn = syn { implicitAllowed = False }
41+
42+{- | Parses an expression as a whole
43+ FullExpr ::= Expr EOF_t;
44+ -}
45+fullExpr :: SyntaxInfo -> IdrisParser PTerm
46+fullExpr syn = do x <- expr syn
47+ eof
48+ i <- get
49+ return $ desugar syn i x
50+
51+
52+{- |Parses an expression
53+ Expr ::= Expr';
54+-}
55+expr :: SyntaxInfo -> IdrisParser PTerm
56+expr syn = do i <- get
57+ buildExpressionParser (table (idris_infixes i)) (expr' syn)
58+
59+{- | Parses either an internally defined expression or
60+ a user-defined one
61+
62+Expr' ::= "External (User-defined) Syntax"
63+ | InternalExpr;
64+
65+ -}
66+expr' :: SyntaxInfo -> IdrisParser PTerm
67+expr' syn = try (externalExpr syn)
68+ <|> internalExpr syn
69+ <?> "expression"
70+
71+{- | Parses a user-defined expression -}
72+externalExpr :: SyntaxInfo -> IdrisParser PTerm
73+externalExpr syn = do i <- get
74+ extensions syn (syntax_rules i)
75+ <?> "user-defined expression"
76+
77+{- | Parses a simple user-defined expression -}
78+simpleExternalExpr :: SyntaxInfo -> IdrisParser PTerm
79+simpleExternalExpr syn = do i <- get
80+ extensions syn (filter isSimple (syntax_rules i))
81+ where
82+ isSimple (Rule (Expr x:xs) _ _) = False
83+ isSimple (Rule (SimpleExpr x:xs) _ _) = False
84+ isSimple (Rule [Keyword _] _ _) = True
85+ isSimple (Rule [Symbol _] _ _) = True
86+ isSimple (Rule (_:xs) _ _) = case last xs of
87+ Keyword _ -> True
88+ Symbol _ -> True
89+ _ -> False
90+ isSimple _ = False
91+
92+{- | Tries to parse a user-defined expression given a list of syntactic extensions -}
93+extensions :: SyntaxInfo -> [Syntax] -> IdrisParser PTerm
94+extensions syn rules = choice (map (try . extension syn) (filter isValid rules))
95+ <?> "user-defined expression"
96+ where
97+ isValid :: Syntax -> Bool
98+ isValid (Rule _ _ AnySyntax) = True
99+ isValid (Rule _ _ PatternSyntax) = inPattern syn
100+ isValid (Rule _ _ TermSyntax) = not (inPattern syn)
101+
102+
103+data SynMatch = SynTm PTerm | SynBind Name
104+
105+{- | Tries to parse an expression given a user-defined rule -}
106+extension :: SyntaxInfo -> Syntax -> IdrisParser PTerm
107+extension syn (Rule ssym ptm _)
108+ = do smap <- mapM extensionSymbol ssym
109+ let ns = mapMaybe id smap
110+ return (update ns ptm) -- updated with smap
111+ where
112+ extensionSymbol :: SSymbol -> IdrisParser (Maybe (Name, SynMatch))
113+ extensionSymbol (Keyword n) = do reserved (show n); return Nothing
114+ extensionSymbol (Expr n) = do tm <- expr syn
115+ return $ Just (n, SynTm tm)
116+ extensionSymbol (SimpleExpr n) = do tm <- simpleExpr syn
117+ return $ Just (n, SynTm tm)
118+ extensionSymbol (Binding n) = do b <- name
119+ return $ Just (n, SynBind b)
120+ extensionSymbol (Symbol s) = do symbol s
121+ return Nothing
122+ dropn :: Name -> [(Name, a)] -> [(Name, a)]
123+ dropn n [] = []
124+ dropn n ((x,t) : xs) | n == x = xs
125+ | otherwise = (x,t):dropn n xs
126+
127+ updateB :: [(Name, SynMatch)] -> Name -> Name
128+ updateB ns n = case lookup n ns of
129+ Just (SynBind t) -> t
130+ _ -> n
131+
132+ update :: [(Name, SynMatch)] -> PTerm -> PTerm
133+ update ns (PRef fc n) = case lookup n ns of
134+ Just (SynTm t) -> t
135+ _ -> PRef fc n
136+ update ns (PLam n ty sc) = PLam (updateB ns n) (update ns ty) (update (dropn n ns) sc)
137+ update ns (PPi p n ty sc) = PPi p (updateB ns n) (update ns ty) (update (dropn n ns) sc)
138+ update ns (PLet n ty val sc) = PLet (updateB ns n) (update ns ty) (update ns val)
139+ (update (dropn n ns) sc)
140+ update ns (PApp fc t args) = PApp fc (update ns t) (map (fmap (update ns)) args)
141+ update ns (PCase fc c opts) = PCase fc (update ns c) (map (pmap (update ns)) opts)
142+ update ns (PPair fc l r) = PPair fc (update ns l) (update ns r)
143+ update ns (PDPair fc l t r) = PDPair fc (update ns l) (update ns t) (update ns r)
144+ update ns (PAlternative a as) = PAlternative a (map (update ns) as)
145+ update ns (PHidden t) = PHidden (update ns t)
146+ update ns (PDoBlock ds) = PDoBlock $ upd ns ds
147+ where upd :: [(Name, SynMatch)] -> [PDo] -> [PDo]
148+ upd ns (DoExp fc t : ds) = DoExp fc (update ns t) : upd ns ds
149+ upd ns (DoBind fc n t : ds) = DoBind fc n (update ns t) : upd (dropn n ns) ds
150+ upd ns (DoLet fc n ty t : ds) = DoLet fc n (update ns ty) (update ns t)
151+ : upd (dropn n ns) ds
152+ upd ns (DoBindP fc i t : ds) = DoBindP fc (update ns i) (update ns t)
153+ : upd ns ds
154+ upd ns (DoLetP fc i t : ds) = DoLetP fc (update ns i) (update ns t)
155+ : upd ns ds
156+ update ns (PGoal fc r n sc) = PGoal fc (update ns r) n (update ns sc)
157+ update ns t = t
158+
159+{- |Parses a (normal) built-in expression
160+
161+InternalExpr ::=
162+ App
163+ | MatchApp
164+ | UnifyLog
165+ | RecordType
166+ | SimpleExpr
167+ | Lambda
168+ | QuoteGoal
169+ | Let
170+ | RewriteTerm
171+ | Pi
172+ | DoBlock
173+ ;
174+-}
175+internalExpr :: SyntaxInfo -> IdrisParser PTerm
176+internalExpr syn =
177+ try (app syn)
178+ <|> try (matchApp syn)
179+ <|> try (unifyLog syn)
180+ <|> recordType syn
181+ <|> try (simpleExpr syn)
182+ <|> lambda syn
183+ <|> quoteGoal syn
184+ <|> let_ syn
185+ <|> rewriteTerm syn
186+ <|> pi syn
187+ <|> doBlock syn
188+ <?> "expression"
189+
190+{- | Parses a case expression
191+CaseExpr ::=
192+ 'case' Expr 'of' OpenBlock CaseOption+ CloseBlock;
193+-}
194+caseExpr :: SyntaxInfo -> IdrisParser PTerm
195+caseExpr syn = do reserved "case"; fc <- getFC
196+ scr <- expr syn; reserved "of";
197+ opts <- indentedBlock1 (caseOption syn)
198+ return (PCase fc scr opts)
199+ <?> "case expression"
200+
201+{- | Parses a case in a case expression
202+CaseOption ::=
203+ Expr '=>' Expr Terminator
204+ ;
205+-}
206+caseOption :: SyntaxInfo -> IdrisParser (PTerm, PTerm)
207+caseOption syn = do lhs <- expr (syn { inPattern = True })
208+ symbol "=>"; r <- expr syn
209+ return (lhs, r)
210+ <?> "case option"
211+
212+{- | Parses a proof block
213+ProofExpr ::=
214+ 'proof' OpenBlock Tactic'* CloseBlock
215+ ;
216+-}
217+proofExpr :: SyntaxInfo -> IdrisParser PTerm
218+proofExpr syn = do reserved "proof"
219+ ts <- indentedBlock (tactic syn)
220+ return $ PProof ts
221+ <?> "proof block"
222+
223+{- | Parses a tactics block
224+TacticsExpr :=
225+ 'tactics' OpenBlock Tactic'* CloseBlock
226+;
227+-}
228+tacticsExpr :: SyntaxInfo -> IdrisParser PTerm
229+tacticsExpr syn = do reserved "tactics"
230+ ts <- indentedBlock (tactic syn)
231+ return $ PTactics ts
232+ <?> "tactics block"
233+
234+{- | Parses a simple expresion
235+SimpleExpr ::=
236+ '![' Term ']'
237+ | '?' Name
238+ | % 'instance'
239+ | 'refl' ('{' Expr '}')?
240+ | ProofExpr
241+ | TacticsExpr
242+ | CaseExpr
243+ | FnName
244+ | List
245+ | Comprehension
246+ | Alt
247+ | Idiom
248+ | '(' Bracketed
249+ | Constant
250+ | Type
251+ | '_|_'
252+ | '_'
253+ | {- External (User-defined) Simple Expression -}
254+ ;
255+-}
256+simpleExpr :: SyntaxInfo -> IdrisParser PTerm
257+simpleExpr syn =
258+ {-try (do symbol "!["; t <- term; lchar ']'; return $ PQuote t)
259+ <|>-} do lchar '?'; x <- name; return (PMetavar x)
260+ <|> do lchar '%'; fc <- getFC; reserved "instance"; return (PResolveTC fc)
261+ <|> do reserved "refl"; fc <- getFC;
262+ tm <- option Placeholder (do lchar '{'; t <- expr syn; lchar '}';
263+ return t)
264+ return (PRefl fc tm)
265+ <|> proofExpr syn
266+ <|> tacticsExpr syn
267+ <|> caseExpr syn
268+ <|> try (do fc <- getFC
269+ x <- fnName
270+ return (PRef fc x))
271+ <|> try (listExpr syn)
272+ <|> try (comprehension syn)
273+ <|> try (alt syn)
274+ <|> try (idiom syn)
275+ <|> do lchar '('
276+ bracketed (disallowImp syn)
277+ <|> try (do c <- constant
278+ fc <- getFC
279+ return (modifyConst syn fc (PConstant c)))
280+ <|> do reserved "Type"; return PType
281+ <|> try (do symbol "_|_"
282+ fc <- getFC
283+ return (PFalse fc))
284+ <|> do lchar '_'; return Placeholder
285+ <|> simpleExternalExpr syn
286+ <?> "expression"
287+
288+
289+{- |Parses the rest of an expression in braces
290+Bracketed ::=
291+ ')'
292+ | Expr ')'
293+ | ExprList ')'
294+ | Expr '**' Expr ')'
295+ | Operator Expr ')'
296+ | Expr Operator ')'
297+ | Name ':' Expr '**' Expr ')'
298+ ;
299+-}
300+bracketed :: SyntaxInfo -> IdrisParser PTerm
301+bracketed syn =
302+ do lchar ')'
303+ fc <- getFC
304+ return $ PTrue fc
305+ <|>
306+ try (do l <- expr syn
307+ lchar ')'
308+ return l)
309+ <|> do (l, fc) <- try (do
310+ l <- expr syn
311+ fc <- getFC
312+ lchar ','
313+ return (l, fc))
314+ rs <- sepBy1 (do fc' <- getFC; r <- expr syn; return (r, fc')) (lchar ',')
315+ lchar ')'
316+ return $ PPair fc l (mergePairs rs)
317+ <|> do (l, fc) <- try (do
318+ l <- expr syn
319+ fc <- getFC
320+ reservedOp "**"
321+ return (l, fc))
322+ r <- expr syn
323+ lchar ')'
324+ return (PDPair fc l Placeholder r)
325+ <|> try(do fc0 <- getFC
326+ l <- simpleExpr syn
327+ o <- operator
328+ lchar ')'
329+ return $ PLam (MN 1000 "ARG") Placeholder
330+ (PApp fc0 (PRef fc0 (UN o)) [pexp l,
331+ pexp (PRef fc0 (MN 1000 "ARG"))]))
332+ <|> try(do fc <- getFC; o <- operator; e <- expr syn; lchar ')'
333+ return $ PLam (MN 1000 "ARG") Placeholder
334+ (PApp fc (PRef fc (UN o)) [pexp (PRef fc (MN 1000 "ARG")),
335+ pexp e]))
336+ <|> try (do ln <- name; lchar ':'
337+ lty <- expr syn
338+ reservedOp "**"
339+ fc <- getFC
340+ r <- expr syn
341+ lchar ')'
342+ return (PDPair fc (PRef fc ln) lty r))
343+ <?> "end of braced expression"
344+ where mergePairs :: [(PTerm, FC)] -> PTerm
345+ mergePairs [(t, fc)] = t
346+ mergePairs ((t, fc):rs) = PPair fc t (mergePairs rs)
347+
348+-- bit of a hack here. If the integer doesn't fit in an Int, treat it as a
349+-- big integer, otherwise try fromInteger and the constants as alternatives.
350+-- a better solution would be to fix fromInteger to work with Integer, as the
351+-- name suggests, rather than Int
352+{-| Finds optimal type for integer constant -}
353+modifyConst :: SyntaxInfo -> FC -> PTerm -> PTerm
354+modifyConst syn fc (PConstant (BI x))
355+ | not (inPattern syn)
356+ = PAlternative False
357+ (PApp fc (PRef fc (UN "fromInteger")) [pexp (PConstant (BI (fromInteger x)))]
358+ : consts)
359+ | otherwise = PAlternative False consts
360+ where
361+ consts = [ PConstant (BI x)
362+ , PConstant (I (fromInteger x))
363+ , PConstant (B8 (fromInteger x))
364+ , PConstant (B16 (fromInteger x))
365+ , PConstant (B32 (fromInteger x))
366+ , PConstant (B64 (fromInteger x))
367+ ]
368+modifyConst syn fc x = x
369+
370+{- | Parses a list literal expression e.g. [1,2,3]
371+ListExpr ::=
372+ '[' ExprList? ']'
373+;
374+
375+ExprList ::=
376+ Expr
377+ | Expr ',' ExprList
378+ ;
379+
380+ -}
381+listExpr :: SyntaxInfo -> IdrisParser PTerm
382+listExpr syn = do lchar '['; fc <- getFC; xs <- sepBy (expr syn) (lchar ','); lchar ']'
383+ return (mkList fc xs)
384+ <?> "list expression"
385+ where
386+ mkList :: FC -> [PTerm] -> PTerm
387+ mkList fc [] = PRef fc (UN "Nil")
388+ mkList fc (x : xs) = PApp fc (PRef fc (UN "::")) [pexp x, pexp (mkList fc xs)]
389+
390+
391+{- | Parses an alternative expression
392+ Alt ::= '(|' Expr_List '|)';
393+
394+ Expr_List ::=
395+ Expr'
396+ | Expr' ',' Expr_List
397+ ;
398+-}
399+alt :: SyntaxInfo -> IdrisParser PTerm
400+alt syn = do symbol "(|"; alts <- sepBy1 (expr' syn) (lchar ','); symbol "|)"
401+ return (PAlternative False alts)
402+
403+{- | Parses a possibly hidden simple expression
404+HSimpleExpr ::=
405+ '.' SimpleExpr
406+ | SimpleExpr
407+ ;
408+-}
409+hsimpleExpr :: SyntaxInfo -> IdrisParser PTerm
410+hsimpleExpr syn =
411+ do lchar '.'
412+ e <- simpleExpr syn
413+ return $ PHidden e
414+ <|> simpleExpr syn
415+ <?> "expression"
416+
417+{- | Parses a matching application expression
418+MatchApp ::=
419+ SimpleExpr '<==' FnName
420+ ;
421+-}
422+matchApp :: SyntaxInfo -> IdrisParser PTerm
423+matchApp syn = do ty <- simpleExpr syn
424+ symbol "<=="
425+ fc <- getFC
426+ f <- fnName
427+ return (PLet (MN 0 "match")
428+ ty
429+ (PMatchApp fc f)
430+ (PRef fc (MN 0 "match")))
431+ <?> "matching application expression"
432+
433+{- | Parses a unification log expression
434+UnifyLog ::=
435+ '%' 'unifyLog' SimpleExpr
436+ ;
437+-}
438+unifyLog :: SyntaxInfo -> IdrisParser PTerm
439+unifyLog syn = do lchar '%'; reserved "unifyLog";
440+ tm <- simpleExpr syn
441+ return (PUnifyLog tm)
442+ <?> "unification log expression"
443+
444+{- | Parses a function application expression
445+App ::=
446+ 'mkForeign' Arg Arg*
447+ | SimpleExpr Arg+
448+ ;
449+-}
450+app :: SyntaxInfo -> IdrisParser PTerm
451+app syn = do f <- reserved "mkForeign"
452+ fc <- getFC
453+ fn <- arg syn
454+ args <- many (do notEndApp; arg syn)
455+ i <- get
456+ -- mkForeign f args ==>
457+ -- liftPrimIO (\w => mkForeignPrim f args w)
458+ let ap = PApp fc (PRef fc (UN "liftPrimIO"))
459+ [pexp (PLam (MN 0 "w")
460+ Placeholder
461+ (PApp fc (PRef fc (UN "mkForeignPrim"))
462+ (fn : args ++
463+ [pexp (PRef fc (MN 0 "w"))])))]
464+ return (dslify i ap)
465+
466+ <|> do f <- simpleExpr syn
467+ fc <- getFC
468+ args <- some (do notEndApp; arg syn)
469+ i <- get
470+ return (dslify i $ PApp fc f args)
471+ <?> "function application"
472+ where
473+ dslify :: IState -> PTerm -> PTerm
474+ dslify i (PApp fc (PRef _ f) [a])
475+ | [d] <- lookupCtxt f (idris_dsls i)
476+ = desugar (syn { dsl_info = d }) i (getTm a)
477+ dslify i t = t
478+
479+{- |Parses a function argument
480+Arg ::=
481+ ImplicitArg
482+ | ConstraintArg
483+ | SimpleExpr
484+ ;
485+-}
486+arg :: SyntaxInfo -> IdrisParser PArg
487+arg syn = implicitArg syn
488+ <|> constraintArg syn
489+ <|> do e <- simpleExpr syn
490+ return (pexp e)
491+ <?> "function argument"
492+
493+{- |Parses an implicit function argument
494+ImplicitArg ::=
495+ '{' Name ('=' Expr)? '}'
496+ ;
497+-}
498+implicitArg :: SyntaxInfo -> IdrisParser PArg
499+implicitArg syn = do lchar '{'
500+ n <- name
501+ fc <- getFC
502+ v <- option (PRef fc n) (do lchar '='
503+ expr syn)
504+ lchar '}'
505+ return (pimp n v)
506+ <?> "implicit function argument"
507+
508+{- |Parses a constraint argument (for selecting a named type class instance)
509+ConstraintArg ::=
510+ '@{' Expr '}'
511+ ;
512+-}
513+constraintArg :: SyntaxInfo -> IdrisParser PArg
514+constraintArg syn = do symbol "@{"
515+ e <- expr syn
516+ symbol "}"
517+ return (pconst e)
518+ <?> "constraint argument"
519+
520+
521+{- |Parses a record field setter expression
522+RecordType ::=
523+ 'record' '{' FieldTypeList '}';
524+
525+FieldTypeList ::=
526+ FieldType
527+ | FieldType ',' FieldTypeList
528+ ;
529+
530+FieldType ::=
531+ FnName '=' Expr
532+ ;
533+-}
534+recordType :: SyntaxInfo -> IdrisParser PTerm
535+recordType syn
536+ = do reserved "record"
537+ lchar '{'
538+ fields <- sepBy1 fieldType (lchar ',')
539+ lchar '}'
540+ fc <- getFC
541+ rec <- optional (simpleExpr syn)
542+ case rec of
543+ Nothing ->
544+ return (PLam (MN 0 "fldx") Placeholder
545+ (applyAll fc fields (PRef fc (MN 0 "fldx"))))
546+ Just v -> return (applyAll fc fields v)
547+ <?> "record setting expression"
548+ where fieldType :: IdrisParser (Name, PTerm)
549+ fieldType = do n <- fnName
550+ lchar '='
551+ e <- expr syn
552+ return (n, e)
553+ <?> "field setter"
554+ applyAll :: FC -> [(Name, PTerm)] -> PTerm -> PTerm
555+ applyAll fc [] x = x
556+ applyAll fc ((n, e) : es) x
557+ = applyAll fc es (PApp fc (PRef fc (mkType n)) [pexp e, pexp x])
558+
559+{- |Creates setters for record types on necessary functions -}
560+mkType :: Name -> Name
561+mkType (UN n) = UN ("set_" ++ n)
562+mkType (MN 0 n) = MN 0 ("set_" ++ n)
563+mkType (NS n s) = NS (mkType n) s
564+
565+{- |Parses a type signature
566+TypeSig ::=
567+ ':' Expr
568+ ;
569+TypeExpr ::= ConstraintList? Expr;
570+ -}
571+typeExpr :: SyntaxInfo -> IdrisParser PTerm
572+typeExpr syn = do cs <- if implicitAllowed syn then constraintList syn else return []
573+ sc <- expr syn
574+ return (bindList (PPi constraint) (map (\x -> (MN 0 "c", x)) cs) sc)
575+ <?> "type signature"
576+
577+{- |Parses a lambda expression
578+Lambda ::=
579+ '\\' TypeOptDeclList '=>' Expr
580+ | '\\' SimpleExprList '=>' Expr
581+ ;
582+SimpleExprList ::=
583+ SimpleExpr
584+ | SimpleExpr ',' SimpleExprList
585+ ;
586+-}
587+lambda :: SyntaxInfo -> IdrisParser PTerm
588+lambda syn = do lchar '\\'
589+ try (do xt <- tyOptDeclList syn
590+ symbol "=>"
591+ sc <- expr syn
592+ return (bindList PLam xt sc)
593+ <|> (do ps <- sepBy (do fc <- getFC
594+ e <- simpleExpr syn
595+ return (fc, e)) (lchar ',')
596+ symbol "=>"
597+ sc <- expr syn
598+ return (pmList (zip [0..] ps) sc)))
599+ <?> "lambda expression"
600+ where pmList :: [(Int, (FC, PTerm))] -> PTerm -> PTerm
601+ pmList [] sc = sc
602+ pmList ((i, (fc, x)) : xs) sc
603+ = PLam (MN i "lamp") Placeholder
604+ (PCase fc (PRef fc (MN i "lamp"))
605+ [(x, pmList xs sc)])
606+
607+{- |Parses a term rewrite expression
608+RewriteTerm ::=
609+ 'rewrite' Expr ('==>' Expr)? 'in' Expr
610+ ;
611+-}
612+rewriteTerm :: SyntaxInfo -> IdrisParser PTerm
613+rewriteTerm syn = do reserved "rewrite"
614+ fc <- getFC
615+ prf <- expr syn
616+ giving <- optional (do symbol "==>"; expr' syn)
617+ reserved "in"; sc <- expr syn
618+ return (PRewrite fc
619+ (PApp fc (PRef fc (UN "sym")) [pexp prf]) sc
620+ giving)
621+ <?> "term rewrite expression"
622+
623+{- |Parses a let binding
624+Let ::=
625+ 'let' Name TypeSig'? '=' Expr 'in' Expr
626+| 'let' Expr' '=' Expr' 'in' Expr
627+
628+TypeSig' ::=
629+ ':' Expr'
630+ ;
631+ -}
632+let_ :: SyntaxInfo -> IdrisParser PTerm
633+let_ syn = try (do reserved "let"; n <- name;
634+ ty <- option Placeholder (do lchar ':'; expr' syn)
635+ lchar '='
636+ v <- expr syn
637+ reserved "in"; sc <- expr syn
638+ return (PLet n ty v sc))
639+ <|> (do reserved "let"; fc <- getFC; pat <- expr' (syn { inPattern = True } )
640+ symbol "="; v <- expr syn
641+ reserved "in"; sc <- expr syn
642+ return (PCase fc v [(pat, sc)]))
643+ <?> "let binding"
644+
645+{- |Parses a quote goal
646+QuoteGoal ::=
647+ 'quoteGoal' Name 'by' Expr 'in' Expr
648+ ;
649+ -}
650+quoteGoal :: SyntaxInfo -> IdrisParser PTerm
651+quoteGoal syn = do reserved "quoteGoal"; n <- name;
652+ reserved "by"
653+ r <- expr syn
654+ reserved "in"
655+ fc <- getFC
656+ sc <- expr syn
657+ return (PGoal fc r n sc)
658+ <?> "quote goal expression"
659+
660+{- |Parses a dependent type signature
661+Pi ::=
662+ '|'? Static? '(' TypeDeclList ')' DocComment '->' Expr
663+ | '|'? Static? '{' TypeDeclList '}' '->' Expr
664+ | '{' 'auto' TypeDeclList '}' '->' Expr
665+ | '{' 'default' TypeDeclList '}' '->' Expr
666+ | '{' 'static' '}' Expr' '->' Expr
667+ ;
668+ -}
669+
670+pi :: SyntaxInfo -> IdrisParser PTerm
671+pi syn =
672+ do lazy <- if implicitAllowed syn -- laziness is top level only
673+ then option False (do lchar '|'; return True)
674+ else return False
675+ st <- static
676+ (do try(lchar '('); xt <- typeDeclList syn; lchar ')'
677+ doc <- option "" (docComment '^')
678+ symbol "->"
679+ sc <- expr syn
680+ return (bindList (PPi (Exp lazy st doc)) xt sc)) <|> (do
681+ lchar '{'
682+ (do reserved "auto"
683+ when (lazy || (st == Static)) $ fail "auto type constraints can not be lazy or static"
684+ xt <- typeDeclList syn
685+ lchar '}'
686+ symbol "->"
687+ sc <- expr syn
688+ return (bindList (PPi
689+ (TacImp False Dynamic (PTactics [Trivial]) "")) xt sc)) <|> (do
690+ reserved "default"
691+ when (lazy || (st == Static)) $ fail "default tactic constraints can not be lazy or static"
692+ script <- simpleExpr syn
693+ xt <- typeDeclList syn
694+ lchar '}'
695+ symbol "->"
696+ sc <- expr syn
697+ return (bindList (PPi (TacImp False Dynamic script "")) xt sc)) <|> (do
698+ reserved "static"
699+ lchar '}'
700+ t <- expr' syn
701+ symbol "->"
702+ sc <- expr syn
703+ return (PPi (Exp False Static "") (MN 42 "__pi_arg") t sc)) <|> (
704+ if implicitAllowed syn then do
705+ xt <- typeDeclList syn
706+ lchar '}'
707+ symbol "->"
708+ sc <- expr syn
709+ return (bindList (PPi (Imp lazy st "")) xt sc)
710+ else do fail "no implicit arguments allowed here"))
711+ <?> "dependent type signature"
712+
713+{- | Parses a type constraint list
714+ConstraintList ::=
715+ '(' Expr_List ')' '=>'
716+ | Expr '=>'
717+ ;
718+-}
719+constraintList :: SyntaxInfo -> IdrisParser [PTerm]
720+constraintList syn = try (do lchar '('
721+ tys <- sepBy1 (expr' (disallowImp syn)) (lchar ',')
722+ lchar ')'
723+ reservedOp "=>"
724+ return tys)
725+ <|> try (do t <- expr (disallowImp syn)
726+ reservedOp "=>"
727+ return [t])
728+ <|> return []
729+ <?> "type constraint list"
730+
731+{- |Parses a type declaration list
732+TypeDeclList ::=
733+ FunctionSignatureList
734+ | NameList TypeSig
735+ ;
736+
737+FunctionSignatureList ::=
738+ Name TypeSig
739+ | Name TypeSig ',' FunctionSignatureList
740+ ;
741+-}
742+typeDeclList :: SyntaxInfo -> IdrisParser [(Name, PTerm)]
743+typeDeclList syn = try (sepBy1 (do x <- fnName
744+ lchar ':'
745+ t <- typeExpr (disallowImp syn)
746+ return (x,t))
747+ (lchar ','))
748+ <|> do ns <- sepBy1 name (lchar ',')
749+ lchar ':'
750+ t <- typeExpr (disallowImp syn)
751+ return (map (\x -> (x, t)) ns)
752+ <?> "type declaration list"
753+
754+{- |Parses a type declaration list with optional parameters
755+TypeOptDeclList ::=
756+ NameOrPlaceholder TypeSig?
757+ | NameOrPlaceholder TypeSig? ',' TypeOptDeclList
758+ ;
759+
760+NameOrPlaceHolder ::= Name | '_';
761+-}
762+tyOptDeclList :: SyntaxInfo -> IdrisParser [(Name, PTerm)]
763+tyOptDeclList syn = sepBy1 (do x <- nameOrPlaceholder
764+ t <- option Placeholder (do lchar ':'
765+ expr syn)
766+ return (x,t))
767+ (lchar ',')
768+ <?> "type declaration list"
769+ where nameOrPlaceholder :: IdrisParser Name
770+ nameOrPlaceholder = fnName
771+ <|> do symbol "_"
772+ return (MN 0 "underscore")
773+ <?> "name or placeholder"
774+
775+{- |Parses a list comprehension
776+Comprehension ::= '[' Expr '|' DoList ']';
777+
778+DoList ::=
779+ Do
780+ | Do ',' DoList
781+ ;
782+-}
783+comprehension :: SyntaxInfo -> IdrisParser PTerm
784+comprehension syn
785+ = do lchar '['
786+ fc <- getFC
787+ pat <- expr syn
788+ lchar '|'
789+ qs <- sepBy1 (do_ syn) (lchar ',')
790+ lchar ']'
791+ return (PDoBlock (map addGuard qs ++
792+ [DoExp fc (PApp fc (PRef fc (UN "return"))
793+ [pexp pat])]))
794+ <?> "list comprehension"
795+ where addGuard :: PDo -> PDo
796+ addGuard (DoExp fc e) = DoExp fc (PApp fc (PRef fc (UN "guard"))
797+ [pexp e])
798+ addGuard x = x
799+
800+{- |Parses a do-block
801+Do' ::= Do KeepTerminator;
802+
803+DoBlock ::=
804+ 'do' OpenBlock Do'+ CloseBlock
805+ ;
806+ -}
807+doBlock :: SyntaxInfo -> IdrisParser PTerm
808+doBlock syn
809+ = do reserved "do"
810+ ds <- indentedBlock (do_ syn)
811+ return (PDoBlock ds)
812+ <?> "do block"
813+
814+{- |Parses an expression inside a do block
815+Do ::=
816+ 'let' Name TypeSig'? '=' Expr
817+ | 'let' Expr' '=' Expr
818+ | Name '<-' Expr
819+ | Expr' '<-' Expr
820+ | Expr
821+ ;
822+-}
823+do_ :: SyntaxInfo -> IdrisParser PDo
824+do_ syn
825+ = try (do reserved "let"
826+ i <- name
827+ ty <- option Placeholder (do lchar ':'
828+ expr' syn)
829+ reservedOp "="
830+ fc <- getFC
831+ e <- expr syn
832+ return (DoLet fc i ty e))
833+ <|> try (do reserved "let"
834+ i <- expr' syn
835+ reservedOp "="
836+ fc <- getFC
837+ sc <- expr syn
838+ return (DoLetP fc i sc))
839+ <|> try (do i <- name
840+ symbol "<-"
841+ fc <- getFC
842+ e <- expr syn;
843+ return (DoBind fc i e))
844+ <|> try (do i <- expr' syn
845+ symbol "<-"
846+ fc <- getFC
847+ e <- expr syn;
848+ return (DoBindP fc i e))
849+ <|> do e <- expr syn
850+ fc <- getFC
851+ return (DoExp fc e)
852+ <?> "do block expression"
853+
854+{- |Parses an expression in idiom brackets
855+Idiom ::= '[|' Expr '|]';
856+-}
857+idiom :: SyntaxInfo -> IdrisParser PTerm
858+idiom syn
859+ = do symbol "[|"
860+ fc <- getFC
861+ e <- expr syn
862+ symbol "|]"
863+ return (PIdiom fc e)
864+ <?> "expression in idiom brackets"
865+
866+{- |Parses a constant or literal expression
867+Constant ::=
868+ 'Integer'
869+ | 'Int'
870+ | 'Char'
871+ | 'Float'
872+ | 'String'
873+ | 'Ptr'
874+ | 'Bits8'
875+ | 'Bits16'
876+ | 'Bits32'
877+ | 'Bits64'
878+ | 'Bits8x16'
879+ | 'Bits16x8'
880+ | 'Bits32x4'
881+ | 'Bits64x2'
882+ | Float_t
883+ | Natural_t
884+ | String_t
885+ | Char_t
886+ ;
887+-}
888+constant :: IdrisParser Core.TT.Const
889+constant = do reserved "Integer";return (AType (ATInt ITBig))
890+ <|> do reserved "Int"; return (AType (ATInt ITNative))
891+ <|> do reserved "Char"; return (AType (ATInt ITChar))
892+ <|> do reserved "Float"; return (AType ATFloat)
893+ <|> do reserved "String"; return StrType
894+ <|> do reserved "Ptr"; return PtrType
895+ <|> do reserved "Bits8"; return (AType (ATInt (ITFixed IT8)))
896+ <|> do reserved "Bits16"; return (AType (ATInt (ITFixed IT16)))
897+ <|> do reserved "Bits32"; return (AType (ATInt (ITFixed IT32)))
898+ <|> do reserved "Bits64"; return (AType (ATInt (ITFixed IT64)))
899+ <|> do reserved "Bits8x16"; return (AType (ATInt (ITVec IT8 16)))
900+ <|> do reserved "Bits16x8"; return (AType (ATInt (ITVec IT16 8)))
901+ <|> do reserved "Bits32x4"; return (AType (ATInt (ITVec IT32 4)))
902+ <|> do reserved "Bits64x2"; return (AType (ATInt (ITVec IT64 2)))
903+ <|> try (do f <- float; return $ Fl f)
904+ <|> try (do i <- natural; return $ BI i)
905+ <|> try (do s <- stringLiteral; return $ Str s)
906+ <|> try (do c <- charLiteral; return $ Ch c)
907+ <?> "constant or literal"
908+
909+{- |Parses a static modifier
910+Static ::=
911+ '[' static ']'
912+;
913+-}
914+static :: IdrisParser Static
915+static = do lchar '['; reserved "static"; lchar ']'; return Static
916+ <|> return Dynamic
917+ <?> "static modifier"
918+
919+{- | Parses a tactic script
920+Tactic ::= 'intro' NameList?
921+ | 'intros'
922+ | 'refine' Name Imp+
923+ | 'mrefine' Name
924+ | 'rewrite' Expr
925+ | 'equiv' Expr
926+ | 'let' Name ':' Expr' '=' Expr
927+ | 'let' Name '=' Expr
928+ | 'focus' Name
929+ | 'exact' Expr
930+ | 'applyTactic' Expr
931+ | 'reflect' Expr
932+ | 'fill' Expr
933+ | 'try' Tactic '|' Tactic
934+ | '{' TacticSeq '}'
935+ | 'compute'
936+ | 'trivial'
937+ | 'solve'
938+ | 'attack'
939+ | 'state'
940+ | 'term'
941+ | 'undo'
942+ | 'qed'
943+ | 'abandon'
944+ | ':' 'q'
945+ ;
946+
947+Imp ::= '?' | '_';
948+
949+TacticSeq ::=
950+ Tactic ';' Tactic
951+ | Tactic ';' TacticSeq
952+ ;
953+
954+-}
955+
956+tactic :: SyntaxInfo -> IdrisParser PTactic
957+tactic syn = do reserved "intro"; ns <- sepBy name (lchar ',')
958+ return $ Intro ns
959+ <|> do reserved "intros"; return Intros
960+ <|> try (do reserved "refine"; n <- name
961+ imps <- some imp
962+ return $ Refine n imps)
963+ <|> do reserved "refine"; n <- name
964+ i <- get
965+ return $ Refine n []
966+ <|> do reserved "mrefine"; n <- name
967+ i <- get
968+ return $ MatchRefine n
969+ <|> do reserved "rewrite"; t <- expr syn;
970+ i <- get
971+ return $ Rewrite (desugar syn i t)
972+ <|> do reserved "equiv"; t <- expr syn;
973+ i <- get
974+ return $ Equiv (desugar syn i t)
975+ <|> try (do reserved "let"; n <- name; lchar ':';
976+ ty <- expr' syn; lchar '='; t <- expr syn;
977+ i <- get
978+ return $ LetTacTy n (desugar syn i ty) (desugar syn i t))
979+ <|> try (do reserved "let"; n <- name; lchar '=';
980+ t <- expr syn;
981+ i <- get
982+ return $ LetTac n (desugar syn i t))
983+ <|> do reserved "focus"; n <- name
984+ return $ Focus n
985+ <|> do reserved "exact"; t <- expr syn;
986+ i <- get
987+ return $ Exact (desugar syn i t)
988+ <|> do reserved "applyTactic"; t <- expr syn;
989+ i <- get
990+ return $ ApplyTactic (desugar syn i t)
991+ <|> do reserved "reflect"; t <- expr syn;
992+ i <- get
993+ return $ Reflect (desugar syn i t)
994+ <|> do reserved "fill"; t <- expr syn;
995+ i <- get
996+ return $ Fill (desugar syn i t)
997+ <|> do reserved "try"; t <- tactic syn;
998+ lchar '|';
999+ t1 <- tactic syn
1000+ return $ Try t t1
1001+ <|> do lchar '{'
1002+ t <- tactic syn;
1003+ lchar ';';
1004+ ts <- sepBy1 (tactic syn) (lchar ';')
1005+ lchar '}'
1006+ return $ TSeq t (mergeSeq ts)
1007+ <|> do reserved "compute"; return Compute
1008+ <|> do reserved "trivial"; return Trivial
1009+ <|> do reserved "solve"; return Solve
1010+ <|> do reserved "attack"; return Attack
1011+ <|> do reserved "state"; return ProofState
1012+ <|> do reserved "term"; return ProofTerm
1013+ <|> do reserved "undo"; return Undo
1014+ <|> do reserved "qed"; return Qed
1015+ <|> do reserved "abandon"; return Abandon
1016+ <|> do lchar ':'; reserved "q"; return Abandon
1017+ <?> "tactic"
1018+ where
1019+ imp :: IdrisParser Bool
1020+ imp = do lchar '?'; return False
1021+ <|> do lchar '_'; return True
1022+ mergeSeq :: [PTactic] -> PTactic
1023+ mergeSeq [t] = t
1024+ mergeSeq (t:ts) = TSeq t (mergeSeq ts)
1025+
1026+{- | Parses a tactic as a whole -}
1027+fullTactic :: SyntaxInfo -> IdrisParser PTactic
1028+fullTactic syn = do t <- tactic syn
1029+ eof
1030+ return t
src/Idris/ParseHelpers.hsnew file+403
@@ -0,0 +1,403 @@
1+{-# LANGUAGE GeneralizedNewtypeDeriving, ConstraintKinds, PatternGuards #-}
2+module Idris.ParseHelpers where
3+
4+import Prelude hiding (pi)
5+
6+import Text.Trifecta.Delta
7+import Text.Trifecta hiding (span, stringLiteral, charLiteral, natural, symbol, char, string, whiteSpace)
8+import Text.Parser.LookAhead
9+import Text.Parser.Expression
10+import qualified Text.Parser.Token as Tok
11+import qualified Text.Parser.Char as Chr
12+import qualified Text.Parser.Token.Highlight as Hi
13+
14+import Idris.AbsSyntax
15+
16+import Core.TT
17+
18+import Control.Applicative
19+import Control.Monad
20+import Control.Monad.State.Strict
21+
22+import Data.Maybe
23+import qualified Data.List.Split as Spl
24+import Data.List
25+import Data.Monoid
26+import Data.Char
27+import qualified Data.HashSet as HS
28+import qualified Data.Text as T
29+import qualified Data.ByteString.UTF8 as UTF8
30+
31+import System.FilePath
32+
33+-- | Idris parser with state used during parsing
34+type IdrisParser = StateT IState IdrisInnerParser
35+
36+newtype IdrisInnerParser a = IdrisInnerParser { runInnerParser :: Parser a }
37+ deriving (Monad, Functor, MonadPlus, Applicative, Alternative, CharParsing, LookAheadParsing, Parsing, DeltaParsing, MarkParsing Delta, Monoid)
38+
39+instance TokenParsing IdrisInnerParser where
40+ someSpace = many (simpleWhiteSpace <|> singleLineComment <|> multiLineComment) *> pure ()
41+
42+-- | Generalized monadic parsing constraint type
43+type MonadicParsing m = (DeltaParsing m, LookAheadParsing m, TokenParsing m, Monad m)
44+
45+{- * Space, comments and literals (token/lexing like parsers) -}
46+
47+-- | Consumes any simple whitespace (any character which satisfies Char.isSpace)
48+simpleWhiteSpace :: MonadicParsing m => m ()
49+simpleWhiteSpace = satisfy isSpace *> pure ()
50+
51+-- | Checks if a charcter is end of line
52+isEol :: Char -> Bool
53+isEol '\n' = True
54+isEol _ = False
55+
56+eol :: MonadicParsing m => m ()
57+eol = (satisfy isEol *> pure ()) <|> lookAhead eof <?> "end of line"
58+
59+-- | Checks if a character is a documentation comment marker
60+isDocCommentMarker :: Char -> Bool
61+isDocCommentMarker '|' = True
62+isDocCommentMarker '^' = True
63+isDocCommentMarker _ = False
64+
65+{- | Consumes a single-line comment
66+ SingleLineComment_t ::= '--' EOL_t
67+ | '--' ~DocCommentMarker_t ~EOL_t* EOL_t
68+ ;
69+ -}
70+singleLineComment :: MonadicParsing m => m ()
71+singleLineComment = try (string "--" *> eol *> pure ())
72+ <|> string "--" *> satisfy (not . isDocCommentMarker) *> many (satisfy (not . isEol)) *> eol *> pure ()
73+ <?> ""
74+
75+{- | Consumes a multi-line comment
76+ MultiLineComment_t ::=
77+ '{ -- }'
78+ | '{ -' ~DocCommentMarker_t InCommentChars_t
79+ ;
80+
81+ InCommentChars_t ::=
82+ '- }'
83+ | MultiLineComment_t InCommentChars_t
84+ | ~'- }'+ InCommentChars_t
85+ ;
86+ -}
87+
88+multiLineComment :: MonadicParsing m => m ()
89+multiLineComment = try (string "{-" *> (string "-}") *> pure ())
90+ <|> string "{-" *> satisfy (not . isDocCommentMarker) *> inCommentChars
91+ <?> ""
92+ where inCommentChars :: MonadicParsing m => m ()
93+ inCommentChars = string "-}" *> pure ()
94+ <|> try (multiLineComment) *> inCommentChars
95+ <|> try (docComment '|') *> inCommentChars
96+ <|> try (docComment '^') *> inCommentChars
97+ <|> skipSome (noneOf startEnd) *> inCommentChars
98+ <|> oneOf startEnd *> inCommentChars
99+ <?> "end of comment"
100+ startEnd :: String
101+ startEnd = "{}-"
102+
103+{-| Parses a documentation comment (similar to haddoc) given a marker character
104+ DocComment_t ::= '--' DocCommentMarker_t ~EOL_t* EOL_t
105+ | '{ -' DocCommentMarket_t ~'- }'* '- }'
106+ ;
107+ -}
108+docComment :: MonadicParsing m => Char -> m String
109+docComment marker | isDocCommentMarker marker = do dc <- docComment' marker; return (T.unpack $ T.strip $ T.pack dc)
110+ | otherwise = fail "internal error: tried to parse a documentation comment with invalid marker"
111+ where docComment' :: MonadicParsing m => Char -> m String
112+ docComment' marker = string "--" *> char marker *> many (satisfy (not . isEol)) <* eol
113+ <|> string "{-" *> char marker *> (manyTill anyChar (try (string "-}")) <?> "end of comment")
114+ <?> ""
115+
116+-- | Parses some white space
117+whiteSpace :: MonadicParsing m => m ()
118+whiteSpace = Tok.whiteSpace
119+
120+-- | Parses a string literal
121+stringLiteral :: MonadicParsing m => m String
122+stringLiteral = Tok.stringLiteral
123+
124+-- | Parses a char literal
125+charLiteral :: MonadicParsing m => m Char
126+charLiteral = Tok.charLiteral
127+
128+-- | Parses a natural number
129+natural :: MonadicParsing m => m Integer
130+natural = Tok.natural
131+
132+-- | Parses an integral number
133+integer :: MonadicParsing m => m Integer
134+integer = Tok.integer
135+
136+-- | Parses a floating point number
137+float :: MonadicParsing m => m Double
138+float = Tok.double
139+
140+{- * Symbols, identifiers, names and operators -}
141+
142+
143+-- | Idris Style for parsing identifiers/reserved keywords
144+idrisStyle :: MonadicParsing m => IdentifierStyle m
145+idrisStyle = IdentifierStyle _styleName _styleStart _styleLetter _styleReserved Hi.Identifier Hi.ReservedIdentifier
146+ where _styleName = "Idris"
147+ _styleStart = satisfy isAlpha
148+ _styleLetter = satisfy isAlphaNum <|> oneOf "_'" <|> (lchar '.')
149+ _styleReserved = HS.fromList ["let", "in", "data", "codata", "record", "Type",
150+ "do", "dsl", "import", "impossible",
151+ "case", "of", "total", "partial", "mutual",
152+ "infix", "infixl", "infixr", "rewrite",
153+ "where", "with", "syntax", "proof", "postulate",
154+ "using", "namespace", "class", "instance",
155+ "public", "private", "abstract", "implicit",
156+ "quoteGoal",
157+ "Int", "Integer", "Float", "Char", "String", "Ptr",
158+ "Bits8", "Bits16", "Bits32", "Bits64",
159+ "Bits8x16", "Bits16x8", "Bits32x4", "Bits64x2"]
160+
161+char :: MonadicParsing m => Char -> m Char
162+char = Chr.char
163+
164+string :: MonadicParsing m => String -> m String
165+string = Chr.string
166+
167+-- | Parses a character as a token
168+lchar :: MonadicParsing m => Char -> m Char
169+lchar = token . char
170+
171+-- | Parses string as a token
172+symbol :: MonadicParsing m => String -> m String
173+symbol = Tok.symbol
174+
175+-- | Parses a reserved identifier
176+reserved :: MonadicParsing m => String -> m ()
177+reserved = Tok.reserve idrisStyle
178+
179+-- Taken from Parsec (c) Daan Leijen 1999-2001, (c) Paolo Martini 2007
180+-- | Parses a reserved operator
181+reservedOp :: MonadicParsing m => String -> m ()
182+reservedOp name = token $ try $
183+ do string name
184+ notFollowedBy (operatorLetter) <?> ("end of " ++ show name)
185+
186+-- | Parses an identifier as a token
187+identifier :: MonadicParsing m => m String
188+identifier = token $ Tok.ident idrisStyle
189+
190+-- | Parses an identifier with possible namespace as a name
191+iName :: MonadicParsing m => [String] -> m Name
192+iName bad = maybeWithNS identifier False bad <?> "name"
193+
194+-- | Parses an string possibly prefixed by a namespace
195+maybeWithNS :: MonadicParsing m => m String -> Bool -> [String] -> m Name
196+maybeWithNS parser ascend bad = do
197+ i <- option "" (lookAhead identifier)
198+ when (i `elem` bad) $ unexpected "reserved identifier"
199+ let transf = if ascend then id else reverse
200+ (x, xs) <- choice (transf (parserNoNS parser : parsersNS parser i))
201+ return $ mkName (x, xs)
202+ where parserNoNS :: MonadicParsing m => m String -> m (String, String)
203+ parserNoNS parser = do x <- parser; return (x, "")
204+ parserNS :: MonadicParsing m => m String -> String -> m (String, String)
205+ parserNS parser ns = do xs <- string ns; lchar '.'; x <- parser; return (x, xs)
206+ parsersNS :: MonadicParsing m => m String -> String -> [m (String, String)]
207+ parsersNS parser i = [try (parserNS parser ns) | ns <- (initsEndAt (=='.') i)]
208+
209+-- | Parses a name
210+name :: IdrisParser Name
211+name = do i <- get
212+ iName (syntax_keywords i)
213+ <?> "name"
214+
215+
216+{- | List of all initial segments in ascending order of a list. Every such
217+ initial segment ends right before an element satisfying the given
218+ condition.
219+-}
220+initsEndAt :: (a -> Bool) -> [a] -> [[a]]
221+initsEndAt p [] = []
222+initsEndAt p (x:xs) | p x = [] : x_inits_xs
223+ | otherwise = x_inits_xs
224+ where x_inits_xs = [x : cs | cs <- initsEndAt p xs]
225+
226+
227+{- | Create a `Name' from a pair of strings representing a base name and its
228+ namespace.
229+-}
230+mkName :: (String, String) -> Name
231+mkName (n, "") = UN n
232+mkName (n, ns) = NS (UN n) (reverse (parseNS ns))
233+ where parseNS x = case span (/= '.') x of
234+ (x, "") -> [x]
235+ (x, '.':y) -> x : parseNS y
236+
237+operatorLetter :: MonadicParsing m => m Char
238+operatorLetter = oneOf ":!#$%&*+./<=>?@\\^|-~"
239+
240+-- | Parses an operator
241+operator :: MonadicParsing m => m String
242+operator = do op <- token . some $ operatorLetter
243+ when (op == ":") $ fail "(:) is not a valid operator"
244+ return op
245+
246+{- * Position helpers -}
247+{- | Get filename from position (returns "(interactive)" when no source file is given) -}
248+fileName :: Delta -> String
249+fileName (Directed fn _ _ _ _) = UTF8.toString fn
250+fileName _ = "(interactive)"
251+
252+{- | Get line number from position -}
253+lineNum :: Delta -> Int
254+lineNum (Lines l _ _ _) = fromIntegral l + 1
255+lineNum (Directed _ l _ _ _) = fromIntegral l + 1
256+
257+{- | Get file position as FC -}
258+getFC :: MonadicParsing m => m FC
259+getFC = do s <- position
260+ let (dir, file) = splitFileName (fileName s)
261+ let f = if dir == addTrailingPathSeparator "." then file else fileName s
262+ return $ FC f (lineNum s)
263+
264+{-* Syntax helpers-}
265+-- | Bind constraints to term
266+bindList :: (Name -> PTerm -> PTerm -> PTerm) -> [(Name, PTerm)] -> PTerm -> PTerm
267+bindList b [] sc = sc
268+bindList b ((n, t):bs) sc = b n t (bindList b bs sc)
269+
270+{- * Layout helpers -}
271+
272+-- | Push indentation to stack
273+pushIndent :: IdrisParser ()
274+pushIndent = do pos <- position
275+ ist <- get
276+ put (ist { indent_stack = (fromIntegral (column pos) + 1) : indent_stack ist })
277+
278+-- | Pops indentation from stack
279+popIndent :: IdrisParser ()
280+popIndent = do ist <- get
281+ let (x : xs) = indent_stack ist
282+ put (ist { indent_stack = xs })
283+
284+
285+-- | Gets current indentation
286+indent :: IdrisParser Int
287+indent = liftM ((+1) . fromIntegral . column) position
288+
289+-- | Gets last indentation
290+lastIndent :: IdrisParser Int
291+lastIndent = do ist <- get
292+ case indent_stack ist of
293+ (x : xs) -> return x
294+ _ -> return 1
295+
296+-- | Applies parser in an indented position
297+indented :: IdrisParser a -> IdrisParser a
298+indented p = notEndBlock *> p <* keepTerminator
299+
300+-- | Applies parser to get a block (which has possibly indented statements)
301+indentedBlock :: IdrisParser a -> IdrisParser [a]
302+indentedBlock p = do openBlock
303+ pushIndent
304+ res <- many (indented p)
305+ popIndent
306+ closeBlock
307+ return res
308+
309+-- | Applies parser to get a block with at least one statement (which has possibly indented statements)
310+indentedBlock1 :: IdrisParser a -> IdrisParser [a]
311+indentedBlock1 p = do openBlock
312+ pushIndent
313+ res <- some (indented p)
314+ popIndent
315+ closeBlock
316+ return res
317+
318+-- | Applies parser to get a block with exactly one (possibly indented) statement
319+indentedBlockS :: IdrisParser a -> IdrisParser a
320+indentedBlockS p = do openBlock
321+ pushIndent
322+ res <- indented p
323+ popIndent
324+ closeBlock
325+ return res
326+
327+
328+-- | Checks if the following character matches provided parser
329+lookAheadMatches :: MonadicParsing m => m a -> m Bool
330+lookAheadMatches p = do match <- lookAhead (optional p)
331+ return $ isJust match
332+
333+-- | Parses a start of block
334+openBlock :: IdrisParser ()
335+openBlock = do lchar '{'
336+ ist <- get
337+ put (ist { brace_stack = Nothing : brace_stack ist })
338+ <|> do ist <- get
339+ lvl' <- indent
340+ -- if we're not indented further, it's an empty block, so
341+ -- increment lvl to ensure we get to the end
342+ let lvl = case brace_stack ist of
343+ Just lvl_old : _ ->
344+ if lvl' <= lvl_old then lvl_old+1
345+ else lvl'
346+ [] -> if lvl' == 1 then 2 else lvl'
347+ _ -> lvl'
348+ put (ist { brace_stack = Just lvl : brace_stack ist })
349+ <?> "start of block"
350+
351+-- | Parses an end of block
352+closeBlock :: IdrisParser ()
353+closeBlock = do ist <- get
354+ bs <- case brace_stack ist of
355+ [] -> eof >> return []
356+ Nothing : xs -> lchar '}' >> return xs <?> "end of block"
357+ Just lvl : xs -> (do i <- indent
358+ isParen <- lookAheadMatches (char ')')
359+ if i >= lvl && not isParen
360+ then fail "not end of block"
361+ else return xs)
362+ <|> (do notOpenBraces
363+ eof
364+ return [])
365+ put (ist { brace_stack = bs })
366+
367+-- | Parses a terminator
368+terminator :: IdrisParser ()
369+terminator = do lchar ';'; popIndent
370+ <|> do c <- indent; l <- lastIndent
371+ if c <= l then popIndent else fail "not a terminator"
372+ <|> do isParen <- lookAheadMatches (oneOf ")}")
373+ if isParen then popIndent else fail "not a termiantor"
374+ <|> lookAhead eof
375+
376+-- | Parses and keeps a terminator
377+keepTerminator :: IdrisParser ()
378+keepTerminator = do lchar ';'; return ()
379+ <|> do c <- indent; l <- lastIndent
380+ unless (c <= l) $ fail "not a terminator"
381+ <|> do isParen <- lookAheadMatches (oneOf ")}|")
382+ unless isParen $ fail "not a terminator"
383+ <|> lookAhead eof
384+
385+-- | Checks if application expression does not end
386+notEndApp :: IdrisParser ()
387+notEndApp = do c <- indent; l <- lastIndent
388+ when (c <= l) (fail "terminator")
389+
390+-- | Checks that it is not end of block
391+notEndBlock :: IdrisParser ()
392+notEndBlock = do ist <- get
393+ case brace_stack ist of
394+ Just lvl : xs -> do i <- indent
395+ isParen <- lookAheadMatches (char ')')
396+ when (i < lvl || isParen) (fail "end of block")
397+ _ -> return ()
398+
399+notOpenBraces :: IdrisParser ()
400+notOpenBraces = do ist <- get
401+ when (hasNothing $ brace_stack ist) $ fail "end of input"
402+ where hasNothing :: [Maybe a] -> Bool
403+ hasNothing = any isNothing
src/Idris/ParseOps.hsnew file+88
@@ -0,0 +1,88 @@
1+{-# LANGUAGE GeneralizedNewtypeDeriving, ConstraintKinds, PatternGuards #-}
2+module Idris.ParseOps where
3+
4+import Prelude hiding (pi)
5+
6+import Text.Trifecta.Delta
7+import Text.Trifecta hiding (span, stringLiteral, charLiteral, natural, symbol, char, string, whiteSpace)
8+import Text.Parser.LookAhead
9+import Text.Parser.Expression
10+import qualified Text.Parser.Token as Tok
11+import qualified Text.Parser.Char as Chr
12+import qualified Text.Parser.Token.Highlight as Hi
13+
14+import Idris.AbsSyntax
15+import Idris.ParseHelpers
16+
17+import Core.TT
18+
19+import Control.Applicative
20+import Control.Monad
21+import Control.Monad.State.Strict
22+
23+import Data.Maybe
24+import qualified Data.List.Split as Spl
25+import Data.List
26+import Data.Monoid
27+import Data.Char
28+import qualified Data.HashSet as HS
29+import qualified Data.Text as T
30+import qualified Data.ByteString.UTF8 as UTF8
31+
32+{- |Creates table for fixity declarations to build expression parser using
33+ pre-build and user-defined operator/fixity declarations -}
34+table :: [FixDecl] -> OperatorTable IdrisParser PTerm
35+table fixes
36+ = [[prefix "-" (\fc x -> PApp fc (PRef fc (UN "-"))
37+ [pexp (PApp fc (PRef fc (UN "fromInteger")) [pexp (PConstant (BI 0))]), pexp x])]]
38+ ++ toTable (reverse fixes) ++
39+ [[backtick],
40+ [binary "=" PEq AssocLeft],
41+ [binary "->" (\fc x y -> PPi expl (MN 42 "__pi_arg") x y) AssocRight]]
42+
43+{- |Calculates table for fixtiy declarations -}
44+toTable :: [FixDecl] -> OperatorTable IdrisParser PTerm
45+toTable fs = map (map toBin)
46+ (groupBy (\ (Fix x _) (Fix y _) -> prec x == prec y) fs)
47+ where toBin (Fix (PrefixN _) op) = prefix op
48+ (\fc x -> PApp fc (PRef fc (UN op)) [pexp x])
49+ toBin (Fix f op)
50+ = binary op (\fc x y -> PApp fc (PRef fc (UN op)) [pexp x,pexp y]) (assoc f)
51+ assoc (Infixl _) = AssocLeft
52+ assoc (Infixr _) = AssocRight
53+ assoc (InfixN _) = AssocNone
54+
55+{- |Binary operator -}
56+binary :: String -> (FC -> PTerm -> PTerm -> PTerm) -> Assoc -> Operator IdrisParser PTerm
57+binary name f = Infix (do fc <- getFC
58+ reservedOp name
59+ doc <- option "" (docComment '^')
60+ return (f fc))
61+
62+{- |Prefix operator -}
63+prefix :: String -> (FC -> PTerm -> PTerm) -> Operator IdrisParser PTerm
64+prefix name f = Prefix (do reservedOp name
65+ fc <- getFC
66+ return (f fc))
67+
68+{- |Backtick operator -}
69+backtick :: Operator IdrisParser PTerm
70+backtick = Infix (do lchar '`'; n <- fnName
71+ lchar '`'
72+ fc <- getFC
73+ return (\x y -> PApp fc (PRef fc n) [pexp x, pexp y])) AssocNone
74+
75+{- | Parses an operator in function position i.e. enclosed by `()', with an
76+ optional namespace
77+
78+ OperatorFront ::= (Identifier_t '.')? '(' Operator_t ')';
79+-}
80+operatorFront :: IdrisParser Name
81+operatorFront = maybeWithNS (lchar '(' *> operator <* lchar ')') False []
82+
83+{- | Parses a function (either normal name or operator)
84+ FnName ::= Name | OperatorFront;
85+-}
86+fnName :: IdrisParser Name
87+fnName = try operatorFront <|> name <?> "function name"
88+
src/Idris/Parser.hs+9−1427
@@ -1,5 +1,8 @@
11{-# LANGUAGE GeneralizedNewtypeDeriving, ConstraintKinds, PatternGuards #-}
2−module Idris.Parser where
2+module Idris.Parser(module Idris.Parser,
3+ module Idris.ParseExpr,
4+ module Idris.ParseHelpers,
5+ module Idris.ParseOps) where
36
47import Prelude hiding (pi)
58
@@ -21,6 +24,11 @@ import Idris.Coverage
2124import Idris.IBC
2225import Idris.Unlit
2326import Idris.Providers
27+
28+import Idris.ParseHelpers
29+import Idris.ParseOps
30+import Idris.ParseExpr
31+
2432import Paths_idris
2533
2634import Util.DynamicLinker
@@ -54,295 +62,6 @@ import System.FilePath
5462 RULE{n} = rule repeated n times
5563-}
5664
57−
58−-- | Idris parser with state used during parsing
59−type IdrisParser = StateT IState IdrisInnerParser
60−
61−newtype IdrisInnerParser a = IdrisInnerParser { runInnerParser :: Parser a }
62− deriving (Monad, Functor, MonadPlus, Applicative, Alternative, CharParsing, LookAheadParsing, Parsing, DeltaParsing, MarkParsing Delta, Monoid)
63−
64−instance TokenParsing IdrisInnerParser where
65− someSpace = many (simpleWhiteSpace <|> singleLineComment <|> multiLineComment) *> pure ()
66−
67−-- | Generalized monadic parsing constraint type
68−type MonadicParsing m = (DeltaParsing m, LookAheadParsing m, TokenParsing m, Monad m)
69−
70−{- * Space, comments and literals (token/lexing like parsers) -}
71−
72−-- | Consumes any simple whitespace (any character which satisfies Char.isSpace)
73−simpleWhiteSpace :: MonadicParsing m => m ()
74−simpleWhiteSpace = satisfy isSpace *> pure ()
75−
76−-- | Checks if a charcter is end of line
77−isEol :: Char -> Bool
78−isEol '\n' = True
79−isEol _ = False
80−
81−eol :: MonadicParsing m => m ()
82−eol = (satisfy isEol *> pure ()) <|> lookAhead eof <?> "end of line"
83−
84−-- | Checks if a character is a documentation comment marker
85−isDocCommentMarker :: Char -> Bool
86−isDocCommentMarker '|' = True
87−isDocCommentMarker '^' = True
88−isDocCommentMarker _ = False
89−
90−{- | Consumes a single-line comment
91− SingleLineComment_t ::= '--' EOL_t
92− | '--' ~DocCommentMarker_t ~EOL_t* EOL_t
93− ;
94− -}
95−singleLineComment :: MonadicParsing m => m ()
96−singleLineComment = try (string "--" *> eol *> pure ())
97− <|> string "--" *> satisfy (not . isDocCommentMarker) *> many (satisfy (not . isEol)) *> eol *> pure ()
98− <?> ""
99−
100−{- | Consumes a multi-line comment
101− MultiLineComment_t ::=
102− '{ -- }'
103− | '{ -' ~DocCommentMarker_t InCommentChars_t
104− ;
105−
106− InCommentChars_t ::=
107− '- }'
108− | MultiLineComment_t InCommentChars_t
109− | ~'- }'+ InCommentChars_t
110− ;
111− -}
112−
113−multiLineComment :: MonadicParsing m => m ()
114−multiLineComment = try (string "{-" *> (string "-}") *> pure ())
115− <|> string "{-" *> satisfy (not . isDocCommentMarker) *> inCommentChars
116− <?> ""
117− where inCommentChars :: MonadicParsing m => m ()
118− inCommentChars = string "-}" *> pure ()
119− <|> try (multiLineComment) *> inCommentChars
120− <|> try (docComment '|') *> inCommentChars
121− <|> try (docComment '^') *> inCommentChars
122− <|> skipSome (noneOf startEnd) *> inCommentChars
123− <|> oneOf startEnd *> inCommentChars
124− <?> "end of comment"
125− startEnd :: String
126− startEnd = "{}-"
127−
128−{-| Parses a documentation comment (similar to haddoc) given a marker character
129− DocComment_t ::= '--' DocCommentMarker_t ~EOL_t* EOL_t
130− | '{ -' DocCommentMarket_t ~'- }'* '- }'
131− ;
132− -}
133−docComment :: MonadicParsing m => Char -> m String
134−docComment marker | isDocCommentMarker marker = do dc <- docComment' marker; return (T.unpack $ T.strip $ T.pack dc)
135− | otherwise = fail "internal error: tried to parse a documentation comment with invalid marker"
136− where docComment' :: MonadicParsing m => Char -> m String
137− docComment' marker = string "--" *> char marker *> many (satisfy (not . isEol)) <* eol
138− <|> string "{-" *> char marker *> (manyTill anyChar (try (string "-}")) <?> "end of comment")
139− <?> ""
140−
141−-- | Parses some white space
142−whiteSpace :: MonadicParsing m => m ()
143−whiteSpace = Tok.whiteSpace
144−
145−-- | Parses a string literal
146−stringLiteral :: MonadicParsing m => m String
147−stringLiteral = Tok.stringLiteral
148−
149−-- | Parses a char literal
150−charLiteral :: MonadicParsing m => m Char
151−charLiteral = Tok.charLiteral
152−
153−-- | Parses a natural number
154−natural :: MonadicParsing m => m Integer
155−natural = Tok.natural
156−
157−-- | Parses an integral number
158−integer :: MonadicParsing m => m Integer
159−integer = Tok.integer
160−
161−-- | Parses a floating point number
162−float :: MonadicParsing m => m Double
163−float = Tok.double
164−
165−{- * Symbols, identifiers, names and operators -}
166−
167−
168−-- | Idris Style for parsing identifiers/reserved keywords
169−idrisStyle :: MonadicParsing m => IdentifierStyle m
170−idrisStyle = IdentifierStyle _styleName _styleStart _styleLetter _styleReserved Hi.Identifier Hi.ReservedIdentifier
171− where _styleName = "Idris"
172− _styleStart = satisfy isAlpha
173− _styleLetter = satisfy isAlphaNum <|> oneOf "_'" <|> (lchar '.')
174− _styleReserved = HS.fromList ["let", "in", "data", "codata", "record", "Type",
175− "do", "dsl", "import", "impossible",
176− "case", "of", "total", "partial", "mutual",
177− "infix", "infixl", "infixr", "rewrite",
178− "where", "with", "syntax", "proof", "postulate",
179− "using", "namespace", "class", "instance",
180− "public", "private", "abstract", "implicit",
181− "quoteGoal",
182− "Int", "Integer", "Float", "Char", "String", "Ptr",
183− "Bits8", "Bits16", "Bits32", "Bits64",
184− "Bits8x16", "Bits16x8", "Bits32x4", "Bits64x2"]
185−
186−char :: MonadicParsing m => Char -> m Char
187−char = Chr.char
188−
189−string :: MonadicParsing m => String -> m String
190−string = Chr.string
191−
192−-- | Parses a character as a token
193−lchar :: MonadicParsing m => Char -> m Char
194−lchar = token . char
195−
196−-- | Parses string as a token
197−symbol :: MonadicParsing m => String -> m String
198−symbol = Tok.symbol
199−
200−-- | Parses a reserved identifier
201−reserved :: MonadicParsing m => String -> m ()
202−reserved = Tok.reserve idrisStyle
203−
204−-- Taken from Parsec (c) Daan Leijen 1999-2001, (c) Paolo Martini 2007
205−-- | Parses a reserved operator
206−reservedOp :: MonadicParsing m => String -> m ()
207−reservedOp name = token $ try $
208− do string name
209− notFollowedBy (operatorLetter) <?> ("end of " ++ show name)
210−
211−-- | Parses an identifier as a token
212−identifier :: MonadicParsing m => m String
213−identifier = token $ Tok.ident idrisStyle
214−
215−-- | Parses an identifier with possible namespace as a name
216−iName :: MonadicParsing m => [String] -> m Name
217−iName bad = maybeWithNS identifier False bad <?> "name"
218−
219−-- | Parses an string possibly prefixed by a namespace
220−maybeWithNS :: MonadicParsing m => m String -> Bool -> [String] -> m Name
221−maybeWithNS parser ascend bad = do
222− i <- option "" (lookAhead identifier)
223− when (i `elem` bad) $ unexpected "reserved identifier"
224− let transf = if ascend then id else reverse
225− (x, xs) <- choice (transf (parserNoNS parser : parsersNS parser i))
226− return $ mkName (x, xs)
227− where parserNoNS :: MonadicParsing m => m String -> m (String, String)
228− parserNoNS parser = do x <- parser; return (x, "")
229− parserNS :: MonadicParsing m => m String -> String -> m (String, String)
230− parserNS parser ns = do xs <- string ns; lchar '.'; x <- parser; return (x, xs)
231− parsersNS :: MonadicParsing m => m String -> String -> [m (String, String)]
232− parsersNS parser i = [try (parserNS parser ns) | ns <- (initsEndAt (=='.') i)]
233−
234−-- | Parses a name
235−name :: IdrisParser Name
236−name = do i <- get
237− iName (syntax_keywords i)
238− <?> "name"
239−
240−
241−{- | List of all initial segments in ascending order of a list. Every such
242− initial segment ends right before an element satisfying the given
243− condition.
244−-}
245−initsEndAt :: (a -> Bool) -> [a] -> [[a]]
246−initsEndAt p [] = []
247−initsEndAt p (x:xs) | p x = [] : x_inits_xs
248− | otherwise = x_inits_xs
249− where x_inits_xs = [x : cs | cs <- initsEndAt p xs]
250−
251−
252−{- | Create a `Name' from a pair of strings representing a base name and its
253− namespace.
254−-}
255−mkName :: (String, String) -> Name
256−mkName (n, "") = UN n
257−mkName (n, ns) = NS (UN n) (reverse (parseNS ns))
258− where parseNS x = case span (/= '.') x of
259− (x, "") -> [x]
260− (x, '.':y) -> x : parseNS y
261−
262−operatorLetter :: MonadicParsing m => m Char
263−operatorLetter = oneOf ":!#$%&*+./<=>?@\\^|-~"
264−
265−-- | Parses an operator
266−operator :: MonadicParsing m => m String
267−operator = do op <- token . some $ operatorLetter
268− when (op == ":") $ fail "(:) is not a valid operator"
269− return op
270−
271−{- * Position helpers -}
272−{- | Get filename from position (returns "(interactive)" when no source file is given) -}
273−fileName :: Delta -> String
274−fileName (Directed fn _ _ _ _) = UTF8.toString fn
275−fileName _ = "(interactive)"
276−
277−{- | Get line number from position -}
278−lineNum :: Delta -> Int
279−lineNum (Lines l _ _ _) = fromIntegral l + 1
280−lineNum (Directed _ l _ _ _) = fromIntegral l + 1
281−
282−{- | Get file position as FC -}
283−getFC :: MonadicParsing m => m FC
284−getFC = do s <- position
285− let (dir, file) = splitFileName (fileName s)
286− let f = if dir == addTrailingPathSeparator "." then file else fileName s
287− return $ FC f (lineNum s)
288−
289−{-* Syntax helpers-}
290−-- | Bind constraints to term
291−bindList :: (Name -> PTerm -> PTerm -> PTerm) -> [(Name, PTerm)] -> PTerm -> PTerm
292−bindList b [] sc = sc
293−bindList b ((n, t):bs) sc = b n t (bindList b bs sc)
294−
295−{- |Creates table for fixtiy declarations to build expression parser using
296− pre-build and user-defined operator/fixity declarations -}
297−table :: [FixDecl] -> OperatorTable IdrisParser PTerm
298−table fixes
299− = [[prefix "-" (\fc x -> PApp fc (PRef fc (UN "-"))
300− [pexp (PApp fc (PRef fc (UN "fromInteger")) [pexp (PConstant (BI 0))]), pexp x])]]
301− ++ toTable (reverse fixes) ++
302− [[backtick],
303− [binary "=" PEq AssocLeft],
304− [binary "->" (\fc x y -> PPi expl (MN 42 "__pi_arg") x y) AssocRight]]
305−
306−{- |Calculates table for fixtiy declarations -}
307−toTable :: [FixDecl] -> OperatorTable IdrisParser PTerm
308−toTable fs = map (map toBin)
309− (groupBy (\ (Fix x _) (Fix y _) -> prec x == prec y) fs)
310− where toBin (Fix (PrefixN _) op) = prefix op
311− (\fc x -> PApp fc (PRef fc (UN op)) [pexp x])
312− toBin (Fix f op)
313− = binary op (\fc x y -> PApp fc (PRef fc (UN op)) [pexp x,pexp y]) (assoc f)
314− assoc (Infixl _) = AssocLeft
315− assoc (Infixr _) = AssocRight
316− assoc (InfixN _) = AssocNone
317−
318−{- |Binary operator -}
319−binary :: String -> (FC -> PTerm -> PTerm -> PTerm) -> Assoc -> Operator IdrisParser PTerm
320−binary name f = Infix (do fc <- getFC
321− reservedOp name
322− doc <- option "" (docComment '^')
323− return (f fc))
324−
325−{- |Prefix operator -}
326−prefix :: String -> (FC -> PTerm -> PTerm) -> Operator IdrisParser PTerm
327−prefix name f = Prefix (do reservedOp name
328− fc <- getFC
329− return (f fc))
330−
331−{- |Backtick operator -}
332−backtick :: Operator IdrisParser PTerm
333−backtick = Infix (do lchar '`'; n <- fnName
334− lchar '`'
335− fc <- getFC
336− return (\x y -> PApp fc (PRef fc n) [pexp x, pexp y])) AssocNone
337−
338−-- | Allow implicit type declarations
339−allowImp :: SyntaxInfo -> SyntaxInfo
340−allowImp syn = syn { implicitAllowed = True }
341−
342−-- | Disallow implicit type declarations
343−disallowImp :: SyntaxInfo -> SyntaxInfo
344−disallowImp syn = syn { implicitAllowed = False }
345−
34665-- | Adds accessibility option for function
34766addAcc :: Name -> Maybe Accessibility -> IdrisParser ()
34867addAcc n a = do i <- get
@@ -362,140 +81,6 @@ accData a n ns = do addAcc n a
36281fixErrorMsg :: String -> [String] -> String
36382fixErrorMsg msg fixes = msg ++ ", possible fixes:\n" ++ (concat $ intersperse "\n\nor\n\n" fixes)
36483
365−{- * Layout helpers -}
366−
367−-- | Push indentation to stack
368−pushIndent :: IdrisParser ()
369−pushIndent = do pos <- position
370− ist <- get
371− put (ist { indent_stack = (fromIntegral (column pos) + 1) : indent_stack ist })
372−
373−-- | Pops indentation from stack
374−popIndent :: IdrisParser ()
375−popIndent = do ist <- get
376− let (x : xs) = indent_stack ist
377− put (ist { indent_stack = xs })
378−
379−-- | Gets current indentation
380−indent :: IdrisParser Int
381−indent = liftM ((+1) . fromIntegral . column) position
382−
383−-- | Gets last indentation
384−lastIndent :: IdrisParser Int
385−lastIndent = do ist <- get
386− case indent_stack ist of
387− (x : xs) -> return x
388− _ -> return 1
389−
390−-- | Applies parser in an indented position
391−indented :: IdrisParser a -> IdrisParser a
392−indented p = notEndBlock *> p <* keepTerminator
393−
394−-- | Applies parser to get a block (which has possibly indented statements)
395−indentedBlock :: IdrisParser a -> IdrisParser [a]
396−indentedBlock p = do openBlock
397− pushIndent
398− res <- many (indented p)
399− popIndent
400− closeBlock
401− return res
402−
403−-- | Applies parser to get a block with at least one statement (which has possibly indented statements)
404−indentedBlock1 :: IdrisParser a -> IdrisParser [a]
405−indentedBlock1 p = do openBlock
406− pushIndent
407− res <- some (indented p)
408− popIndent
409− closeBlock
410− return res
411−
412−-- | Applies parser to get a block with exactly one (possibly indented) statement
413−indentedBlockS :: IdrisParser a -> IdrisParser a
414−indentedBlockS p = do openBlock
415− pushIndent
416− res <- indented p
417− popIndent
418− closeBlock
419− return res
420−
421−
422−-- | Checks if the following character matches provided parser
423−lookAheadMatches :: MonadicParsing m => m a -> m Bool
424−lookAheadMatches p = do match <- lookAhead (optional p)
425− return $ isJust match
426−
427−-- | Parses a start of block
428−openBlock :: IdrisParser ()
429−openBlock = do lchar '{'
430− ist <- get
431− put (ist { brace_stack = Nothing : brace_stack ist })
432− <|> do ist <- get
433− lvl' <- indent
434− -- if we're not indented further, it's an empty block, so
435− -- increment lvl to ensure we get to the end
436− let lvl = case brace_stack ist of
437− Just lvl_old : _ ->
438− if lvl' <= lvl_old then lvl_old+1
439− else lvl'
440− [] -> if lvl' == 1 then 2 else lvl'
441− _ -> lvl'
442− put (ist { brace_stack = Just lvl : brace_stack ist })
443− <?> "start of block"
444−
445−-- | Parses an end of block
446−closeBlock :: IdrisParser ()
447−closeBlock = do ist <- get
448− bs <- case brace_stack ist of
449− [] -> eof >> return []
450− Nothing : xs -> lchar '}' >> return xs <?> "end of block"
451− Just lvl : xs -> (do i <- indent
452− isParen <- lookAheadMatches (char ')')
453− if i >= lvl && not isParen
454− then fail "not end of block"
455− else return xs)
456− <|> (do notOpenBraces
457− eof
458− return [])
459− put (ist { brace_stack = bs })
460−
461−-- | Parses a terminator
462−terminator :: IdrisParser ()
463−terminator = do lchar ';'; popIndent
464− <|> do c <- indent; l <- lastIndent
465− if c <= l then popIndent else fail "not a terminator"
466− <|> do isParen <- lookAheadMatches (oneOf ")}")
467− if isParen then popIndent else fail "not a termiantor"
468− <|> lookAhead eof
469−
470−-- | Parses and keeps a terminator
471−keepTerminator :: IdrisParser ()
472−keepTerminator = do lchar ';'; return ()
473− <|> do c <- indent; l <- lastIndent
474− unless (c <= l) $ fail "not a terminator"
475− <|> do isParen <- lookAheadMatches (oneOf ")}|")
476− unless isParen $ fail "not a terminator"
477− <|> lookAhead eof
478−
479−-- | Checks if application expression does not end
480−notEndApp :: IdrisParser ()
481−notEndApp = do c <- indent; l <- lastIndent
482− when (c <= l) (fail "terminator")
483−
484−-- | Checks that it is not end of block
485−notEndBlock :: IdrisParser ()
486−notEndBlock = do ist <- get
487− case brace_stack ist of
488− Just lvl : xs -> do i <- indent
489− isParen <- lookAheadMatches (char ')')
490− when (i < lvl || isParen) (fail "end of block")
491− _ -> return ()
492−
493−notOpenBraces :: IdrisParser ()
494−notOpenBraces = do ist <- get
495− when (hasNothing $ brace_stack ist) $ fail "end of input"
496− where hasNothing :: [Maybe a] -> Bool
497− hasNothing = any isNothing
498−
49984{- * Main grammar -}
50085
50186{- | Parses module definition
@@ -757,20 +342,6 @@ fnOpts opts
757342 return (Just (fromInteger reds)))
758343 return (n, t)
759344
760−{- | Parses an operator in function position i.e. enclosed by `()', with an
761− optional namespace
762−
763− OperatorFront ::= (Identifier_t '.')? '(' Operator_t ')';
764−-}
765−operatorFront :: IdrisParser Name
766−operatorFront = maybeWithNS (lchar '(' *> operator <* lchar ')') False []
767−
768−{- | Parses a function (either normal name or operator)
769− FnName ::= Name | OperatorFront;
770−-}
771−fnName :: IdrisParser Name
772−fnName = try operatorFront <|> name <?> "function name"
773−
774345{- | Parses an accessibilty modifier (e.g. public, private) -}
775346accessibility :: IdrisParser Accessibility
776347accessibility = do reserved "public"; return Public
@@ -989,695 +560,6 @@ instance_ syn = do reserved "instance"; fc <- getFC
989560 <?> "instance name"
990561
991562
992−{- | Parses an expression as a whole
993− FullExpr ::= Expr EOF_t;
994− -}
995−fullExpr :: SyntaxInfo -> IdrisParser PTerm
996−fullExpr syn = do x <- expr syn
997− eof
998− i <- get
999− return $ desugar syn i x
1000−
1001−
1002−{- |Parses an expression
1003− Expr ::= Expr';
1004−-}
1005−expr :: SyntaxInfo -> IdrisParser PTerm
1006−expr syn = do i <- get
1007− buildExpressionParser (table (idris_infixes i)) (expr' syn)
1008−
1009−{- | Parses either an internally defined expression or
1010− a user-defined one
1011−
1012−Expr' ::= "External (User-defined) Syntax"
1013− | InternalExpr;
1014−
1015− -}
1016−expr' :: SyntaxInfo -> IdrisParser PTerm
1017−expr' syn = try (externalExpr syn)
1018− <|> internalExpr syn
1019− <?> "expression"
1020−
1021−{- | Parses a user-defined expression -}
1022−externalExpr :: SyntaxInfo -> IdrisParser PTerm
1023−externalExpr syn = do i <- get
1024− extensions syn (syntax_rules i)
1025− <?> "user-defined expression"
1026−
1027−{- | Parses a simple user-defined expression -}
1028−simpleExternalExpr :: SyntaxInfo -> IdrisParser PTerm
1029−simpleExternalExpr syn = do i <- get
1030− extensions syn (filter isSimple (syntax_rules i))
1031− where
1032− isSimple (Rule (Expr x:xs) _ _) = False
1033− isSimple (Rule (SimpleExpr x:xs) _ _) = False
1034− isSimple (Rule [Keyword _] _ _) = True
1035− isSimple (Rule [Symbol _] _ _) = True
1036− isSimple (Rule (_:xs) _ _) = case last xs of
1037− Keyword _ -> True
1038− Symbol _ -> True
1039− _ -> False
1040− isSimple _ = False
1041−
1042−{- | Tries to parse a user-defined expression given a list of syntactic extensions -}
1043−extensions :: SyntaxInfo -> [Syntax] -> IdrisParser PTerm
1044−extensions syn rules = choice (map (try . extension syn) (filter isValid rules))
1045− <?> "user-defined expression"
1046− where
1047− isValid :: Syntax -> Bool
1048− isValid (Rule _ _ AnySyntax) = True
1049− isValid (Rule _ _ PatternSyntax) = inPattern syn
1050− isValid (Rule _ _ TermSyntax) = not (inPattern syn)
1051−
1052−
1053−data SynMatch = SynTm PTerm | SynBind Name
1054−
1055−{- | Tries to parse an expression given a user-defined rule -}
1056−extension :: SyntaxInfo -> Syntax -> IdrisParser PTerm
1057−extension syn (Rule ssym ptm _)
1058− = do smap <- mapM extensionSymbol ssym
1059− let ns = mapMaybe id smap
1060− return (update ns ptm) -- updated with smap
1061− where
1062− extensionSymbol :: SSymbol -> IdrisParser (Maybe (Name, SynMatch))
1063− extensionSymbol (Keyword n) = do reserved (show n); return Nothing
1064− extensionSymbol (Expr n) = do tm <- expr syn
1065− return $ Just (n, SynTm tm)
1066− extensionSymbol (SimpleExpr n) = do tm <- simpleExpr syn
1067− return $ Just (n, SynTm tm)
1068− extensionSymbol (Binding n) = do b <- name
1069− return $ Just (n, SynBind b)
1070− extensionSymbol (Symbol s) = do symbol s
1071− return Nothing
1072− dropn :: Name -> [(Name, a)] -> [(Name, a)]
1073− dropn n [] = []
1074− dropn n ((x,t) : xs) | n == x = xs
1075− | otherwise = (x,t):dropn n xs
1076−
1077− updateB :: [(Name, SynMatch)] -> Name -> Name
1078− updateB ns n = case lookup n ns of
1079− Just (SynBind t) -> t
1080− _ -> n
1081−
1082− update :: [(Name, SynMatch)] -> PTerm -> PTerm
1083− update ns (PRef fc n) = case lookup n ns of
1084− Just (SynTm t) -> t
1085− _ -> PRef fc n
1086− update ns (PLam n ty sc) = PLam (updateB ns n) (update ns ty) (update (dropn n ns) sc)
1087− update ns (PPi p n ty sc) = PPi p (updateB ns n) (update ns ty) (update (dropn n ns) sc)
1088− update ns (PLet n ty val sc) = PLet (updateB ns n) (update ns ty) (update ns val)
1089− (update (dropn n ns) sc)
1090− update ns (PApp fc t args) = PApp fc (update ns t) (map (fmap (update ns)) args)
1091− update ns (PCase fc c opts) = PCase fc (update ns c) (map (pmap (update ns)) opts)
1092− update ns (PPair fc l r) = PPair fc (update ns l) (update ns r)
1093− update ns (PDPair fc l t r) = PDPair fc (update ns l) (update ns t) (update ns r)
1094− update ns (PAlternative a as) = PAlternative a (map (update ns) as)
1095− update ns (PHidden t) = PHidden (update ns t)
1096− update ns (PDoBlock ds) = PDoBlock $ upd ns ds
1097− where upd :: [(Name, SynMatch)] -> [PDo] -> [PDo]
1098− upd ns (DoExp fc t : ds) = DoExp fc (update ns t) : upd ns ds
1099− upd ns (DoBind fc n t : ds) = DoBind fc n (update ns t) : upd (dropn n ns) ds
1100− upd ns (DoLet fc n ty t : ds) = DoLet fc n (update ns ty) (update ns t)
1101− : upd (dropn n ns) ds
1102− upd ns (DoBindP fc i t : ds) = DoBindP fc (update ns i) (update ns t)
1103− : upd ns ds
1104− upd ns (DoLetP fc i t : ds) = DoLetP fc (update ns i) (update ns t)
1105− : upd ns ds
1106− update ns (PGoal fc r n sc) = PGoal fc (update ns r) n (update ns sc)
1107− update ns t = t
1108−
1109−{- |Parses a (normal) built-in expression
1110−
1111−InternalExpr ::=
1112− App
1113− | MatchApp
1114− | UnifyLog
1115− | RecordType
1116− | SimpleExpr
1117− | Lambda
1118− | QuoteGoal
1119− | Let
1120− | RewriteTerm
1121− | Pi
1122− | DoBlock
1123− ;
1124−-}
1125−internalExpr :: SyntaxInfo -> IdrisParser PTerm
1126−internalExpr syn =
1127− try (app syn)
1128− <|> try (matchApp syn)
1129− <|> try (unifyLog syn)
1130− <|> recordType syn
1131− <|> try (simpleExpr syn)
1132− <|> lambda syn
1133− <|> quoteGoal syn
1134− <|> let_ syn
1135− <|> rewriteTerm syn
1136− <|> pi syn
1137− <|> doBlock syn
1138− <?> "expression"
1139−
1140−{- | Parses a case expression
1141−CaseExpr ::=
1142− 'case' Expr 'of' OpenBlock CaseOption+ CloseBlock;
1143−-}
1144−caseExpr :: SyntaxInfo -> IdrisParser PTerm
1145−caseExpr syn = do reserved "case"; fc <- getFC
1146− scr <- expr syn; reserved "of";
1147− opts <- indentedBlock1 (caseOption syn)
1148− return (PCase fc scr opts)
1149− <?> "case expression"
1150−
1151−{- | Parses a case in a case expression
1152−CaseOption ::=
1153− Expr '=>' Expr Terminator
1154− ;
1155−-}
1156−caseOption :: SyntaxInfo -> IdrisParser (PTerm, PTerm)
1157−caseOption syn = do lhs <- expr (syn { inPattern = True })
1158− symbol "=>"; r <- expr syn
1159− return (lhs, r)
1160− <?> "case option"
1161−
1162−{- | Parses a proof block
1163−ProofExpr ::=
1164− 'proof' OpenBlock Tactic'* CloseBlock
1165− ;
1166−-}
1167−proofExpr :: SyntaxInfo -> IdrisParser PTerm
1168−proofExpr syn = do reserved "proof"
1169− ts <- indentedBlock (tactic syn)
1170− return $ PProof ts
1171− <?> "proof block"
1172−
1173−{- | Parses a tactics block
1174−TacticsExpr :=
1175− 'tactics' OpenBlock Tactic'* CloseBlock
1176−;
1177−-}
1178−tacticsExpr :: SyntaxInfo -> IdrisParser PTerm
1179−tacticsExpr syn = do reserved "tactics"
1180− ts <- indentedBlock (tactic syn)
1181− return $ PTactics ts
1182− <?> "tactics block"
1183−
1184−{- | Parses a simple expresion
1185−SimpleExpr ::=
1186− '![' Term ']'
1187− | '?' Name
1188− | % 'instance'
1189− | 'refl' ('{' Expr '}')?
1190− | ProofExpr
1191− | TacticsExpr
1192− | CaseExpr
1193− | FnName
1194− | List
1195− | Comprehension
1196− | Alt
1197− | Idiom
1198− | '(' Bracketed
1199− | Constant
1200− | Type
1201− | '_|_'
1202− | '_'
1203− | {- External (User-defined) Simple Expression -}
1204− ;
1205−-}
1206−simpleExpr :: SyntaxInfo -> IdrisParser PTerm
1207−simpleExpr syn =
1208− {-try (do symbol "!["; t <- term; lchar ']'; return $ PQuote t)
1209− <|>-} do lchar '?'; x <- name; return (PMetavar x)
1210− <|> do lchar '%'; fc <- getFC; reserved "instance"; return (PResolveTC fc)
1211− <|> do reserved "refl"; fc <- getFC;
1212− tm <- option Placeholder (do lchar '{'; t <- expr syn; lchar '}';
1213− return t)
1214− return (PRefl fc tm)
1215− <|> proofExpr syn
1216− <|> tacticsExpr syn
1217− <|> caseExpr syn
1218− <|> try (do fc <- getFC
1219− x <- fnName
1220− return (PRef fc x))
1221− <|> try (listExpr syn)
1222− <|> try (comprehension syn)
1223− <|> try (alt syn)
1224− <|> try (idiom syn)
1225− <|> do lchar '('
1226− bracketed (disallowImp syn)
1227− <|> try (do c <- constant
1228− fc <- getFC
1229− return (modifyConst syn fc (PConstant c)))
1230− <|> do reserved "Type"; return PType
1231− <|> try (do symbol "_|_"
1232− fc <- getFC
1233− return (PFalse fc))
1234− <|> do lchar '_'; return Placeholder
1235− <|> simpleExternalExpr syn
1236− <?> "expression"
1237−
1238−
1239−{- |Parses the rest of an expression in braces
1240−Bracketed ::=
1241− ')'
1242− | Expr ')'
1243− | ExprList ')'
1244− | Expr '**' Expr ')'
1245− | Operator Expr ')'
1246− | Expr Operator ')'
1247− | Name ':' Expr '**' Expr ')'
1248− ;
1249−-}
1250−bracketed :: SyntaxInfo -> IdrisParser PTerm
1251−bracketed syn =
1252− do lchar ')'
1253− fc <- getFC
1254− return $ PTrue fc
1255− <|>
1256− try (do l <- expr syn
1257− lchar ')'
1258− return l)
1259− <|> do (l, fc) <- try (do
1260− l <- expr syn
1261− fc <- getFC
1262− lchar ','
1263− return (l, fc))
1264− rs <- sepBy1 (do fc' <- getFC; r <- expr syn; return (r, fc')) (lchar ',')
1265− lchar ')'
1266− return $ PPair fc l (mergePairs rs)
1267− <|> do (l, fc) <- try (do
1268− l <- expr syn
1269− fc <- getFC
1270− reservedOp "**"
1271− return (l, fc))
1272− r <- expr syn
1273− lchar ')'
1274− return (PDPair fc l Placeholder r)
1275− <|> try(do fc0 <- getFC
1276− l <- simpleExpr syn
1277− o <- operator
1278− lchar ')'
1279− return $ PLam (MN 1000 "ARG") Placeholder
1280− (PApp fc0 (PRef fc0 (UN o)) [pexp l,
1281− pexp (PRef fc0 (MN 1000 "ARG"))]))
1282− <|> try(do fc <- getFC; o <- operator; e <- expr syn; lchar ')'
1283− return $ PLam (MN 1000 "ARG") Placeholder
1284− (PApp fc (PRef fc (UN o)) [pexp (PRef fc (MN 1000 "ARG")),
1285− pexp e]))
1286− <|> try (do ln <- name; lchar ':'
1287− lty <- expr syn
1288− reservedOp "**"
1289− fc <- getFC
1290− r <- expr syn
1291− lchar ')'
1292− return (PDPair fc (PRef fc ln) lty r))
1293− <?> "end of braced expression"
1294− where mergePairs :: [(PTerm, FC)] -> PTerm
1295− mergePairs [(t, fc)] = t
1296− mergePairs ((t, fc):rs) = PPair fc t (mergePairs rs)
1297−
1298−-- bit of a hack here. If the integer doesn't fit in an Int, treat it as a
1299−-- big integer, otherwise try fromInteger and the constants as alternatives.
1300−-- a better solution would be to fix fromInteger to work with Integer, as the
1301−-- name suggests, rather than Int
1302−{-| Finds optimal type for integer constant -}
1303−modifyConst :: SyntaxInfo -> FC -> PTerm -> PTerm
1304−modifyConst syn fc (PConstant (BI x))
1305− | not (inPattern syn)
1306− = PAlternative False
1307− (PApp fc (PRef fc (UN "fromInteger")) [pexp (PConstant (BI (fromInteger x)))]
1308− : consts)
1309− | otherwise = PAlternative False consts
1310− where
1311− consts = [ PConstant (BI x)
1312− , PConstant (I (fromInteger x))
1313− , PConstant (B8 (fromInteger x))
1314− , PConstant (B16 (fromInteger x))
1315− , PConstant (B32 (fromInteger x))
1316− , PConstant (B64 (fromInteger x))
1317− ]
1318−modifyConst syn fc x = x
1319−
1320−{- | Parses a list literal expression e.g. [1,2,3]
1321−ListExpr ::=
1322− '[' ExprList? ']'
1323−;
1324−
1325−ExprList ::=
1326− Expr
1327− | Expr ',' ExprList
1328− ;
1329−
1330− -}
1331−listExpr :: SyntaxInfo -> IdrisParser PTerm
1332−listExpr syn = do lchar '['; fc <- getFC; xs <- sepBy (expr syn) (lchar ','); lchar ']'
1333− return (mkList fc xs)
1334− <?> "list expression"
1335− where
1336− mkList :: FC -> [PTerm] -> PTerm
1337− mkList fc [] = PRef fc (UN "Nil")
1338− mkList fc (x : xs) = PApp fc (PRef fc (UN "::")) [pexp x, pexp (mkList fc xs)]
1339−
1340−
1341−{- | Parses an alternative expression
1342− Alt ::= '(|' Expr_List '|)';
1343−
1344− Expr_List ::=
1345− Expr'
1346− | Expr' ',' Expr_List
1347− ;
1348−-}
1349−alt :: SyntaxInfo -> IdrisParser PTerm
1350−alt syn = do symbol "(|"; alts <- sepBy1 (expr' syn) (lchar ','); symbol "|)"
1351− return (PAlternative False alts)
1352−
1353−{- | Parses a possibly hidden simple expression
1354−HSimpleExpr ::=
1355− '.' SimpleExpr
1356− | SimpleExpr
1357− ;
1358−-}
1359−hsimpleExpr :: SyntaxInfo -> IdrisParser PTerm
1360−hsimpleExpr syn =
1361− do lchar '.'
1362− e <- simpleExpr syn
1363− return $ PHidden e
1364− <|> simpleExpr syn
1365− <?> "expression"
1366−
1367−{- | Parses a matching application expression
1368−MatchApp ::=
1369− SimpleExpr '<==' FnName
1370− ;
1371−-}
1372−matchApp :: SyntaxInfo -> IdrisParser PTerm
1373−matchApp syn = do ty <- simpleExpr syn
1374− symbol "<=="
1375− fc <- getFC
1376− f <- fnName
1377− return (PLet (MN 0 "match")
1378− ty
1379− (PMatchApp fc f)
1380− (PRef fc (MN 0 "match")))
1381− <?> "matching application expression"
1382−
1383−{- | Parses a unification log expression
1384−UnifyLog ::=
1385− '%' 'unifyLog' SimpleExpr
1386− ;
1387−-}
1388−unifyLog :: SyntaxInfo -> IdrisParser PTerm
1389−unifyLog syn = do lchar '%'; reserved "unifyLog";
1390− tm <- simpleExpr syn
1391− return (PUnifyLog tm)
1392− <?> "unification log expression"
1393−
1394−{- | Parses a function application expression
1395−App ::=
1396− 'mkForeign' Arg Arg*
1397− | SimpleExpr Arg+
1398− ;
1399−-}
1400−app :: SyntaxInfo -> IdrisParser PTerm
1401−app syn = do f <- reserved "mkForeign"
1402− fc <- getFC
1403− fn <- arg syn
1404− args <- many (do notEndApp; arg syn)
1405− i <- get
1406− -- mkForeign f args ==>
1407− -- liftPrimIO (\w => mkForeignPrim f args w)
1408− let ap = PApp fc (PRef fc (UN "liftPrimIO"))
1409− [pexp (PLam (MN 0 "w")
1410− Placeholder
1411− (PApp fc (PRef fc (UN "mkForeignPrim"))
1412− (fn : args ++
1413− [pexp (PRef fc (MN 0 "w"))])))]
1414− return (dslify i ap)
1415−
1416− <|> do f <- simpleExpr syn
1417− fc <- getFC
1418− args <- some (do notEndApp; arg syn)
1419− i <- get
1420− return (dslify i $ PApp fc f args)
1421− <?> "function application"
1422− where
1423− dslify :: IState -> PTerm -> PTerm
1424− dslify i (PApp fc (PRef _ f) [a])
1425− | [d] <- lookupCtxt f (idris_dsls i)
1426− = desugar (syn { dsl_info = d }) i (getTm a)
1427− dslify i t = t
1428−
1429−{- |Parses a function argument
1430−Arg ::=
1431− ImplicitArg
1432− | ConstraintArg
1433− | SimpleExpr
1434− ;
1435−-}
1436−arg :: SyntaxInfo -> IdrisParser PArg
1437−arg syn = implicitArg syn
1438− <|> constraintArg syn
1439− <|> do e <- simpleExpr syn
1440− return (pexp e)
1441− <?> "function argument"
1442−
1443−{- |Parses an implicit function argument
1444−ImplicitArg ::=
1445− '{' Name ('=' Expr)? '}'
1446− ;
1447−-}
1448−implicitArg :: SyntaxInfo -> IdrisParser PArg
1449−implicitArg syn = do lchar '{'
1450− n <- name
1451− fc <- getFC
1452− v <- option (PRef fc n) (do lchar '='
1453− expr syn)
1454− lchar '}'
1455− return (pimp n v)
1456− <?> "implicit function argument"
1457−
1458−{- |Parses a constraint argument (for selecting a named type class instance)
1459−ConstraintArg ::=
1460− '@{' Expr '}'
1461− ;
1462−-}
1463−constraintArg :: SyntaxInfo -> IdrisParser PArg
1464−constraintArg syn = do symbol "@{"
1465− e <- expr syn
1466− symbol "}"
1467− return (pconst e)
1468− <?> "constraint argument"
1469−
1470−
1471−{- |Parses a record field setter expression
1472−RecordType ::=
1473− 'record' '{' FieldTypeList '}';
1474−
1475−FieldTypeList ::=
1476− FieldType
1477− | FieldType ',' FieldTypeList
1478− ;
1479−
1480−FieldType ::=
1481− FnName '=' Expr
1482− ;
1483−-}
1484−recordType :: SyntaxInfo -> IdrisParser PTerm
1485−recordType syn
1486− = do reserved "record"
1487− lchar '{'
1488− fields <- sepBy1 fieldType (lchar ',')
1489− lchar '}'
1490− fc <- getFC
1491− rec <- optional (simpleExpr syn)
1492− case rec of
1493− Nothing ->
1494− return (PLam (MN 0 "fldx") Placeholder
1495− (applyAll fc fields (PRef fc (MN 0 "fldx"))))
1496− Just v -> return (applyAll fc fields v)
1497− <?> "record setting expression"
1498− where fieldType :: IdrisParser (Name, PTerm)
1499− fieldType = do n <- fnName
1500− lchar '='
1501− e <- expr syn
1502− return (n, e)
1503− <?> "field setter"
1504− applyAll :: FC -> [(Name, PTerm)] -> PTerm -> PTerm
1505− applyAll fc [] x = x
1506− applyAll fc ((n, e) : es) x
1507− = applyAll fc es (PApp fc (PRef fc (mkType n)) [pexp e, pexp x])
1508−
1509−{- |Creates setters for record types on necessary functions -}
1510−mkType :: Name -> Name
1511−mkType (UN n) = UN ("set_" ++ n)
1512−mkType (MN 0 n) = MN 0 ("set_" ++ n)
1513−mkType (NS n s) = NS (mkType n) s
1514−
1515−{- |Parses a type signature
1516−TypeSig ::=
1517− ':' Expr
1518− ;
1519−TypeExpr ::= ConstraintList? Expr;
1520− -}
1521−typeExpr :: SyntaxInfo -> IdrisParser PTerm
1522−typeExpr syn = do cs <- if implicitAllowed syn then constraintList syn else return []
1523− sc <- expr syn
1524− return (bindList (PPi constraint) (map (\x -> (MN 0 "c", x)) cs) sc)
1525− <?> "type signature"
1526−
1527−{- |Parses a lambda expression
1528−Lambda ::=
1529− '\\' TypeOptDeclList '=>' Expr
1530− | '\\' SimpleExprList '=>' Expr
1531− ;
1532−SimpleExprList ::=
1533− SimpleExpr
1534− | SimpleExpr ',' SimpleExprList
1535− ;
1536−-}
1537−lambda :: SyntaxInfo -> IdrisParser PTerm
1538−lambda syn = do lchar '\\'
1539− try (do xt <- tyOptDeclList syn
1540− symbol "=>"
1541− sc <- expr syn
1542− return (bindList PLam xt sc)
1543− <|> (do ps <- sepBy (do fc <- getFC
1544− e <- simpleExpr syn
1545− return (fc, e)) (lchar ',')
1546− symbol "=>"
1547− sc <- expr syn
1548− return (pmList (zip [0..] ps) sc)))
1549− <?> "lambda expression"
1550− where pmList :: [(Int, (FC, PTerm))] -> PTerm -> PTerm
1551− pmList [] sc = sc
1552− pmList ((i, (fc, x)) : xs) sc
1553− = PLam (MN i "lamp") Placeholder
1554− (PCase fc (PRef fc (MN i "lamp"))
1555− [(x, pmList xs sc)])
1556−
1557−{- |Parses a term rewrite expression
1558−RewriteTerm ::=
1559− 'rewrite' Expr ('==>' Expr)? 'in' Expr
1560− ;
1561−-}
1562−rewriteTerm :: SyntaxInfo -> IdrisParser PTerm
1563−rewriteTerm syn = do reserved "rewrite"
1564− fc <- getFC
1565− prf <- expr syn
1566− giving <- optional (do symbol "==>"; expr' syn)
1567− reserved "in"; sc <- expr syn
1568− return (PRewrite fc
1569− (PApp fc (PRef fc (UN "sym")) [pexp prf]) sc
1570− giving)
1571− <?> "term rewrite expression"
1572−
1573−{- |Parses a let binding
1574−Let ::=
1575− 'let' Name TypeSig'? '=' Expr 'in' Expr
1576−| 'let' Expr' '=' Expr' 'in' Expr
1577−
1578−TypeSig' ::=
1579− ':' Expr'
1580− ;
1581− -}
1582−let_ :: SyntaxInfo -> IdrisParser PTerm
1583−let_ syn = try (do reserved "let"; n <- name;
1584− ty <- option Placeholder (do lchar ':'; expr' syn)
1585− lchar '='
1586− v <- expr syn
1587− reserved "in"; sc <- expr syn
1588− return (PLet n ty v sc))
1589− <|> (do reserved "let"; fc <- getFC; pat <- expr' (syn { inPattern = True } )
1590− symbol "="; v <- expr syn
1591− reserved "in"; sc <- expr syn
1592− return (PCase fc v [(pat, sc)]))
1593− <?> "let binding"
1594−
1595−{- |Parses a quote goal
1596−QuoteGoal ::=
1597− 'quoteGoal' Name 'by' Expr 'in' Expr
1598− ;
1599− -}
1600−quoteGoal :: SyntaxInfo -> IdrisParser PTerm
1601−quoteGoal syn = do reserved "quoteGoal"; n <- name;
1602− reserved "by"
1603− r <- expr syn
1604− reserved "in"
1605− fc <- getFC
1606− sc <- expr syn
1607− return (PGoal fc r n sc)
1608− <?> "quote goal expression"
1609−
1610−{- |Parses a dependent type signature
1611−Pi ::=
1612− '|'? Static? '(' TypeDeclList ')' DocComment '->' Expr
1613− | '|'? Static? '{' TypeDeclList '}' '->' Expr
1614− | '{' 'auto' TypeDeclList '}' '->' Expr
1615− | '{' 'default' TypeDeclList '}' '->' Expr
1616− | '{' 'static' '}' Expr' '->' Expr
1617− ;
1618− -}
1619−
1620−pi :: SyntaxInfo -> IdrisParser PTerm
1621−pi syn =
1622− do lazy <- if implicitAllowed syn -- laziness is top level only
1623− then option False (do lchar '|'; return True)
1624− else return False
1625− st <- static
1626− (do try(lchar '('); xt <- typeDeclList syn; lchar ')'
1627− doc <- option "" (docComment '^')
1628− symbol "->"
1629− sc <- expr syn
1630− return (bindList (PPi (Exp lazy st doc)) xt sc)) <|> (do
1631− lchar '{'
1632− (do reserved "auto"
1633− when (lazy || (st == Static)) $ fail "auto type constraints can not be lazy or static"
1634− xt <- typeDeclList syn
1635− lchar '}'
1636− symbol "->"
1637− sc <- expr syn
1638− return (bindList (PPi
1639− (TacImp False Dynamic (PTactics [Trivial]) "")) xt sc)) <|> (do
1640− reserved "default"
1641− when (lazy || (st == Static)) $ fail "default tactic constraints can not be lazy or static"
1642− script <- simpleExpr syn
1643− xt <- typeDeclList syn
1644− lchar '}'
1645− symbol "->"
1646− sc <- expr syn
1647− return (bindList (PPi (TacImp False Dynamic script "")) xt sc)) <|> (do
1648− reserved "static"
1649− lchar '}'
1650− t <- expr' syn
1651− symbol "->"
1652− sc <- expr syn
1653− return (PPi (Exp False Static "") (MN 42 "__pi_arg") t sc)) <|> (
1654− if implicitAllowed syn then do
1655− xt <- typeDeclList syn
1656− lchar '}'
1657− symbol "->"
1658− sc <- expr syn
1659− return (bindList (PPi (Imp lazy st "")) xt sc)
1660− else do fail "no implicit arguments allowed here"))
1661− <?> "dependent type signature"
1662−
1663−{- | Parses a type constraint list
1664−ConstraintList ::=
1665− '(' Expr_List ')' '=>'
1666− | Expr '=>'
1667− ;
1668−-}
1669−constraintList :: SyntaxInfo -> IdrisParser [PTerm]
1670−constraintList syn = try (do lchar '('
1671− tys <- sepBy1 (expr' (disallowImp syn)) (lchar ',')
1672− lchar ')'
1673− reservedOp "=>"
1674− return tys)
1675− <|> try (do t <- expr (disallowImp syn)
1676− reservedOp "=>"
1677− return [t])
1678− <|> return []
1679− <?> "type constraint list"
1680−
1681563{- | Parses a using declaration list
1682564UsingDeclList ::=
1683565 UsingDeclList'
@@ -1719,194 +601,6 @@ usingDecl syn = try (do x <- fnName
1719601 return (UConstraint c xs)
1720602 <?> "using declaration"
1721603
1722−{- |Parses a type declaration list
1723−TypeDeclList ::=
1724− FunctionSignatureList
1725− | NameList TypeSig
1726− ;
1727−
1728−FunctionSignatureList ::=
1729− Name TypeSig
1730− | Name TypeSig ',' FunctionSignatureList
1731− ;
1732−-}
1733−typeDeclList :: SyntaxInfo -> IdrisParser [(Name, PTerm)]
1734−typeDeclList syn = try (sepBy1 (do x <- fnName
1735− lchar ':'
1736− t <- typeExpr (disallowImp syn)
1737− return (x,t))
1738− (lchar ','))
1739− <|> do ns <- sepBy1 name (lchar ',')
1740− lchar ':'
1741− t <- typeExpr (disallowImp syn)
1742− return (map (\x -> (x, t)) ns)
1743− <?> "type declaration list"
1744−
1745−{- |Parses a type declaration list with optional parameters
1746−TypeOptDeclList ::=
1747− NameOrPlaceholder TypeSig?
1748− | NameOrPlaceholder TypeSig? ',' TypeOptDeclList
1749− ;
1750−
1751−NameOrPlaceHolder ::= Name | '_';
1752−-}
1753−tyOptDeclList :: SyntaxInfo -> IdrisParser [(Name, PTerm)]
1754−tyOptDeclList syn = sepBy1 (do x <- nameOrPlaceholder
1755− t <- option Placeholder (do lchar ':'
1756− expr syn)
1757− return (x,t))
1758− (lchar ',')
1759− <?> "type declaration list"
1760− where nameOrPlaceholder :: IdrisParser Name
1761− nameOrPlaceholder = fnName
1762− <|> do symbol "_"
1763− return (MN 0 "underscore")
1764− <?> "name or placeholder"
1765−
1766−{- |Parses a list comprehension
1767−Comprehension ::= '[' Expr '|' DoList ']';
1768−
1769−DoList ::=
1770− Do
1771− | Do ',' DoList
1772− ;
1773−-}
1774−comprehension :: SyntaxInfo -> IdrisParser PTerm
1775−comprehension syn
1776− = do lchar '['
1777− fc <- getFC
1778− pat <- expr syn
1779− lchar '|'
1780− qs <- sepBy1 (do_ syn) (lchar ',')
1781− lchar ']'
1782− return (PDoBlock (map addGuard qs ++
1783− [DoExp fc (PApp fc (PRef fc (UN "return"))
1784− [pexp pat])]))
1785− <?> "list comprehension"
1786− where addGuard :: PDo -> PDo
1787− addGuard (DoExp fc e) = DoExp fc (PApp fc (PRef fc (UN "guard"))
1788− [pexp e])
1789− addGuard x = x
1790−
1791−{- |Parses a do-block
1792−Do' ::= Do KeepTerminator;
1793−
1794−DoBlock ::=
1795− 'do' OpenBlock Do'+ CloseBlock
1796− ;
1797− -}
1798−doBlock :: SyntaxInfo -> IdrisParser PTerm
1799−doBlock syn
1800− = do reserved "do"
1801− ds <- indentedBlock (do_ syn)
1802− return (PDoBlock ds)
1803− <?> "do block"
1804−
1805−{- |Parses an expression inside a do block
1806−Do ::=
1807− 'let' Name TypeSig'? '=' Expr
1808− | 'let' Expr' '=' Expr
1809− | Name '<-' Expr
1810− | Expr' '<-' Expr
1811− | Expr
1812− ;
1813−-}
1814−do_ :: SyntaxInfo -> IdrisParser PDo
1815−do_ syn
1816− = try (do reserved "let"
1817− i <- name
1818− ty <- option Placeholder (do lchar ':'
1819− expr' syn)
1820− reservedOp "="
1821− fc <- getFC
1822− e <- expr syn
1823− return (DoLet fc i ty e))
1824− <|> try (do reserved "let"
1825− i <- expr' syn
1826− reservedOp "="
1827− fc <- getFC
1828− sc <- expr syn
1829− return (DoLetP fc i sc))
1830− <|> try (do i <- name
1831− symbol "<-"
1832− fc <- getFC
1833− e <- expr syn;
1834− return (DoBind fc i e))
1835− <|> try (do i <- expr' syn
1836− symbol "<-"
1837− fc <- getFC
1838− e <- expr syn;
1839− return (DoBindP fc i e))
1840− <|> do e <- expr syn
1841− fc <- getFC
1842− return (DoExp fc e)
1843− <?> "do block expression"
1844−
1845−{- |Parses an expression in idiom brackets
1846−Idiom ::= '[|' Expr '|]';
1847−-}
1848−idiom :: SyntaxInfo -> IdrisParser PTerm
1849−idiom syn
1850− = do symbol "[|"
1851− fc <- getFC
1852− e <- expr syn
1853− symbol "|]"
1854− return (PIdiom fc e)
1855− <?> "expression in idiom brackets"
1856−
1857−{- |Parses a constant or literal expression
1858−Constant ::=
1859− 'Integer'
1860− | 'Int'
1861− | 'Char'
1862− | 'Float'
1863− | 'String'
1864− | 'Ptr'
1865− | 'Bits8'
1866− | 'Bits16'
1867− | 'Bits32'
1868− | 'Bits64'
1869− | 'Bits8x16'
1870− | 'Bits16x8'
1871− | 'Bits32x4'
1872− | 'Bits64x2'
1873− | Float_t
1874− | Natural_t
1875− | String_t
1876− | Char_t
1877− ;
1878−-}
1879−constant :: IdrisParser Core.TT.Const
1880−constant = do reserved "Integer";return (AType (ATInt ITBig))
1881− <|> do reserved "Int"; return (AType (ATInt ITNative))
1882− <|> do reserved "Char"; return (AType (ATInt ITChar))
1883− <|> do reserved "Float"; return (AType ATFloat)
1884− <|> do reserved "String"; return StrType
1885− <|> do reserved "Ptr"; return PtrType
1886− <|> do reserved "Bits8"; return (AType (ATInt (ITFixed IT8)))
1887− <|> do reserved "Bits16"; return (AType (ATInt (ITFixed IT16)))
1888− <|> do reserved "Bits32"; return (AType (ATInt (ITFixed IT32)))
1889− <|> do reserved "Bits64"; return (AType (ATInt (ITFixed IT64)))
1890− <|> do reserved "Bits8x16"; return (AType (ATInt (ITVec IT8 16)))
1891− <|> do reserved "Bits16x8"; return (AType (ATInt (ITVec IT16 8)))
1892− <|> do reserved "Bits32x4"; return (AType (ATInt (ITVec IT32 4)))
1893− <|> do reserved "Bits64x2"; return (AType (ATInt (ITVec IT64 2)))
1894− <|> try (do f <- float; return $ Fl f)
1895− <|> try (do i <- natural; return $ BI i)
1896− <|> try (do s <- stringLiteral; return $ Str s)
1897− <|> try (do c <- charLiteral; return $ Ch c)
1898− <?> "constant or literal"
1899−
1900−{- |Parses a static modifier
1901−Static ::=
1902− '[' static ']'
1903−;
1904−-}
1905−static :: IdrisParser Static
1906−static = do lchar '['; reserved "static"; lchar ']'; return Static
1907− <|> return Dynamic
1908− <?> "static modifier"
1909−
1910604{- |Parses a record type declaration
1911605Record ::=
1912606 DocComment Accessibility? 'record' FnName TypeSig 'where' OpenBlock Constructor KeepTerminator CloseBlock;
@@ -2423,118 +1117,6 @@ transform syn = do try (lchar '%' *> reserved "transform")
24231117 return [PTransform fc False l r]
24241118 <?> "transform"
24251119
2426−{- | Parses a tactic script
2427−Tactic ::= 'intro' NameList?
2428− | 'intros'
2429− | 'refine' Name Imp+
2430− | 'mrefine' Name
2431− | 'rewrite' Expr
2432− | 'equiv' Expr
2433− | 'let' Name ':' Expr' '=' Expr
2434− | 'let' Name '=' Expr
2435− | 'focus' Name
2436− | 'exact' Expr
2437− | 'applyTactic' Expr
2438− | 'reflect' Expr
2439− | 'fill' Expr
2440− | 'try' Tactic '|' Tactic
2441− | '{' TacticSeq '}'
2442− | 'compute'
2443− | 'trivial'
2444− | 'solve'
2445− | 'attack'
2446− | 'state'
2447− | 'term'
2448− | 'undo'
2449− | 'qed'
2450− | 'abandon'
2451− | ':' 'q'
2452− ;
2453−
2454−Imp ::= '?' | '_';
2455−
2456−TacticSeq ::=
2457− Tactic ';' Tactic
2458− | Tactic ';' TacticSeq
2459− ;
2460−
2461−-}
2462−
2463−tactic :: SyntaxInfo -> IdrisParser PTactic
2464−tactic syn = do reserved "intro"; ns <- sepBy name (lchar ',')
2465− return $ Intro ns
2466− <|> do reserved "intros"; return Intros
2467− <|> try (do reserved "refine"; n <- name
2468− imps <- some imp
2469− return $ Refine n imps)
2470− <|> do reserved "refine"; n <- name
2471− i <- get
2472− return $ Refine n []
2473− <|> do reserved "mrefine"; n <- name
2474− i <- get
2475− return $ MatchRefine n
2476− <|> do reserved "rewrite"; t <- expr syn;
2477− i <- get
2478− return $ Rewrite (desugar syn i t)
2479− <|> do reserved "equiv"; t <- expr syn;
2480− i <- get
2481− return $ Equiv (desugar syn i t)
2482− <|> try (do reserved "let"; n <- name; lchar ':';
2483− ty <- expr' syn; lchar '='; t <- expr syn;
2484− i <- get
2485− return $ LetTacTy n (desugar syn i ty) (desugar syn i t))
2486− <|> try (do reserved "let"; n <- name; lchar '=';
2487− t <- expr syn;
2488− i <- get
2489− return $ LetTac n (desugar syn i t))
2490− <|> do reserved "focus"; n <- name
2491− return $ Focus n
2492− <|> do reserved "exact"; t <- expr syn;
2493− i <- get
2494− return $ Exact (desugar syn i t)
2495− <|> do reserved "applyTactic"; t <- expr syn;
2496− i <- get
2497− return $ ApplyTactic (desugar syn i t)
2498− <|> do reserved "reflect"; t <- expr syn;
2499− i <- get
2500− return $ Reflect (desugar syn i t)
2501− <|> do reserved "fill"; t <- expr syn;
2502− i <- get
2503− return $ Fill (desugar syn i t)
2504− <|> do reserved "try"; t <- tactic syn;
2505− lchar '|';
2506− t1 <- tactic syn
2507− return $ Try t t1
2508− <|> do lchar '{'
2509− t <- tactic syn;
2510− lchar ';';
2511− ts <- sepBy1 (tactic syn) (lchar ';')
2512− lchar '}'
2513− return $ TSeq t (mergeSeq ts)
2514− <|> do reserved "compute"; return Compute
2515− <|> do reserved "trivial"; return Trivial
2516− <|> do reserved "solve"; return Solve
2517− <|> do reserved "attack"; return Attack
2518− <|> do reserved "state"; return ProofState
2519− <|> do reserved "term"; return ProofTerm
2520− <|> do reserved "undo"; return Undo
2521− <|> do reserved "qed"; return Qed
2522− <|> do reserved "abandon"; return Abandon
2523− <|> do lchar ':'; reserved "q"; return Abandon
2524− <?> "tactic"
2525− where
2526− imp :: IdrisParser Bool
2527− imp = do lchar '?'; return False
2528− <|> do lchar '_'; return True
2529− mergeSeq :: [PTactic] -> PTactic
2530− mergeSeq [t] = t
2531− mergeSeq (t:ts) = TSeq t (mergeSeq ts)
2532−
2533−{- | Parses a tactic as a whole -}
2534−fullTactic :: SyntaxInfo -> IdrisParser PTactic
2535−fullTactic syn = do t <- tactic syn
2536− eof
2537− return t
25381120
25391121{- * Loading and parsing -}
25401122{- | Parses an expression from input -}
src/Idris/REPL.hs+8
@@ -21,6 +21,7 @@ import Idris.IdeSlave
2121import Idris.Chaser
2222import Idris.Imports
2323import Idris.Colours
24+import Idris.Inliner
2425
2526import Paths_idris
2627import Util.System
@@ -491,6 +492,13 @@ process fn (HNF t) = do (tm, ty) <- elabVal toplevel False t
491492 ist <- getIState
492493 let tm' = hnf ctxt [] tm
493494 iResult (show (delab ist tm'))
495+process fn (TestInline t) = do (tm, ty) <- elabVal toplevel False t
496+ ctxt <- getContext
497+ ist <- getIState
498+ let tm' = inlineTerm ist tm
499+ imp <- impShow
500+ c <- colourise
501+ iResult (showImp (Just ist) imp c (delab ist tm'))
494502process fn TTShell = do ist <- getIState
495503 let shst = initState (tt_ctxt ist)
496504 runShell shst
src/Idris/REPLParser.hs+1
@@ -55,6 +55,7 @@ pCmd = do P.whiteSpace; try (do cmd ["q", "quit"]; eof; return Quit)
5555 <|> try (do cmd ["cd"]; f <- many anyChar; return (ChangeDirectory f))
5656 <|> try (do cmd ["spec"]; P.whiteSpace; t <- P.fullExpr defaultSyntax; return (Spec t))
5757 <|> try (do cmd ["hnf"]; P.whiteSpace; t <- P.fullExpr defaultSyntax; return (HNF t))
58+ <|> try (do cmd ["inline"]; P.whiteSpace; t <- P.fullExpr defaultSyntax; return (TestInline t))
5859 <|> try (do cmd ["doc"]; n <- P.fnName; eof; return (DocStr n))
5960 <|> try (do cmd ["d", "def"]; some (P.char ' ') ; n <- P.fnName; eof; return (Defn n))
6061 <|> try (do cmd ["total"]; do n <- P.fnName; eof; return (TotCheck n))