on master help sign in
Split Parser.hs into several files
67fb9ccEdwin Brady
idris.cabal+3
@@ -309,6 +309,9 @@ Executable idris
309 , Idris.Imports
309 , Idris.Imports
310 , Idris.Inliner
310 , Idris.Inliner
311 , Idris.Parser
311 , Idris.Parser
312+ , Idris.ParseHelpers
313+ , Idris.ParseOps
314+ , Idris.ParseExpr
312 , Idris.PartialEval
315 , Idris.PartialEval
313 , Idris.Primitives
316 , Idris.Primitives
314 , Idris.Prover
317 , Idris.Prover
src/Idris/AbsSyntaxTree.hs+1
@@ -225,6 +225,7 @@ data Command = Quit
225 | LogLvl Int
225 | LogLvl Int
226 | Spec PTerm
226 | Spec PTerm
227 | HNF PTerm
227 | HNF PTerm
228+ | TestInline PTerm
228 | Defn Name
229 | Defn Name
229 | Info Name
230 | Info Name
230 | Missing Name
231 | 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 @@
1{-# LANGUAGE GeneralizedNewtypeDeriving, ConstraintKinds, PatternGuards #-}
1{-# 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
3
6
4import Prelude hiding (pi)
7import Prelude hiding (pi)
5
8
@@ -21,6 +24,11 @@ import Idris.Coverage
21import Idris.IBC
24import Idris.IBC
22import Idris.Unlit
25import Idris.Unlit
23import Idris.Providers
26import Idris.Providers
27+
28+import Idris.ParseHelpers
29+import Idris.ParseOps
30+import Idris.ParseExpr
31+
24import Paths_idris
32import Paths_idris
25
33
26import Util.DynamicLinker
34import Util.DynamicLinker
@@ -54,295 +62,6 @@ import System.FilePath
54 RULE{n} = rule repeated n times
62 RULE{n} = rule repeated n times
55-}
63-}
56
64
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−
346-- | Adds accessibility option for function
65-- | Adds accessibility option for function
347addAcc :: Name -> Maybe Accessibility -> IdrisParser ()
66addAcc :: Name -> Maybe Accessibility -> IdrisParser ()
348addAcc n a = do i <- get
67addAcc n a = do i <- get
@@ -362,140 +81,6 @@ accData a n ns = do addAcc n a
362fixErrorMsg :: String -> [String] -> String
81fixErrorMsg :: String -> [String] -> String
363fixErrorMsg msg fixes = msg ++ ", possible fixes:\n" ++ (concat $ intersperse "\n\nor\n\n" fixes)
82fixErrorMsg msg fixes = msg ++ ", possible fixes:\n" ++ (concat $ intersperse "\n\nor\n\n" fixes)
364
83
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−
499{- * Main grammar -}
84{- * Main grammar -}
500
85
501{- | Parses module definition
86{- | Parses module definition
@@ -757,20 +342,6 @@ fnOpts opts
757 return (Just (fromInteger reds)))
342 return (Just (fromInteger reds)))
758 return (n, t)
343 return (n, t)
759
344
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−
774{- | Parses an accessibilty modifier (e.g. public, private) -}
345{- | Parses an accessibilty modifier (e.g. public, private) -}
775accessibility :: IdrisParser Accessibility
346accessibility :: IdrisParser Accessibility
776accessibility = do reserved "public"; return Public
347accessibility = do reserved "public"; return Public
@@ -989,695 +560,6 @@ instance_ syn = do reserved "instance"; fc <- getFC
989 <?> "instance name"
560 <?> "instance name"
990
561
991
562
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−
1681{- | Parses a using declaration list
563{- | Parses a using declaration list
1682UsingDeclList ::=
564UsingDeclList ::=
1683 UsingDeclList'
565 UsingDeclList'
@@ -1719,194 +601,6 @@ usingDecl syn = try (do x <- fnName
1719 return (UConstraint c xs)
601 return (UConstraint c xs)
1720 <?> "using declaration"
602 <?> "using declaration"
1721
603
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−
1910{- |Parses a record type declaration
604{- |Parses a record type declaration
1911Record ::=
605Record ::=
1912 DocComment Accessibility? 'record' FnName TypeSig 'where' OpenBlock Constructor KeepTerminator CloseBlock;
606 DocComment Accessibility? 'record' FnName TypeSig 'where' OpenBlock Constructor KeepTerminator CloseBlock;
@@ -2423,118 +1117,6 @@ transform syn = do try (lchar '%' *> reserved "transform")
2423 return [PTransform fc False l r]
1117 return [PTransform fc False l r]
2424 <?> "transform"
1118 <?> "transform"
2425
1119
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
2538
1120
2539{- * Loading and parsing -}
1121{- * Loading and parsing -}
2540{- | Parses an expression from input -}
1122{- | Parses an expression from input -}
src/Idris/REPL.hs+8
@@ -21,6 +21,7 @@ import Idris.IdeSlave
21import Idris.Chaser
21import Idris.Chaser
22import Idris.Imports
22import Idris.Imports
23import Idris.Colours
23import Idris.Colours
24+import Idris.Inliner
24
25
25import Paths_idris
26import Paths_idris
26import Util.System
27import Util.System
@@ -491,6 +492,13 @@ process fn (HNF t) = do (tm, ty) <- elabVal toplevel False t
491 ist <- getIState
492 ist <- getIState
492 let tm' = hnf ctxt [] tm
493 let tm' = hnf ctxt [] tm
493 iResult (show (delab ist tm'))
494 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'))
494process fn TTShell = do ist <- getIState
502process fn TTShell = do ist <- getIState
495 let shst = initState (tt_ctxt ist)
503 let shst = initState (tt_ctxt ist)
496 runShell shst
504 runShell shst
src/Idris/REPLParser.hs+1
@@ -55,6 +55,7 @@ pCmd = do P.whiteSpace; try (do cmd ["q", "quit"]; eof; return Quit)
55 <|> try (do cmd ["cd"]; f <- many anyChar; return (ChangeDirectory f))
55 <|> try (do cmd ["cd"]; f <- many anyChar; return (ChangeDirectory f))
56 <|> try (do cmd ["spec"]; P.whiteSpace; t <- P.fullExpr defaultSyntax; return (Spec t))
56 <|> try (do cmd ["spec"]; P.whiteSpace; t <- P.fullExpr defaultSyntax; return (Spec t))
57 <|> try (do cmd ["hnf"]; P.whiteSpace; t <- P.fullExpr defaultSyntax; return (HNF t))
57 <|> 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))
58 <|> try (do cmd ["doc"]; n <- P.fnName; eof; return (DocStr n))
59 <|> try (do cmd ["doc"]; n <- P.fnName; eof; return (DocStr n))
59 <|> try (do cmd ["d", "def"]; some (P.char ' ') ; n <- P.fnName; eof; return (Defn n))
60 <|> try (do cmd ["d", "def"]; some (P.char ' ') ; n <- P.fnName; eof; return (Defn n))
60 <|> try (do cmd ["total"]; do n <- P.fnName; eof; return (TotCheck n))
61 <|> try (do cmd ["total"]; do n <- P.fnName; eof; return (TotCheck n))