1{-# LANGUAGE PatternGuards #-}
3module Idris.ElabTerm where
6import Idris.AbsSyntaxTree
10import Idris.ProofSearch
11import Idris.Output (pshow)
13import Idris.Core.Elaborate hiding (Tactic(..))
15import Idris.Core.Evaluate
16import Idris.Core.Unify
17import Idris.Core.Typecheck (check, recheck)
18import Idris.ErrReverse (errReverse)
19import Idris.ElabQuasiquote (extractUnquotes)
20import Idris.Elab.Utils
21import qualified Util.Pretty as U
23import Control.Applicative ((<$>))
25import Control.Monad.State.Strict
27import qualified Data.Map as M
28import Data.Maybe (mapMaybe, fromMaybe)
29import qualified Data.Set as S
30import qualified Data.Text as T
31import Data.Vector.Unboxed (Vector)
32import qualified Data.Vector.Unboxed as V
36data ElabMode = ETyDecl | ELHS | ERHS
39-- Using the elaborator, convert a term in raw syntax to a fully
40-- elaborated, typechecked term.
42-- If building a pattern match, we convert undeclared variables from
43-- holes to pattern bindings.
45-- Also find deferred names in the term and their types
47build :: IState -> ElabInfo -> ElabMode -> FnOpts -> Name -> PTerm ->
48 ElabD (Term, [(Name, (Int, Maybe Name, Type))], [PDecl])
49build ist info emode opts fn tm
50 = do elab ist info emode opts fn tm
52 let inf = case lookupCtxt fn (idris_tyinfodata ist) of
58 -- Resolve remaining type classes. Two passes - first to get the
59 -- default Num instances, second to clean up the rest
61 mapM_ (\n -> when (n `elem` hs) $
64 try (resolveTC True 7 g fn ist)
69 mapM_ (\n -> when (n `elem` hs) $
72 resolveTC True 7 g fn ist) ivs
80 traceWhen u ("Remaining holes:\n" ++ show hs ++ "\n" ++
81 "Remaining problems:\n" ++ qshow probs) $
82 do unify_all; matchProblems True; unifyProblems
87 ((_,_,_,e,_,_):es) -> traceWhen u ("Final problems:\n" ++ show probs) $
91 when tydecl (do update_term orderPats
93-- update_term liftPats)
96 let (tm, ds) = runState (collectDeferred (Just fn) tt) []
98 if (log /= "") then trace log $ return (tm, ds, is)
99 else return (tm, ds, is)
100 where pattern = emode == ELHS
101 tydecl = emode == ETyDecl
103 mkPat = do hs <- get_holes
106 (h: hs) -> do patvar h; mkPat
109-- Build a term autogenerated as a typeclass method definition
110-- (Separate, so we don't go overboard resolving things that we don't
111-- know about yet on the LHS of a pattern def)
113buildTC :: IState -> ElabInfo -> ElabMode -> FnOpts -> Name -> PTerm ->
114 ElabD (Term, [(Name, (Int, Maybe Name, Type))], [PDecl])
115buildTC ist info emode opts fn tm
116 = do -- set name supply to begin after highest index in tm
117 let ns = allNamesIn tm
119 let inf = case lookupCtxt fn (idris_tyinfodata ist) of
123 elab ist info emode opts fn tm
128 ((_,_,_,e,_,_):es) -> if inf then return ()
132 let (tm, ds) = runState (collectDeferred (Just fn) tt) []
134 if (log /= "") then trace log $ return (tm, ds, is)
135 else return (tm, ds, is)
136 where pattern = emode == ELHS
138-- Returns the set of declarations we need to add to complete the definition
139-- (most likely case blocks to elaborate)
141elab :: IState -> ElabInfo -> ElabMode -> FnOpts -> Name -> PTerm ->
143elab ist info emode opts fn tm
144 = do let loglvl = opt_logLevel (idris_options ist)
145 when (loglvl > 5) $ unifyLog True
146 compute -- expand type synonyms, etc
147 elabE (False, False, False, False) tm -- (in argument, guarded, in type, in qquote)
150 when pattern -- convert remaining holes to pattern vars
151 (do update_term orderPats
153 matchProblems False -- only the ones we matched earlier
157 pattern = emode == ELHS
158 bindfree = emode == ETyDecl || emode == ELHS
160 tcgen = Dictionary `elem` opts
161 reflection = Reflection `elem` opts
163 isph arg = case getTm arg of
164 Placeholder -> (True, priority arg)
165 tm -> (False, priority arg)
167 toElab ina arg = case getTm arg of
168 Placeholder -> Nothing
169 v -> Just (priority arg, elabE ina v)
171 toElab' ina arg = case getTm arg of
172 Placeholder -> Nothing
173 v -> Just (elabE ina v)
175 mkPat = do hs <- get_holes
178 (h: hs) -> do patvar h; mkPat
181 -- | elabE elaborates an expression, possibly wrapping implicit coercions
182 -- and forces/delays. If you make a recursive call in elab', it is
183 -- normally correct to call elabE - the ones that don't are desugarings
185 elabE :: (Bool, Bool, Bool, Bool) -> PTerm -> ElabD ()
188 --trace ("Elaborating " ++ show t ++ " : " ++ show g) $
189 do ct <- insertCoerce ina t
195 --trace ("Elaborating " ++ show t' ++ " in " ++ show g
196 -- ++ "\n" ++ show tm
197 -- ++ "\nholes " ++ show hs
198 -- ++ "\nproblems " ++ show ps
199 -- ++ "\n-----------\n") $
200 --trace ("ELAB " ++ show t') $
201 let fc = fileFC "Force"
203 handleError (forceErr env)
205 (elab' ina (PApp fc (PRef fc (sUN "Force"))
206 [pimp (sUN "t") Placeholder True,
207 pimp (sUN "a") Placeholder True,
210 forceErr env (CantUnify _ t t' _ _ _)
211 | (P _ (UN ht) _, _) <- unApply (normalise (tt_ctxt ist) env t),
212 ht == txt "Lazy'" = True
213 forceErr env (CantUnify _ t t' _ _ _)
214 | (P _ (UN ht) _, _) <- unApply (normalise (tt_ctxt ist) env t'),
215 ht == txt "Lazy'" = True
216 forceErr env (InfiniteUnify _ t _)
217 | (P _ (UN ht) _, _) <- unApply (normalise (tt_ctxt ist) env t),
218 ht == txt "Lazy'" = True
219 forceErr env (Elaborating _ _ t) = forceErr env t
220 forceErr env (ElaboratingArg _ _ _ t) = forceErr env t
221 forceErr env (At _ t) = forceErr env t
222 forceErr env t = False
224 local f = do e <- get_env
225 return (f `elem` map fst e)
227 -- | Is a constant a type?
228 constType :: Const -> Bool
229 constType (AType _) = True
230 constType StrType = True
231 constType PtrType = True
232 constType VoidType = True
235 -- "guarded" means immediately under a constructor, to help find patvars
237 elab' :: (Bool, Bool, Bool, Bool) -- ^ (in an argument, guarded, in a type, in a quasiquote)
238 -> PTerm -- ^ The term to elaborate
240 elab' ina (PNoImplicits t) = elab' ina t -- skip elabE step
241 elab' ina PType = do apply RType []; solve
242 elab' ina (PUniverse u) = do apply (RUType u) []; solve
243-- elab' (_,_,inty) (PConstant c)
244-- | constType c && pattern && not reflection && not inty
245-- = lift $ tfail (Msg "Typecase is not allowed")
246 elab' ina (PConstant c) = do apply (RConstant c) []; solve
247 elab' ina (PQuote r) = do fill r; solve
248 elab' ina (PTrue fc _) =
252 TType _ -> elab' ina (PRef fc unitTy)
253 _ -> elab' ina (PRef fc unitCon)
254 elab' ina (PResolveTC (FC "HACK" _ _)) -- for chasing parent classes
255 = do g <- goal; resolveTC False 5 g fn ist
256 elab' ina (PResolveTC fc)
257 = do c <- getNameFrom (sMN 0 "class")
259 elab' ina (PRefl fc t)
260 = elab' ina (PApp fc (PRef fc eqCon) [pimp (sMN 0 "A") Placeholder True,
261 pimp (sMN 0 "x") t False])
262 elab' ina (PEq fc Placeholder Placeholder l r)
263 = try (do tyn <- getNameFrom (sMN 0 "aqty")
266 elab' ina (PApp fc (PRef fc eqTy)
267 [pimp (sUN "A") (PRef fc tyn) True,
268 pimp (sUN "B") (PRef fc tyn) False,
270 (do atyn <- getNameFrom (sMN 0 "aqty")
271 btyn <- getNameFrom (sMN 0 "bqty")
276 elab' ina (PApp fc (PRef fc eqTy)
277 [pimp (sUN "A") (PRef fc atyn) True,
278 pimp (sUN "B") (PRef fc btyn) False,
281 elab' ina (PEq fc lt rt l r) = elab' ina (PApp fc (PRef fc eqTy)
282 [pimp (sUN "A") lt True,
283 pimp (sUN "B") rt False,
285 elab' ina@(_, a, inty, qq) (PPair fc _ l r)
289 TType _ -> elab' ina (PApp fc (PRef fc pairTy)
291 _ -> elab' ina (PApp fc (PRef fc pairCon)
292 [pimp (sUN "A") Placeholder False,
293 pimp (sUN "B") Placeholder False,
295 elab' ina (PDPair fc p l@(PRef _ n) t r)
304 where asType = elab' ina (PApp fc (PRef fc sigmaTy)
306 pexp (PLam n Placeholder r)])
307 asValue = elab' ina (PApp fc (PRef fc existsCon)
308 [pimp (sMN 0 "a") t False,
309 pimp (sMN 0 "P") Placeholder True,
311 elab' ina (PDPair fc p l t r) = elab' ina (PApp fc (PRef fc existsCon)
312 [pimp (sMN 0 "a") t False,
313 pimp (sMN 0 "P") Placeholder True,
315 elab' ina (PAlternative True as)
319 let (tc, _) = unApply ty
321 let as' = pruneByType (map fst env) tc ctxt as
322-- trace (show as ++ "\n ==> " ++ showSep ", " (map showTmImpls as')) $
323 tryAll (zip (map (elab' ina) as') (map showHd as'))
324 where showHd (PApp _ (PRef _ n) _) = n
325 showHd (PRef _ n) = n
326 showHd (PApp _ h _) = showHd h
327 showHd x = NErased -- We probably should do something better than this here
328 elab' ina (PAlternative False as)
330 where -- if none work, take the error from the first
331 trySeq (x : xs) = let e1 = elab' ina x in
332 try' e1 (trySeq' e1 xs) True
333 trySeq' deferr [] = proofFail deferr
334 trySeq' deferr (x : xs)
335 = try' (elab' ina x) (trySeq' deferr xs) True
336 elab' ina (PPatvar fc n) | bindfree = do patvar n; -- update_term liftPats
337-- elab' (_, _, inty) (PRef fc f)
338-- | isTConName f (tt_ctxt ist) && pattern && not reflection && not inty
339-- = lift $ tfail (Msg "Typecase is not allowed")
340 elab' (ina, guarded, inty, qq) (PRef fc n)
341 | (pattern || (bindfree && bindable n)) && not (inparamBlock n) && not qq
342 = do ctxt <- get_context
343 let defined = case lookupTy n ctxt of
346 -- this is to stop us resolve type classes recursively
347 -- trace (show (n, guarded)) $
348 if (tcname n && ina) then erun fc $ do patvar n; -- update_term liftPats
349 else if (defined && not guarded)
350 then do apply (Var n) []; solve
351 else try (do apply (Var n) []; solve)
352 (do patvar n; ) -- update_term liftPats)
353 where inparamBlock n = case lookupCtxtName n (inblock info) of
356 bindable (NS _ _) = False
357 bindable (UN xs) = True
358 bindable n = implicitable n
359 elab' ina f@(PInferRef fc n) = elab' ina (PApp fc f [])
360 elab' ina (PRef fc n) = erun fc $ do apply (Var n) []; solve
361 elab' ina@(_, a, inty, qq) (PLam n Placeholder sc)
362 = do -- if n is a type constructor name, this makes no sense...
364 when (isTConName n ctxt) $
365 lift $ tfail (Msg $ "Can't use type constructor " ++ show n ++ " here")
367 attack; intro (Just n);
368 -- trace ("------ intro " ++ show n ++ " ---- \n" ++ show ptm)
369 elabE (True, a, inty, qq) sc; solve
370 elab' ina@(_, a, inty, qq) (PLam n ty sc)
371 = do tyn <- getNameFrom (sMN 0 "lamty")
372 -- if n is a type constructor name, this makes no sense...
374 when (isTConName n ctxt) $
375 lift $ tfail (Msg $ "Can't use type constructor " ++ show n ++ " here")
382 introTy (Var tyn) (Just n)
384 elabE (True, a, True, qq) ty
385 elabE (True, a, inty, qq) sc
387 elab' ina@(_, a, _, qq) (PPi _ n Placeholder sc)
388 = do attack; arg n (sMN 0 "ty"); elabE (True, a, True, qq) sc; solve
389 elab' ina@(_, a, _, qq) (PPi _ n ty sc)
390 = do attack; tyn <- getNameFrom (sMN 0 "ty")
393 MN _ _ -> unique_hole n
397 elabE (True, a, True, qq) ty
398 elabE (True, a, True, qq) sc
400 elab' ina@(_, a, inty, qq) (PLet n ty val sc)
403 tyn <- getNameFrom (sMN 0 "letty")
405 valn <- getNameFrom (sMN 0 "letval")
408 letbind n (Var tyn) (Var valn)
410 Placeholder -> return ()
413 elabE (True, a, True, qq) ty
415 elabE (True, a, True, qq) val
416 ivs' <- get_instances
418 elabE (True, a, inty, qq) sc
420 mapM_ (\n -> do focus n
423 if all (\n -> n == tyn || not (n `elem` hs)) (freeNames g)
424 -- let insts = filter tcname $ map fst (ctxtAlist (tt_ctxt ist))
425 then try (resolveTC True 7 g fn ist)
429 -- HACK: If the name leaks into its type, it may leak out of
430 -- scope outside, so substitute in the outer scope.
431 expandLet n (case lookup n env of
434 elab' ina@(_, a, inty, qq) (PGoal fc r n sc) = do
437 tyn <- getNameFrom (sMN 0 "letty")
439 valn <- getNameFrom (sMN 0 "letval")
441 letbind n (Var tyn) (Var valn)
443 elabE (True, a, True, qq) (PApp fc r [pexp (delab ist rty)])
446 elabE (True, a, inty, qq) sc
448-- elab' ina (PLet n Placeholder
449-- (PApp fc r [pexp (delab ist rty)]) sc)
450 elab' ina tm@(PApp fc (PInferRef _ f) args) = do
454 -- make a function type a -> b -> c -> ... -> rty for the
457 argTys <- claimArgTys env args
458 fn <- getNameFrom (sMN 0 "inf_fn")
459 let fty = fnTy argTys rty
460-- trace (show (ptm, map fst argTys)) $ focus fn
461 -- build and defer the function application
462 attack; deferType (mkN f) fty (map fst argTys); solve
463 -- elaborate the arguments, to unify their types. They all have to
465 mapM_ elabIArg (zip argTys args)
466 where claimArgTys env [] = return []
467 claimArgTys env (arg : xs) | Just n <- localVar env (getTm arg)
468 = do nty <- get_type (Var n)
469 ans <- claimArgTys env xs
470 return ((n, (False, forget nty)) : ans)
471 claimArgTys env (_ : xs)
472 = do an <- getNameFrom (sMN 0 "inf_argTy")
473 aval <- getNameFrom (sMN 0 "inf_arg")
476 ans <- claimArgTys env xs
477 return ((aval, (True, (Var an))) : ans)
478 fnTy [] ret = forget ret
479 fnTy ((x, (_, xt)) : xs) ret = RBind x (Pi xt RType) (fnTy xs ret)
481 localVar env (PRef _ x)
482 = case lookup x env of
485 localVar env _ = Nothing
487 elabIArg ((n, (True, ty)), def) = do focus n; elabE ina (getTm def)
488 elabIArg _ = return () -- already done, just a name
492 mkN n = case namespace info of
493 Just xs@(_:_) -> sNS n xs
496 elab' ina (PMatchApp fc fn)
497 = do (fn', imps) <- case lookupCtxtName fn (idris_implicits ist) of
498 [(n, args)] -> return (n, map (const True) args)
499 _ -> lift $ tfail (NoSuchVariable fn)
500 ns <- match_apply (Var fn') (map (\x -> (x,0)) imps)
502 elab' (_, _, inty, qq) (PApp fc (PRef _ f) args')
503 | isTConName f (tt_ctxt ist) && pattern && not reflection && not inty && not qq
504 = lift $ tfail (Msg "Typecase is not allowed")
505 -- if f is local, just do a simple_app
506 elab' (ina, g, inty, qq) tm@(PApp fc (PRef _ f) args)
508 if (f `elem` map fst env && length args == 1)
509 then -- simple app, as below
510 do simple_app (elabE (ina, g, inty, qq) (PRef fc f))
511 (elabE (True, g, inty, qq) (getTm (head args)))
515 do ivs <- get_instances
517 -- HACK: we shouldn't resolve type classes if we're defining an instance
518 -- function or default definition.
519 let isinf = f == inferCon || tcname f
520 -- if f is a type class, we need to know its arguments so that
521 -- we can unify with them
522 case lookupCtxt f (idris_classes ist) of
524 _ -> do mapM_ setInjective (map getTm args)
525 -- maybe more things are solvable now
528 let guarded = isConName f ctxt
529-- trace ("args is " ++ show args) $ return ()
530 ns <- apply (Var f) (map isph args)
531-- trace ("ns is " ++ show ns) $ return ()
532 -- mark any type class arguments as injective
533 mapM_ checkIfInjective (map snd ns)
534 unifyProblems -- try again with the new information,
535 -- to help with disambiguation
536 -- Sort so that the implicit tactics and alternatives go last
537 let (ns', eargs) = unzip $
538 sortBy cmpArg (zip ns args)
540 elabArgs ist (ina || not isinf, guarded, inty, qq)
543 (map (\x -> getTm x) eargs) -- TODO: remove this False arg
545 ivs' <- get_instances
546 -- Attempt to resolve any type classes which have 'complete' types,
547 -- i.e. no holes in them
548 when (not pattern || (ina && not tcgen && not guarded)) $
549 mapM_ (\n -> do focus n
553 if all (\n -> not (n `elem` hs)) (freeNames g)
554 -- let insts = filter tcname $ map fst (ctxtAlist (tt_ctxt ist))
555 then try (resolveTC False 7 g fn ist)
559 where -- normal < alternatives < lambdas < rewrites < tactic < default tactic
560 -- reason for lambdas after alternatives is that having
561 -- the alternative resolved can help with typechecking the lambda
562 -- or the rewrite. Rewrites/tactics need as much information
563 -- as possible about the type.
564 -- FIXME: Better would be to allow alternative resolution to be
565 -- retried after more information is in.
567 | constraint x && not (constraint y) = LT
568 | constraint y && not (constraint x) = GT
570 = compare (conDepth 0 (getTm x) + priority x + alt x)
571 (conDepth 0 (getTm y) + priority y + alt y)
572 where alt t = case getTm t of
573 PAlternative False _ -> 5
574 PAlternative True _ -> 2
577 PRewrite _ _ _ _ -> 4
581 constraint (PConstraint _ _ _ _) = True
584 -- Score a point for every level where there is a non-constructor
585 -- function (so higher score --> done later)
586 -- Only relevant when on lhs
587 conDepth d t | not pattern = 0
588 conDepth d (PRef _ f) | isConName f (tt_ctxt ist) = 0
589 | otherwise = max (100 - d) 1
590 conDepth d (PApp _ f as)
591 = conDepth d f + sum (map (conDepth (d+1)) (map getTm as))
592 conDepth d (PPatvar _ _) = 0
593 conDepth d (PAlternative _ as) = maximum (map (conDepth d) as)
594 conDepth d Placeholder = 0
595 conDepth d (PResolveTC _) = 0
596 conDepth d t = max (100 - d) 1
598 checkIfInjective n = do
603 case unApply (binderTy b) of
605 case lookupCtxt c (idris_classes ist) of
607 _ -> -- type class, set as injective
608 do mapM_ setinjArg args
609 -- maybe we can solve more things now...
612 traceWhen ulog ("Injective now " ++ show args ++ "\n" ++ qshow probs) $
615 traceWhen ulog (qshow probs) $ return ()
618 setinjArg (P _ n _) = setinj n
619 setinjArg _ = return ()
621 tacTm (PTactics _) = True
622 tacTm (PProof _) = True
625 setInjective (PRef _ n) = setinj n
626 setInjective (PApp _ (PRef _ n) _) = setinj n
627 setInjective _ = return ()
629 elab' ina@(_, a, inty, qq) tm@(PApp fc f [arg])
631 do simple_app (elabE ina f) (elabE (True, a, inty, qq) (getTm arg))
634 elab' ina Placeholder = do (h : hs) <- get_holes
636 elab' ina (PMetavar n) =
638 -- When building the metavar application, leave out the unique
639 -- names which have been used elsewhere in the term, since we
640 -- won't be able to use them in the resulting application.
641 let unique_used = getUniqueUsed (tt_ctxt ist) ptm
646 where mkN n@(NS _ _) = n
647 mkN n = case namespace info of
648 Just xs@(_:_) -> sNS n xs
650 elab' ina (PProof ts) = do compute; mapM_ (runTac True ist fn) ts
651 elab' ina (PTactics ts)
652 | not pattern = do mapM_ (runTac False ist fn) ts
653 | otherwise = elab' ina Placeholder
654 elab' ina (PElabError e) = fail (pshow ist e)
655 elab' ina (PRewrite fc r sc newg)
657 tyn <- getNameFrom (sMN 0 "rty")
659 valn <- getNameFrom (sMN 0 "rval")
661 letn <- getNameFrom (sMN 0 "_rewrite_rule")
662 letbind letn (Var tyn) (Var valn)
669 when (g == g') $ lift $ tfail (NoRewriting g)
671 Nothing -> elab' ina sc
672 Just t -> doEquiv t sc
676 tyn <- getNameFrom (sMN 0 "ety")
678 valn <- getNameFrom (sMN 0 "eqval")
680 letn <- getNameFrom (sMN 0 "equiv_val")
681 letbind letn (Var tyn) (Var valn)
686 elab' ina (PRef fc letn)
688 elab' ina@(_, a, inty, qq) c@(PCase fc scr opts)
690 tyn <- getNameFrom (sMN 0 "scty")
692 valn <- getNameFrom (sMN 0 "scval")
693 scvn <- getNameFrom (sMN 0 "scvar")
695 letbind scvn (Var tyn) (Var valn)
697 elabE (True, a, inty, qq) scr
698 -- Solve any remaining implicits - we need to solve as many
699 -- as possible before making the 'case' type
703 envU <- mapM (getKind args) args
704 let namesUsedInRHS = nub $ scvn : concatMap (\(_,rhs) -> allNamesIn rhs) opts
706 -- Drop the unique arguments used in the scrutinee (since it's
707 -- not valid to use them again anyway)
708 let argsDropped = filter (isUnique envU) (nub $ allNamesIn scr)
709 let args' = filter (\(n, _) -> n `notElem` argsDropped) args
711 cname <- unique_hole' True (mkCaseName fn)
712 let cname' = mkN cname
713-- elab' ina (PMetavar cname')
714 attack; defer argsDropped cname'; solve
716 -- if the scrutinee is one of the 'args' in env, we should
717 -- inspect it directly, rather than adding it as a new argument
718 let newdef = PClauses fc [] cname'
720 (map (isScr scr) (reverse args')) opts)
722 updateAux (newdef : )
723 -- if we haven't got the type yet, hopefully we'll get it later!
726 where mkCaseName (NS n ns) = NS (mkCaseName n) ns
727 mkCaseName n = SN (CaseN n)
728-- mkCaseName (UN x) = UN (x ++ "_case")
729-- mkCaseName (MN i x) = MN i (x ++ "_case")
731 mkN n = case namespace info of
732 Just xs@(_:_) -> sNS n xs
735 isUnique envk n = case lookup n envk of
740 = case lookup n env of
741 Nothing -> return (n, False) -- can't happen, actually...
743 do ty <- get_type (forget (binderTy b))
745 UType UniqueType -> return (n, True)
746 UType AllTypes -> return (n, True)
747 _ -> return (n, False)
749 tcName tm | (P _ n _, _) <- unApply tm
750 = case lookupCtxt n (idris_classes ist) of
757 || any (\x -> x `elem` ns) (allTTNames (binderTy b))
759 -- FIXME: This probably doesn't help us here, but leaving
760 -- it in temporarily... if this comment is still here in master,
761 -- please delete the code!
762 chaseDeps env acc [] = filter (\(n, _) -> n `elem` acc) env
763 chaseDeps env acc ((n,b) : args)
764 = let ns = allTTNames (binderTy b) in
765 extendAcc ns acc args
767 extendAcc [] acc args = chaseDeps env acc args
768 extendAcc (n:ns) acc args
769 | elem n acc = extendAcc ns acc args
770 | otherwise = case lookup n env of
771 Just b -> extendAcc ns (n : acc)
773 Nothing -> extendAcc ns acc args
775 elab' ina (PUnifyLog t) = do unifyLog True
778 elab' (ina, g, inty, qq) (PQuasiquote t goal) -- TODO: goal type
779 = do -- First extract the unquoted subterms, replacing them with fresh
780 -- names in the quasiquoted term. Claim their reflections to be
782 (t, unq) <- extractUnquotes 0 t
783 let unquoteNames = map fst unq
784 mapM_ (flip claim (Var tt)) unquoteNames
787 -- Save the old state - we need a fresh proof state to avoid
788 -- capturing lexically available variables in the quoted term.
792 newProof (sMN 0 "q") ctxt $
795 -- Re-add the unquotes, letting Idris infer the (fictional)
796 -- types. Here, they represent the real type rather than the type
797 -- of their reflection.
798 mapM_ (\n -> do ty <- getNameFrom (sMN 0 "unqTy")
805 -- Determine whether there's an explicit goal type, and act accordingly
806 -- Establish holes for the type and value of the term to be
808 qTy <- getNameFrom (sMN 0 "qquoteTy")
811 qTm <- getNameFrom (sMN 0 "qquoteTm")
814 -- Let-bind the result of elaborating the contained term, so that
815 -- the hole doesn't disappear
816 nTm <- getNameFrom (sMN 0 "quotedTerm")
817 letbind nTm (Var qTy) (Var qTm)
819 -- Fill out the goal type, if relevant
822 Just gTy -> do focus qTy
823 elabE (ina, g, inty, True) gTy
825 -- Elaborate the quasiquoted term into the hole
827 elabE (ina, g, inty, True) t
830 -- We now have an elaborated term. Reflect it and solve the
831 -- original goal in the original proof state.
834 let quoted = fmap (explicitNames . binderVal) $ lookup nTm env
837 Just q -> do ctxt <- get_context
838 (q', _, _) <- lift $ recheck ctxt [(uq, Lam Erased) | uq <- unquoteNames] (forget q) q
840 then reflectQuotePattern unquoteNames q'
841 else do fill $ reflectQuote unquoteNames q'
843 Nothing -> lift . tfail . Msg $ "Broken elaboration of quasiquote"
845 -- Finally fill in the terms or patterns from the unquotes. This
846 -- happens last so that their holes still exist while elaborating
847 -- the main quotation.
848 mapM_ elabUnquote unq
849 where tt = sNS (sUN "TT") ["Reflection", "Language"]
853 elabE (ina, g, inty, False) tm
856 elab' ina (PUnquote t) = fail "Found unquote outside of quasiquote"
857 elab' ina x = fail $ "Unelaboratable syntactic form " ++ showTmImpls x
859 isScr :: PTerm -> (Name, Binder Term) -> (Name, (Bool, Binder Term))
860 isScr (PRef _ n) (n', b) = (n', (n == n', b))
861 isScr _ (n', b) = (n', (False, b))
863 caseBlock :: FC -> Name ->
864 [(Name, (Bool, Binder Term))] -> [(PTerm, PTerm)] -> [PClause]
865 caseBlock fc n env opts
866 = let args' = findScr env
867 args = map mkarg (map getNmScr args') in
868 map (mkClause args) opts
870 where -- Find the variable we want as the scrutinee and mark it as
871 -- 'True'. If the scrutinee is in the environment, match on that
872 -- otherwise match on the new argument we're adding.
873 findScr ((n, (True, t)) : xs)
874 = (n, (True, t)) : scrName n xs
875 findScr [(n, (_, t))] = [(n, (True, t))]
876 findScr (x : xs) = x : findScr xs
877 -- [] can't happen since scrutinee is in the environment!
879 -- To make sure top level pattern name remains in scope, put
880 -- it at the end of the environment
882 scrName n [(_, t)] = [(n, t)]
883 scrName n (x : xs) = x : scrName n xs
885 getNmScr (n, (s, _)) = (n, s)
887 mkarg (n, s) = (PRef fc n, s)
888 -- may be shadowed names in the new pattern - so replace the
889 -- old ones with an _
891 = let args' = map (shadowed (allNamesIn l)) args
892 lhs = PApp (getFC fc l) (PRef (getFC fc l) n)
893 (map (mkLHSarg l) args') in
894 PClause (getFC fc l) n lhs [] r []
896 mkLHSarg l (tm, True) = pexp l
897 mkLHSarg l (tm, False) = pexp tm
899 shadowed new (PRef _ n, s) | n `elem` new = (Placeholder, s)
902 getFC d (PApp fc _ _) = fc
903 getFC d (PRef fc _) = fc
904 getFC d (PAlternative _ (x:_)) = getFC d x
907 insertLazy :: PTerm -> ElabD PTerm
908 insertLazy t@(PApp _ (PRef _ (UN l)) _) | l == txt "Delay" = return t
909 insertLazy t@(PApp _ (PRef _ (UN l)) _) | l == txt "Force" = return t
910 insertLazy (PCoerced t) = return t
914 let (tyh, _) = unApply (normalise (tt_ctxt ist) env ty)
915 let tries = if pattern then [t, mkDelay env t] else [mkDelay env t, t]
917 P _ (UN l) _ | l == txt "Lazy'"
918 -> return (PAlternative False tries)
921 mkDelay env (PAlternative b xs) = PAlternative b (map (mkDelay env) xs)
923 = let fc = fileFC "Delay" in
924 addImplBound ist (map fst env) (PApp fc (PRef fc (sUN "Delay"))
928 -- Don't put implicit coercions around applications which are marked
929 -- as '%noImplicit', or around case blocks, otherwise we get exponential
930 -- blowup especially where there are errors deep in large expressions.
931 notImplicitable (PApp _ f _) = notImplicitable f
932 -- TMP HACK no coercing on bind (make this configurable)
933 notImplicitable (PRef _ n)
934 | [opts] <- lookupCtxt n (idris_flags ist)
935 = NoImplicit `elem` opts
936 notImplicitable (PAlternative True as) = any notImplicitable as
937 -- case is tricky enough without implicit coercions! If they are needed,
938 -- they can go in the branches separately.
939 notImplicitable (PCase _ _ _) = True
940 notImplicitable _ = False
942 insertCoerce ina t@(PCase _ _ _) = return t
943 insertCoerce ina t | notImplicitable t = return t
946 -- Check for possible coercions to get to the goal
947 -- and add them as 'alternatives'
949 let ty' = normalise (tt_ctxt ist) env ty
950 let cs = getCoercionsTo ist ty'
951 let t' = case (t, cs) of
952 (PCoerced tm, _) -> tm
954 (_, cs) -> PAlternative False [t ,
955 PAlternative True (map (mkCoerce env t) cs)]
958 mkCoerce env t n = let fc = fileFC "Coercion" in -- line never appears!
959 addImplBound ist (map fst env)
960 (PApp fc (PRef fc n) [pexp (PCoerced t)])
962 -- | Elaborate the arguments to a function
963 elabArgs :: IState -- ^ The current Idris state
964 -> (Bool, Bool, Bool, Bool) -- ^ (in an argument, guarded, in a type, in a qquote)
966 -> FC -- ^ Source location
968 -> Name -- ^ Name of the function being applied
969 -> [(Name, Name)] -- ^ (Argument Name, Hole Name)
970 -> Bool -- ^ under a 'force'
971 -> [PTerm] -- ^ (Laziness, argument)
973 elabArgs ist ina failed fc retry f [] force _ = return ()
974 elabArgs ist ina failed fc r f (n:ns) force (Placeholder : args)
975 = elabArgs ist ina failed fc r f ns force args
976 elabArgs ist ina failed fc r f ((argName, holeName):ns) force (t : args)
977 = elabArg argName holeName t
978 where elabArg argName holeName t =
979 do now_elaborating fc f argName
980 wrapErr f argName $ do
983 -- No coercing under an explicit Force (or it can Force/Delay
985 let elab = if force then elab' else elabE
986 failed' <- -- trace (show (n, t, hs, tm)) $
987 -- traceWhen (not (null cs)) (show ty ++ "\n" ++ showImp True t) $
988 case holeName `elem` hs of
989 True -> do focus holeName;
992 traceWhen ulog ("Elaborating argument " ++ show (argName, holeName, g)) $
993 elab ina t; return failed
994 False -> return failed
995 done_elaborating_arg f argName
996 elabArgs ist ina failed fc r f ns force args
997 wrapErr f argName action =
999 while <- elaborating_app
1000 let while' = map (\(x, y, z)-> (y, z)) while
1001 (result, newState) <- case runStateT action elabState of
1002 OK (res, newState) -> return (res, newState)
1003 Error e -> do done_elaborating_arg f argName
1004 lift (tfail (elaboratingArgErr while' e))
1009-- For every alternative, look at the function at the head. Automatically resolve
1010-- any nested alternatives where that function is also at the head
1012pruneAlt :: [PTerm] -> [PTerm]
1013pruneAlt xs = map prune xs
1015 prune (PApp fc1 (PRef fc2 f) as)
1016 = PApp fc1 (PRef fc2 f) (fmap (fmap (choose f)) as)
1019 choose f (PAlternative a as)
1020 = let as' = fmap (choose f) as
1021 fs = filter (headIs f) as' in
1024 _ -> PAlternative a as'
1026 choose f (PApp fc f' as) = PApp fc (choose f f') (fmap (fmap (choose f)) as)
1029 headIs f (PApp _ (PRef _ f') _) = f == f'
1030 headIs f (PApp _ f' _) = headIs f f'
1031 headIs f _ = True -- keep if it's not an application
1033-- Rule out alternatives that don't return the same type as the head of the goal
1034-- (If there are none left as a result, do nothing)
1035pruneByType :: [Name] -> Term -> Context -> [PTerm] -> [PTerm]
1036-- if an alternative has a locally bound name at the head, take it
1037pruneByType env t c as
1038 | Just a <- locallyBound as = [a]
1040 locallyBound [] = Nothing
1042 | Just n <- getName t,
1043 n `elem` env = Just t
1044 | otherwise = locallyBound ts
1045 getName (PRef _ n) = Just n
1046 getName (PApp _ f _) = getName f
1049pruneByType env (P _ n _) c as
1050-- if the goal type is polymorphic, keep e
1051 | [] <- lookupTy n c = as
1053 = let asV = filter (headIs True n) as
1054 as' = filter (headIs False n) as in
1061 headIs var f (PApp _ (PRef _ f') _) = typeHead var f f'
1062 headIs var f (PApp _ f' _) = headIs var f f'
1063 headIs var f (PPi _ _ _ sc) = headIs var f sc
1064 headIs _ _ _ = True -- keep if it's not an application
1067 = case lookupTy f' c of
1068 [ty] -> let ty' = normalise c [] ty in
1069 case unApply (getRetTy ty') of
1070 (P _ ftyn _, _) -> ftyn == f
1071 (V _, _) -> var -- keep, variable
1075pruneByType _ t _ as = as
1077findInstances :: IState -> Term -> [Name]
1079 | (P _ n _, _) <- unApply t
1080 = case lookupCtxt n (idris_classes ist) of
1081 [CI _ _ _ _ _ ins] -> ins
1086 = trivial (elab ist toplevel ERHS [] (sMN 0 "tac")) ist
1087proofSearch' ist rec depth prv top n hints
1089 proofSearch rec prv depth
1090 (elab ist toplevel ERHS [] (sMN 0 "tac")) top n hints ist
1092resolveTC :: Bool -> Int -> Term -> Name -> IState -> ElabD ()
1093resolveTC = resTC' []
1095resTC' tcs def 0 topg fn ist = fail $ "Can't resolve type class"
1096resTC' tcs def 1 topg fn ist = try' (trivial' ist) (resolveTC def 0 topg fn ist) True
1097resTC' tcs defaultOn depth topg fn ist
1103 traceWhen ulog ("Resolving class " ++ show g) $
1106 let (tc, ttypes) = unApply t
1107 scopeOnly <- needsDefault t tc ttypes
1108 let insts_in = findInstances ist t
1109 let insts = if scopeOnly then filter chaser insts_in
1112 let depth' = if scopeOnly then 2 else depth
1113 blunderbuss t depth' insts) True
1115 elabTC n | n /= fn && tcname n = (resolve n depth, show n)
1116 | otherwise = (fail "Can't resolve", show n)
1118 -- HACK! Rather than giving a special name, better to have some kind
1119 -- of flag in ClassInfo structure
1121 | ('@':'@':_) <- str nm = True -- old way
1122 chaser (SN (ParentN _ _)) = True
1123 chaser (NS n _) = chaser n
1126 numclass = sNS (sUN "Num") ["Classes","Prelude"]
1128 needsDefault t num@(P _ nc _) [P Bound a _] | nc == numclass && defaultOn
1130 fill (RConstant (AType (ATInt ITBig))) -- default Integer
1134 | all boundVar as = return True -- fail $ "Can't resolve " ++ show t
1135 needsDefault t f a = return False -- trace (show t) $ return ()
1137 boundVar (P Bound _ _) = True
1140 blunderbuss t d [] = do -- c <- get_env
1142 lift $ tfail $ CantResolve topg
1143 blunderbuss t d (n:ns)
1144 | n /= fn && tcname n = try' (resolve n d)
1145 (blunderbuss t d ns) True
1146 | otherwise = blunderbuss t d ns
1149 | depth == 0 = fail $ "Can't resolve type class"
1152 let (tc, ttypes) = unApply t
1153-- if (all boundVar ttypes) then resolveTC (depth - 1) fn insts ist
1155 -- if there's a hole in the goal, don't even try
1156 let imps = case lookupCtxtName n (idris_implicits ist) of
1158 [args] -> map isImp (snd args) -- won't be overloaded!
1161 args <- map snd <$> try' (apply (Var n) imps)
1162 (match_apply (Var n) imps) True
1164 when (length ps < length ps' || unrecoverable ps') $
1165 fail "Can't apply type class"
1166-- traceWhen (all boundVar ttypes) ("Progress: " ++ show t ++ " with " ++ show n) $
1167 mapM_ (\ (_,n) -> do focus n
1169 let (tc', ttype) = unApply t'
1170 let got = fst (unApply t)
1171 let depth' = if tc' `elem` tcs
1172 then depth - 1 else depth
1173 resTC' (got : tcs) defaultOn depth' topg fn ist)
1174 (filter (\ (x, y) -> not x) (zip (map fst imps) args))
1175 -- if there's any arguments left, we've failed to resolve
1179 traceWhen ulog ("Got " ++ show n) $ return ()
1180 where isImp (PImp p _ _ _ _) = (True, p)
1181 isImp arg = (False, priority arg)
1183collectDeferred :: Maybe Name ->
1184 Term -> State [(Name, (Int, Maybe Name, Type))] Term
1185collectDeferred top (Bind n (GHole i t) app) =
1187 t' <- collectDeferred top t
1188 when (not (n `elem` map fst ds)) $ put (ds ++ [(n, (i, top, t'))])
1189 collectDeferred top app
1190collectDeferred top (Bind n b t) = do b' <- cdb b
1191 t' <- collectDeferred top t
1192 return (Bind n b' t')
1194 cdb (Let t v) = liftM2 Let (collectDeferred top t) (collectDeferred top v)
1195 cdb (Guess t v) = liftM2 Guess (collectDeferred top t) (collectDeferred top v)
1196 cdb b = do ty' <- collectDeferred top (binderTy b)
1197 return (b { binderTy = ty' })
1198collectDeferred top (App f a) = liftM2 App (collectDeferred top f) (collectDeferred top a)
1199collectDeferred top t = return t
1201case_ :: Bool -> Bool -> IState -> Name -> PTerm -> ElabD ()
1202case_ ind autoSolve ist fn tm = do
1204 tyn <- getNameFrom (sMN 0 "ity")
1206 valn <- getNameFrom (sMN 0 "ival")
1207 claim valn (Var tyn)
1208 letn <- getNameFrom (sMN 0 "irule")
1209 letbind letn (Var tyn) (Var valn)
1211 elab ist toplevel ERHS [] (sMN 0 "tac") tm
1213 let (Just binding) = lookup letn env
1214 let val = binderVal binding
1215 if ind then induction (forget val)
1216 else casetac (forget val)
1217 when autoSolve solveAll
1219-- Running tactics directly
1220-- if a tactic adds unification problems, return an error
1222runTac :: Bool -> IState -> Name -> PTactic -> ElabD ()
1223runTac autoSolve ist fn tac
1226 let tac' = fmap (addImplBound ist (map fst env)) tac
1229 else no_errors (runT tac')
1230 (Just (CantSolveGoal g (map (\(n, b) -> (n, binderTy b)) env)))
1232 runT (Intro []) = do g <- goal
1233 attack; intro (bname g)
1235 bname (Bind n _ _) = Just n
1237 runT (Intro xs) = mapM_ (\x -> do attack; intro (Just x)) xs
1238 runT Intros = do g <- goal
1239 attack; intro (bname g)
1243 bname (Bind n _ _) = Just n
1245 runT (Exact tm) = do elab ist toplevel ERHS [] (sMN 0 "tac") tm
1246 when autoSolve solveAll
1247 runT (MatchRefine fn)
1249 case lookupCtxtName fn (idris_implicits ist) of
1250 [] -> do a <- envArgs fn
1252 ns -> return (map (\ (n, a) -> (n, map (const True) a)) ns)
1253 let tacs = map (\ (fn', imps) ->
1254 (match_apply (Var fn') (map (\x -> (x, 0)) imps),
1257 when autoSolve solveAll
1258 where envArgs n = do e <- get_env
1260 Just t -> return $ map (const False)
1261 (getArgTys (binderTy t))
1265 case lookupCtxtName fn (idris_implicits ist) of
1266 [] -> do a <- envArgs fn
1268 ns -> return (map (\ (n, a) -> (n, map isImp a)) ns)
1269 let tacs = map (\ (fn', imps) ->
1270 (apply (Var fn') (map (\x -> (x, 0)) imps),
1273 when autoSolve solveAll
1274 where isImp (PImp _ _ _ _ _) = True
1276 envArgs n = do e <- get_env
1278 Just t -> return $ map (const False)
1279 (getArgTys (binderTy t))
1281 runT (Refine fn imps) = do ns <- apply (Var fn) (map (\x -> (x,0)) imps)
1282 when autoSolve solveAll
1283 runT DoUnify = do unify_all
1284 when autoSolve solveAll
1285 runT (Equiv tm) -- let bind tm, then
1287 tyn <- getNameFrom (sMN 0 "ety")
1289 valn <- getNameFrom (sMN 0 "eqval")
1290 claim valn (Var tyn)
1291 letn <- getNameFrom (sMN 0 "equiv_val")
1292 letbind letn (Var tyn) (Var valn)
1294 elab ist toplevel ERHS [] (sMN 0 "tac") tm
1296 when autoSolve solveAll
1297 runT (Rewrite tm) -- to elaborate tm, let bind it, then rewrite by that
1298 = do attack; -- (h:_) <- get_holes
1299 tyn <- getNameFrom (sMN 0 "rty")
1302 valn <- getNameFrom (sMN 0 "rval")
1303 claim valn (Var tyn)
1304 letn <- getNameFrom (sMN 0 "rewrite_rule")
1305 letbind letn (Var tyn) (Var valn)
1307 elab ist toplevel ERHS [] (sMN 0 "tac") tm
1309 when autoSolve solveAll
1310 runT (Induction tm) -- let bind tm, similar to the others
1311 = case_ True autoSolve ist fn tm
1313 = case_ False autoSolve ist fn tm
1316 tyn <- getNameFrom (sMN 0 "letty")
1318 valn <- getNameFrom (sMN 0 "letval")
1319 claim valn (Var tyn)
1320 letn <- unique_hole n
1321 letbind letn (Var tyn) (Var valn)
1323 elab ist toplevel ERHS [] (sMN 0 "tac") tm
1324 when autoSolve solveAll
1325 runT (LetTacTy n ty tm)
1327 tyn <- getNameFrom (sMN 0 "letty")
1329 valn <- getNameFrom (sMN 0 "letval")
1330 claim valn (Var tyn)
1331 letn <- unique_hole n
1332 letbind letn (Var tyn) (Var valn)
1334 elab ist toplevel ERHS [] (sMN 0 "tac") ty
1336 elab ist toplevel ERHS [] (sMN 0 "tac") tm
1337 when autoSolve solveAll
1338 runT Compute = compute
1339 runT Trivial = do trivial' ist; when autoSolve solveAll
1340 runT TCInstance = runT (Exact (PResolveTC emptyFC))
1341 runT (ProofSearch rec prover depth top hints)
1342 = do proofSearch' ist rec depth prover top fn hints
1343 when autoSolve solveAll
1344 runT (Focus n) = focus n
1346 runT (Try l r) = do try' (runT l) (runT r) True
1347 runT (TSeq l r) = do runT l; runT r
1348 runT (ApplyTactic tm) = do tenv <- get_env -- store the environment
1349 tgoal <- goal -- store the goal
1350 attack -- let f : List (TTName, Binder TT) -> TT -> Tactic = tm in ...
1351 script <- getNameFrom (sMN 0 "script")
1352 claim script scriptTy
1353 scriptvar <- getNameFrom (sMN 0 "scriptvar" )
1354 letbind scriptvar scriptTy (Var script)
1356 elab ist toplevel ERHS [] (sMN 0 "tac") tm
1357 (script', _) <- get_type_val (Var scriptvar)
1358 -- now that we have the script apply
1359 -- it to the reflected goal and context
1360 restac <- getNameFrom (sMN 0 "restac")
1361 claim restac tacticTy
1363 fill (raw_apply (forget script')
1364 [reflectEnv tenv, reflect tgoal])
1365 restac' <- get_guess
1367 -- normalise the result in order to
1371 let tactic = normalise ctxt env restac'
1373 where tacticTy = Var (reflm "Tactic")
1374 listTy = Var (sNS (sUN "List") ["List", "Prelude"])
1375 scriptTy = (RBind (sMN 0 "__pi_arg")
1376 (Pi (RApp listTy envTupleType) RType)
1377 (RBind (sMN 1 "__pi_arg")
1378 (Pi (Var $ reflm "TT") RType) tacticTy))
1379 runT (ByReflection tm) -- run the reflection function 'tm' on the
1380 -- goal, then apply the resulting reflected Tactic
1383 script <- getNameFrom (sMN 0 "script")
1384 claim script scriptTy
1385 scriptvar <- getNameFrom (sMN 0 "scriptvar" )
1386 letbind scriptvar scriptTy (Var script)
1389 elab ist toplevel ERHS [] (sMN 0 "tac")
1390 (PApp emptyFC tm [pexp (delabTy' ist [] tgoal True True)])
1391 (script', _) <- get_type_val (Var scriptvar)
1392 -- now that we have the script apply
1393 -- it to the reflected goal
1394 restac <- getNameFrom (sMN 0 "restac")
1395 claim restac tacticTy
1397 fill (forget script')
1398 restac' <- get_guess
1400 -- normalise the result in order to
1404 let tactic = normalise ctxt env restac'
1406 where tacticTy = Var (reflm "Tactic")
1409 runT (Reflect v) = do attack -- let x = reflect v in ...
1410 tyn <- getNameFrom (sMN 0 "letty")
1412 valn <- getNameFrom (sMN 0 "letval")
1413 claim valn (Var tyn)
1414 letn <- getNameFrom (sMN 0 "letvar")
1415 letbind letn (Var tyn) (Var valn)
1417 elab ist toplevel ERHS [] (sMN 0 "tac") v
1418 (value, _) <- get_type_val (Var letn)
1421 let value' = hnf ctxt env value
1422 runTac autoSolve ist fn (Exact $ PQuote (reflect value'))
1423 runT (Fill v) = do attack -- let x = fill x in ...
1424 tyn <- getNameFrom (sMN 0 "letty")
1426 valn <- getNameFrom (sMN 0 "letval")
1427 claim valn (Var tyn)
1428 letn <- getNameFrom (sMN 0 "letvar")
1429 letbind letn (Var tyn) (Var valn)
1431 elab ist toplevel ERHS [] (sMN 0 "tac") v
1432 (value, _) <- get_type_val (Var letn)
1435 let value' = normalise ctxt env value
1436 rawValue <- reifyRaw value'
1437 runTac autoSolve ist fn (Exact $ PQuote rawValue)
1438 runT (GoalType n tac) = do g <- goal
1441 if nsroot n' == sUN n
1443 else fail "Wrong goal type"
1444 _ -> fail "Wrong goal type"
1445 runT ProofState = do g <- goal
1447 runT Skip = return ()
1448 runT (TFail err) = lift . tfail $ ReflectionError [err] (Msg "")
1449 runT x = fail $ "Not implemented " ++ show x
1451 runReflected t = do t' <- reify ist t
1452 runTac autoSolve ist fn t'
1454-- | Prefix a name with the "Language.Reflection" namespace
1455reflm :: String -> Name
1456reflm n = sNS (sUN n) ["Reflection", "Language"]
1459-- | Reify tactics from their reflected representation
1460reify :: IState -> Term -> ElabD PTactic
1461reify _ (P _ n _) | n == reflm "Intros" = return Intros
1462reify _ (P _ n _) | n == reflm "Trivial" = return Trivial
1463reify _ (P _ n _) | n == reflm "Instance" = return TCInstance
1464reify _ (P _ n _) | n == reflm "Solve" = return Solve
1465reify _ (P _ n _) | n == reflm "Compute" = return Compute
1466reify _ (P _ n _) | n == reflm "Skip" = return Skip
1467reify ist t@(App _ _)
1468 | (P _ f _, args) <- unApply t = reifyApp ist f args
1469reify _ t = fail ("Unknown tactic " ++ show t)
1471reifyApp :: IState -> Name -> [Term] -> ElabD PTactic
1472reifyApp ist t [l, r] | t == reflm "Try" = liftM2 Try (reify ist l) (reify ist r)
1473reifyApp _ t [Constant (I i)]
1474 | t == reflm "Search" = return (ProofSearch True True i Nothing [])
1476 | t == reflm "Refine" = do n <- reifyTTName x
1477 return $ Refine n []
1478reifyApp ist t [l, r] | t == reflm "Seq" = liftM2 TSeq (reify ist l) (reify ist r)
1479reifyApp ist t [Constant (Str n), x]
1480 | t == reflm "GoalType" = liftM (GoalType n) (reify ist x)
1481reifyApp _ t [n] | t == reflm "Intro" = liftM (Intro . (:[])) (reifyTTName n)
1482reifyApp ist t [t'] | t == reflm "Induction" = liftM (Induction . delab ist) (reifyTT t')
1483reifyApp ist t [t'] | t == reflm "Case" = liftM (Induction . delab ist) (reifyTT t')
1485 | t == reflm "ApplyTactic" = liftM (ApplyTactic . delab ist) (reifyTT t')
1487 | t == reflm "Reflect" = liftM (Reflect . delab ist) (reifyTT t')
1489 | t == reflm "ByReflection" = liftM (ByReflection . delab ist) (reifyTT t')
1491 | t == reflm "Fill" = liftM (Fill . PQuote) (reifyRaw t')
1493 | t == reflm "Exact" = liftM (Exact . delab ist) (reifyTT t')
1495 | t == reflm "Focus" = liftM Focus (reifyTTName x)
1497 | t == reflm "Rewrite" = liftM (Rewrite . delab ist) (reifyTT t')
1498reifyApp ist t [n, t']
1499 | t == reflm "LetTac" = do n' <- reifyTTName n
1501 return $ LetTac n' (delab ist t')
1502reifyApp ist t [n, tt', t']
1503 | t == reflm "LetTacTy" = do n' <- reifyTTName n
1506 return $ LetTacTy n' (delab ist tt'') (delab ist t'')
1507reifyApp ist t [errs]
1508 | t == reflm "Fail" = case unList errs of
1509 Nothing -> fail "Failed to reify errors"
1511 let parts = mapM reifyReportPart errs' in
1513 Left err -> fail $ "Couldn't reify \"Fail\" tactic - " ++ show err
1515 return $ TFail errs''
1516reifyApp _ f args = fail ("Unknown tactic " ++ show (f, args)) -- shouldn't happen
1518-- | Reify terms from their reflected representation
1519reifyTT :: Term -> ElabD Term
1521 | (P _ f _, args) <- unApply t = reifyTTApp f args
1523 | n == reflm "Erased" = return $ Erased
1525 | n == reflm "Impossible" = return $ Impossible
1526reifyTT t = fail ("Unknown reflection term: " ++ show t)
1528reifyTTApp :: Name -> [Term] -> ElabD Term
1529reifyTTApp t [nt, n, x]
1530 | t == reflm "P" = do nt' <- reifyTTNameType nt
1533 return $ P nt' n' x'
1534reifyTTApp t [Constant (I i)]
1535 | t == reflm "V" = return $ V i
1536reifyTTApp t [n, b, x]
1537 | t == reflm "Bind" = do n' <- reifyTTName n
1538 b' <- reifyTTBinder reifyTT (reflm "TT") b
1540 return $ Bind n' b' x'
1542 | t == reflm "App" = do f' <- reifyTT f
1546 | t == reflm "TConst" = liftM Constant (reifyTTConst c)
1547reifyTTApp t [t', Constant (I i)]
1548 | t == reflm "Proj" = do t'' <- reifyTT t'
1551 | t == reflm "TType" = liftM TType (reifyTTUExp tt)
1552reifyTTApp t args = fail ("Unknown reflection term: " ++ show (t, args))
1554-- | Reify raw terms from their reflected representation
1555reifyRaw :: Term -> ElabD Raw
1557 | (P _ f _, args) <- unApply t = reifyRawApp f args
1559 | n == reflm "RType" = return $ RType
1560reifyRaw t = fail ("Unknown reflection raw term: " ++ show t)
1562reifyRawApp :: Name -> [Term] -> ElabD Raw
1564 | t == reflm "Var" = liftM Var (reifyTTName n)
1565reifyRawApp t [n, b, x]
1566 | t == reflm "RBind" = do n' <- reifyTTName n
1567 b' <- reifyTTBinder reifyRaw (reflm "Raw") b
1569 return $ RBind n' b' x'
1571 | t == reflm "RApp" = liftM2 RApp (reifyRaw f) (reifyRaw x)
1573 | t == reflm "RForce" = liftM RForce (reifyRaw t')
1575 | t == reflm "RConstant" = liftM RConstant (reifyTTConst c)
1576reifyRawApp t args = fail ("Unknown reflection raw term: " ++ show (t, args))
1578reifyTTName :: Term -> ElabD Name
1580 | (P _ f _, args) <- unApply t = reifyTTNameApp f args
1581reifyTTName t = fail ("Unknown reflection term name: " ++ show t)
1583reifyTTNameApp :: Name -> [Term] -> ElabD Name
1584reifyTTNameApp t [Constant (Str n)]
1585 | t == reflm "UN" = return $ sUN n
1586reifyTTNameApp t [n, ns]
1587 | t == reflm "NS" = do n' <- reifyTTName n
1588 ns' <- reifyTTNamespace ns
1590reifyTTNameApp t [Constant (I i), Constant (Str n)]
1591 | t == reflm "MN" = return $ sMN i n
1593 | t == reflm "NErased" = return NErased
1594reifyTTNameApp t args = fail ("Unknown reflection term name: " ++ show (t, args))
1596reifyTTNamespace :: Term -> ElabD [String]
1597reifyTTNamespace t@(App _ _)
1599 (P _ f _, [Constant StrType])
1600 | f == sNS (sUN "Nil") ["List", "Prelude"] -> return []
1601 (P _ f _, [Constant StrType, Constant (Str n), ns])
1602 | f == sNS (sUN "::") ["List", "Prelude"] -> liftM (n:) (reifyTTNamespace ns)
1603 _ -> fail ("Unknown reflection namespace arg: " ++ show t)
1604reifyTTNamespace t = fail ("Unknown reflection namespace arg: " ++ show t)
1606reifyTTNameType :: Term -> ElabD NameType
1607reifyTTNameType t@(P _ n _) | n == reflm "Bound" = return $ Bound
1608reifyTTNameType t@(P _ n _) | n == reflm "Ref" = return $ Ref
1609reifyTTNameType t@(App _ _)
1611 (P _ f _, [Constant (I tag), Constant (I num)])
1612 | f == reflm "DCon" -> return $ DCon tag num False -- FIXME: Uniqueness!
1613 | f == reflm "TCon" -> return $ TCon tag num
1614 _ -> fail ("Unknown reflection name type: " ++ show t)
1615reifyTTNameType t = fail ("Unknown reflection name type: " ++ show t)
1617reifyTTBinder :: (Term -> ElabD a) -> Name -> Term -> ElabD (Binder a)
1618reifyTTBinder reificator binderType t@(App _ _)
1620 (P _ f _, bt:args) | forget bt == Var binderType
1621 -> reifyTTBinderApp reificator f args
1622 _ -> fail ("Mismatching binder reflection: " ++ show t)
1623reifyTTBinder _ _ t = fail ("Unknown reflection binder: " ++ show t)
1625reifyTTBinderApp :: (Term -> ElabD a) -> Name -> [Term] -> ElabD (Binder a)
1626reifyTTBinderApp reif f [t]
1627 | f == reflm "Lam" = liftM Lam (reif t)
1628reifyTTBinderApp reif f [t, k]
1629 | f == reflm "Pi" = liftM2 Pi (reif t) (reif k)
1630reifyTTBinderApp reif f [x, y]
1631 | f == reflm "Let" = liftM2 Let (reif x) (reif y)
1632reifyTTBinderApp reif f [x, y]
1633 | f == reflm "NLet" = liftM2 NLet (reif x) (reif y)
1634reifyTTBinderApp reif f [t]
1635 | f == reflm "Hole" = liftM Hole (reif t)
1636reifyTTBinderApp reif f [t]
1637 | f == reflm "GHole" = liftM (GHole 0) (reif t)
1638reifyTTBinderApp reif f [x, y]
1639 | f == reflm "Guess" = liftM2 Guess (reif x) (reif y)
1640reifyTTBinderApp reif f [t]
1641 | f == reflm "PVar" = liftM PVar (reif t)
1642reifyTTBinderApp reif f [t]
1643 | f == reflm "PVTy" = liftM PVTy (reif t)
1644reifyTTBinderApp _ f args = fail ("Unknown reflection binder: " ++ show (f, args))
1646reifyTTConst :: Term -> ElabD Const
1647reifyTTConst (P _ n _) | n == reflm "StrType" = return $ StrType
1648reifyTTConst (P _ n _) | n == reflm "PtrType" = return $ PtrType
1649reifyTTConst (P _ n _) | n == reflm "VoidType" = return $ VoidType
1650reifyTTConst (P _ n _) | n == reflm "Forgot" = return $ Forgot
1651reifyTTConst t@(App _ _)
1652 | (P _ f _, [arg]) <- unApply t = reifyTTConstApp f arg
1653reifyTTConst t = fail ("Unknown reflection constant: " ++ show t)
1655reifyTTConstApp :: Name -> Term -> ElabD Const
1656reifyTTConstApp f aty
1657 | f == reflm "AType" = fmap AType (reifyArithTy aty)
1658reifyTTConstApp f (Constant c@(I _))
1659 | f == reflm "I" = return $ c
1660reifyTTConstApp f (Constant c@(BI _))
1661 | f == reflm "BI" = return $ c
1662reifyTTConstApp f (Constant c@(Fl _))
1663 | f == reflm "Fl" = return $ c
1664reifyTTConstApp f (Constant c@(I _))
1665 | f == reflm "Ch" = return $ c
1666reifyTTConstApp f (Constant c@(Str _))
1667 | f == reflm "Str" = return $ c
1668reifyTTConstApp f (Constant c@(B8 _))
1669 | f == reflm "B8" = return $ c
1670reifyTTConstApp f (Constant c@(B16 _))
1671 | f == reflm "B16" = return $ c
1672reifyTTConstApp f (Constant c@(B32 _))
1673 | f == reflm "B32" = return $ c
1674reifyTTConstApp f (Constant c@(B64 _))
1675 | f == reflm "B64" = return $ c
1676reifyTTConstApp f arg = fail ("Unknown reflection constant: " ++ show (f, arg))
1678reifyArithTy :: Term -> ElabD ArithTy
1679reifyArithTy (App (P _ n _) intTy) | n == reflm "ATInt" = fmap ATInt (reifyIntTy intTy)
1680reifyArithTy (P _ n _) | n == reflm "ATFloat" = return ATFloat
1681reifyArithTy x = fail ("Couldn't reify reflected ArithTy: " ++ show x)
1683reifyNativeTy :: Term -> ElabD NativeTy
1684reifyNativeTy (P _ n _) | n == reflm "IT8" = return IT8
1685reifyNativeTy (P _ n _) | n == reflm "IT8" = return IT8
1686reifyNativeTy (P _ n _) | n == reflm "IT8" = return IT8
1687reifyNativeTy (P _ n _) | n == reflm "IT8" = return IT8
1688reifyNativeTy x = fail $ "Couldn't reify reflected NativeTy " ++ show x
1690reifyIntTy :: Term -> ElabD IntTy
1691reifyIntTy (App (P _ n _) nt) | n == reflm "ITFixed" = fmap ITFixed (reifyNativeTy nt)
1692reifyIntTy (P _ n _) | n == reflm "ITNative" = return ITNative
1693reifyIntTy (P _ n _) | n == reflm "ITBig" = return ITBig
1694reifyIntTy (P _ n _) | n == reflm "ITChar" = return ITChar
1695reifyIntTy (App (App (P _ n _) nt) (Constant (I i))) | n == reflm "ITVec" = fmap (flip ITVec i)
1698reifyTTUExp :: Term -> ElabD UExp
1699reifyTTUExp t@(App _ _)
1701 (P _ f _, [Constant (I i)]) | f == reflm "UVar" -> return $ UVar i
1702 (P _ f _, [Constant (I i)]) | f == reflm "UVal" -> return $ UVal i
1703 _ -> fail ("Unknown reflection type universe expression: " ++ show t)
1704reifyTTUExp t = fail ("Unknown reflection type universe expression: " ++ show t)
1706-- | Create a reflected call to a named function/constructor
1707reflCall :: String -> [Raw] -> Raw
1708reflCall funName args
1709 = raw_apply (Var (reflm funName)) args
1711-- | Lift a term into its Language.Reflection.TT representation
1712reflect :: Term -> Raw
1713reflect = reflectQuote []
1715claimTT :: Name -> ElabD Name
1716claimTT n = do n' <- getNameFrom n
1717 claim n' (Var (sNS (sUN "TT") ["Reflection", "Language"]))
1720-- | Convert a reflected term to a more suitable form for pattern-matching.
1721-- In particular, the less-interesting bits are elaborated to _ patterns. This
1722-- happens to NameTypes, universe levels, names that are bound but not used,
1723-- and the type annotation field of the P constructor.
1724reflectQuotePattern :: [Name] -> Term -> ElabD ()
1725reflectQuotePattern unq (P _ n _)
1726 | n `elem` unq = -- the unquoted names have been claimed as TT already - just use them
1727 do fill (Var n) ; solve
1729 do tyannot <- claimTT (sMN 0 "pTyAnnot")
1730 movelast tyannot -- use a _ pattern here
1731 nt <- getNameFrom (sMN 0 "nt")
1732 claim nt (Var (reflm "NameType"))
1733 movelast nt -- use a _ pattern here
1734 n' <- getNameFrom (sMN 0 "n")
1735 claim n' (Var (reflm "TTName"))
1736 fill $ reflCall "P" [Var nt, Var n', Var tyannot]
1738 focus n'; reflectNameQuotePattern n
1739reflectQuotePattern unq (V n)
1740 = do fill $ reflCall "V" [RConstant (I n)]
1742reflectQuotePattern unq (Bind n b x)
1743 = do x' <- claimTT (sMN 0 "sc")
1745 b' <- getNameFrom (sMN 0 "binder")
1746 claim b' (RApp (Var (sNS (sUN "Binder") ["Reflection", "Language"]))
1747 (Var (sNS (sUN "TT") ["Reflection", "Language"])))
1748 if n `elem` freeNames x
1749 then do fill $ reflCall "Bind"
1754 else do any <- getNameFrom (sMN 0 "anyName")
1755 claim any (Var (reflm "TTName"))
1757 fill $ reflCall "Bind"
1762 focus x'; reflectQuotePattern unq x
1763 focus b'; reflectBinderQuotePattern unq b
1766 reflectBinderQuotePattern :: [Name] -> Binder Term -> ElabD ()
1767 reflectBinderQuotePattern unq (Lam t)
1768 = do t' <- claimTT (sMN 0 "ty"); movelast t'
1769 fill $ reflCall "Lam" [Var (reflm "TT"), Var t']
1771 focus t'; reflectQuotePattern unq t
1772 reflectBinderQuotePattern unq (Pi t k)
1773 = do t' <- claimTT (sMN 0 "ty") ; movelast t'
1774 k' <- claimTT (sMN 0 "k"); movelast k';
1775 fill $ reflCall "Pi" [Var (reflm "TT"), Var t', Var k']
1777 focus t'; reflectQuotePattern unq t
1778 reflectBinderQuotePattern unq (Let x y)
1779 = do x' <- claimTT (sMN 0 "ty"); movelast x';
1780 y' <- claimTT (sMN 0 "v"); movelast y';
1781 fill $ reflCall "Let" [Var (reflm "TT"), Var x', Var y']
1783 focus x'; reflectQuotePattern unq x
1784 focus y'; reflectQuotePattern unq y
1785 reflectBinderQuotePattern unq (NLet x y)
1786 = do x' <- claimTT (sMN 0 "ty"); movelast x'
1787 y' <- claimTT (sMN 0 "v"); movelast y'
1788 fill $ reflCall "NLet" [Var (reflm "TT"), Var x', Var y']
1790 focus x'; reflectQuotePattern unq x
1791 focus y'; reflectQuotePattern unq y
1792 reflectBinderQuotePattern unq (Hole t)
1793 = do t' <- claimTT (sMN 0 "ty"); movelast t'
1794 fill $ reflCall "Hole" [Var (reflm "TT"), Var t']
1796 focus t'; reflectQuotePattern unq t
1797 reflectBinderQuotePattern unq (GHole _ t)
1798 = do t' <- claimTT (sMN 0 "ty"); movelast t'
1799 fill $ reflCall "GHole" [Var (reflm "TT"), Var t']
1801 focus t'; reflectQuotePattern unq t
1802 reflectBinderQuotePattern unq (Guess x y)
1803 = do x' <- claimTT (sMN 0 "ty"); movelast x'
1804 y' <- claimTT (sMN 0 "v"); movelast y'
1805 fill $ reflCall "Guess" [Var (reflm "TT"), Var x', Var y']
1807 focus x'; reflectQuotePattern unq x
1808 focus y'; reflectQuotePattern unq y
1809 reflectBinderQuotePattern unq (PVar t)
1810 = do t' <- claimTT (sMN 0 "ty"); movelast t'
1811 fill $ reflCall "PVar" [Var (reflm "TT"), Var t']
1813 focus t'; reflectQuotePattern unq t
1814 reflectBinderQuotePattern unq (PVTy t)
1815 = do t' <- claimTT (sMN 0 "ty"); movelast t'
1816 fill $ reflCall "PVTy" [Var (reflm "TT"), Var t']
1818 focus t'; reflectQuotePattern unq t
1819reflectQuotePattern unq (App f x)
1820 = do f' <- claimTT (sMN 0 "f"); movelast f'
1821 x' <- claimTT (sMN 0 "x"); movelast x'
1822 fill $ reflCall "App" [Var f', Var x']
1824 focus f'; reflectQuotePattern unq f
1825 focus x'; reflectQuotePattern unq x
1826reflectQuotePattern unq (Constant c)
1827 = do fill $ reflCall "TConst" [reflectConstant c]
1829reflectQuotePattern unq (Proj t i)
1830 = do t' <- claimTT (sMN 0 "t"); movelast t'
1831 fill $ reflCall "Proj" [Var t', RConstant (I i)]
1833 focus t'; reflectQuotePattern unq t
1834reflectQuotePattern unq (Erased)
1835 = do erased <- claimTT (sMN 0 "erased")
1839reflectQuotePattern unq (Impossible)
1840 = do fill $ Var (reflm "Impossible")
1842reflectQuotePattern unq (TType exp)
1843 = do ue <- getNameFrom (sMN 0 "uexp")
1844 claim ue (Var (sNS (sUN "TTUExp") ["Reflection", "Language"]))
1846 fill $ reflCall "TType" [Var ue]
1849-- | Create a reflected term, but leave refs to the provided name intact
1850reflectQuote :: [Name] -> Term -> Raw
1851reflectQuote unq (P nt n t)
1852 | n `elem` unq = Var n
1853 | otherwise = reflCall "P" [reflectNameType nt, reflectName n, reflectQuote unq t]
1854reflectQuote unq (V n)
1855 = reflCall "V" [RConstant (I n)]
1856reflectQuote unq (Bind n b x)
1857 = reflCall "Bind" [reflectName n, reflectBinderQuote unq b, reflectQuote unq x]
1858reflectQuote unq (App f x)
1859 = reflCall "App" [reflectQuote unq f, reflectQuote unq x]
1860reflectQuote unq (Constant c)
1861 = reflCall "TConst" [reflectConstant c]
1862reflectQuote unq (Proj t i)
1863 = reflCall "Proj" [reflectQuote unq t, RConstant (I i)]
1864reflectQuote unq (Erased) = Var (reflm "Erased")
1865reflectQuote unq (Impossible) = Var (reflm "Impossible")
1866reflectQuote unq (TType exp) = reflCall "TType" [reflectUExp exp]
1868reflectNameType :: NameType -> Raw
1869reflectNameType (Bound) = Var (reflm "Bound")
1870reflectNameType (Ref) = Var (reflm "Ref")
1871reflectNameType (DCon x y _)
1872 = reflCall "DCon" [RConstant (I x), RConstant (I y)] -- FIXME: Uniqueness!
1873reflectNameType (TCon x y)
1874 = reflCall "TCon" [RConstant (I x), RConstant (I y)]
1876reflectName :: Name -> Raw
1878 = reflCall "UN" [RConstant (Str (str s))]
1879reflectName (NS n ns)
1880 = reflCall "NS" [ reflectName n
1882 raw_apply ( Var $ sNS (sUN "::") ["List", "Prelude"] )
1883 [ RConstant StrType, RConstant (Str n), s ])
1884 ( raw_apply ( Var $ sNS (sUN "Nil") ["List", "Prelude"] )
1885 [ RConstant StrType ])
1889 = reflCall "MN" [RConstant (I i), RConstant (Str (str n))]
1890reflectName (NErased) = Var (reflm "NErased")
1891reflectName n = Var (reflm "NErased") -- special name, not yet implemented
1893-- | Elaborate a name to a pattern. This means that NS and UN will be intact.
1894-- MNs corresponding to will care about the string but not the number. All
1896reflectNameQuotePattern :: Name -> ElabD ()
1897reflectNameQuotePattern n@(UN s)
1898 = do fill $ reflectName n
1900reflectNameQuotePattern n@(NS _ _)
1901 = do fill $ reflectName n
1903reflectNameQuotePattern (MN _ n)
1904 = do i <- getNameFrom (sMN 0 "mnCounter")
1905 claim i (RConstant (AType (ATInt ITNative)))
1907 fill $ reflCall "MN" [Var i, RConstant (Str $ T.unpack n)]
1909reflectNameQuotePattern _ -- for all other names, match any
1910 = do nameHole <- getNameFrom (sMN 0 "name")
1911 claim nameHole (Var (reflm "TTName"))
1916reflectBinder :: Binder Term -> Raw
1917reflectBinder = reflectBinderQuote []
1919reflectBinderQuote :: [Name] -> Binder Term -> Raw
1920reflectBinderQuote unq (Lam t)
1921 = reflCall "Lam" [Var (reflm "TT"), reflectQuote unq t]
1922reflectBinderQuote unq (Pi t k)
1923 = reflCall "Pi" [Var (reflm "TT"), reflectQuote unq t, reflectQuote unq k]
1924reflectBinderQuote unq (Let x y)
1925 = reflCall "Let" [Var (reflm "TT"), reflectQuote unq x, reflectQuote unq y]
1926reflectBinderQuote unq (NLet x y)
1927 = reflCall "NLet" [Var (reflm "TT"), reflectQuote unq x, reflectQuote unq y]
1928reflectBinderQuote unq (Hole t)
1929 = reflCall "Hole" [Var (reflm "TT"), reflectQuote unq t]
1930reflectBinderQuote unq (GHole _ t)
1931 = reflCall "GHole" [Var (reflm "TT"), reflectQuote unq t]
1932reflectBinderQuote unq (Guess x y)
1933 = reflCall "Guess" [Var (reflm "TT"), reflectQuote unq x, reflectQuote unq y]
1934reflectBinderQuote unq (PVar t)
1935 = reflCall "PVar" [Var (reflm "TT"), reflectQuote unq t]
1936reflectBinderQuote unq (PVTy t)
1937 = reflCall "PVTy" [Var (reflm "TT"), reflectQuote unq t]
1939mkList :: Raw -> [Raw] -> Raw
1940mkList ty [] = RApp (Var (sNS (sUN "Nil") ["List", "Prelude"])) ty
1941mkList ty (x:xs) = RApp (RApp (RApp (Var (sNS (sUN "::") ["List", "Prelude"])) ty)
1945reflectConstant :: Const -> Raw
1946reflectConstant c@(I _) = reflCall "I" [RConstant c]
1947reflectConstant c@(BI _) = reflCall "BI" [RConstant c]
1948reflectConstant c@(Fl _) = reflCall "Fl" [RConstant c]
1949reflectConstant c@(Ch _) = reflCall "Ch" [RConstant c]
1950reflectConstant c@(Str _) = reflCall "Str" [RConstant c]
1951reflectConstant c@(B8 _) = reflCall "B8" [RConstant c]
1952reflectConstant c@(B16 _) = reflCall "B16" [RConstant c]
1953reflectConstant c@(B32 _) = reflCall "B32" [RConstant c]
1954reflectConstant c@(B64 _) = reflCall "B64" [RConstant c]
1955reflectConstant (B8V ws) = reflCall "B8V" [mkList (Var (sUN "Bits8")) . map (RConstant . B8) . V.toList $ ws]
1956reflectConstant (B16V ws) = reflCall "B8V" [mkList (Var (sUN "Bits16")) . map (RConstant . B16) . V.toList $ ws]
1957reflectConstant (B32V ws) = reflCall "B8V" [mkList (Var (sUN "Bits32")) . map (RConstant . B32) . V.toList $ ws]
1958reflectConstant (B64V ws) = reflCall "B8V" [mkList (Var (sUN "Bits64")) . map (RConstant . B64) . V.toList $ ws]
1959reflectConstant (AType (ATInt ITNative)) = reflCall "AType" [reflCall "ATInt" [Var (reflm "ITNative")]]
1960reflectConstant (AType (ATInt ITBig)) = reflCall "AType" [reflCall "ATInt" [Var (reflm "ITBig")]]
1961reflectConstant (AType ATFloat) = reflCall "AType" [Var (reflm "ATFloat")]
1962reflectConstant (AType (ATInt ITChar)) = reflCall "AType" [reflCall "ATInt" [Var (reflm "ITChar")]]
1963reflectConstant StrType = Var (reflm "StrType")
1964reflectConstant (AType (ATInt (ITFixed IT8))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITFixed" [Var (reflm "IT8")]]]
1965reflectConstant (AType (ATInt (ITFixed IT16))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITFixed" [Var (reflm "IT16")]]]
1966reflectConstant (AType (ATInt (ITFixed IT32))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITFixed" [Var (reflm "IT32")]]]
1967reflectConstant (AType (ATInt (ITFixed IT64))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITFixed" [Var (reflm "IT64")]]]
1968reflectConstant (AType (ATInt (ITVec IT8 c))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITVec" [Var (reflm "IT8"), RConstant (I c)]]]
1969reflectConstant (AType (ATInt (ITVec IT16 c))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITVec" [Var (reflm "IT16"), RConstant (I c)]]]
1970reflectConstant (AType (ATInt (ITVec IT32 c))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITVec" [Var (reflm "IT32"), RConstant (I c)]]]
1971reflectConstant (AType (ATInt (ITVec IT64 c))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITVec" [Var (reflm "IT64"), RConstant (I c)]]]
1972reflectConstant PtrType = Var (reflm "PtrType")
1973reflectConstant ManagedPtrType = Var (reflm "ManagedPtrType")
1974reflectConstant BufferType = Var (reflm "BufferType")
1975reflectConstant VoidType = Var (reflm "VoidType")
1976reflectConstant Forgot = Var (reflm "Forgot")
1979reflectUExp :: UExp -> Raw
1980reflectUExp (UVar i) = reflCall "UVar" [RConstant (I i)]
1981reflectUExp (UVal i) = reflCall "UVal" [RConstant (I i)]
1983-- | Reflect the environment of a proof into a List (TTName, Binder TT)
1984reflectEnv :: Env -> Raw
1985reflectEnv = foldr consToEnvList emptyEnvList
1987 consToEnvList :: (Name, Binder Term) -> Raw -> Raw
1988 consToEnvList (n, b) l
1989 = raw_apply (Var (sNS (sUN "::") ["List", "Prelude"]))
1991 , raw_apply (Var pairCon) [ (Var $ reflm "TTName")
1992 , (RApp (Var $ reflm "Binder")
2001 emptyEnvList = raw_apply (Var (sNS (sUN "Nil") ["List", "Prelude"]))
2004-- | Reflect an error into the internal datatype of Idris -- TODO
2005rawBool :: Bool -> Raw
2006rawBool True = Var (sNS (sUN "True") ["Bool", "Prelude"])
2007rawBool False = Var (sNS (sUN "False") ["Bool", "Prelude"])
2010rawNil ty = raw_apply (Var (sNS (sUN "Nil") ["List", "Prelude"])) [ty]
2012rawCons :: Raw -> Raw -> Raw -> Raw
2013rawCons ty hd tl = raw_apply (Var (sNS (sUN "::") ["List", "Prelude"])) [ty, hd, tl]
2015rawList :: Raw -> [Raw] -> Raw
2016rawList ty = foldr (rawCons ty) (rawNil ty)
2018rawPairTy :: Raw -> Raw -> Raw
2019rawPairTy t1 t2 = raw_apply (Var pairTy) [t1, t2]
2021rawPair :: (Raw, Raw) -> (Raw, Raw) -> Raw
2022rawPair (a, b) (x, y) = raw_apply (Var pairCon) [a, b, x, y]
2024reflectCtxt :: [(Name, Type)] -> Raw
2025reflectCtxt ctxt = rawList (rawPairTy (Var $ reflm "TTName") (Var $ reflm "TT"))
2026 (map (\ (n, t) -> (rawPair (Var $ reflm "TTName", Var $ reflm "TT")
2027 (reflectName n, reflect t)))
2030reflectErr :: Err -> Raw
2031reflectErr (Msg msg) = raw_apply (Var $ reflErrName "Msg") [RConstant (Str msg)]
2032reflectErr (InternalMsg msg) = raw_apply (Var $ reflErrName "InternalMsg") [RConstant (Str msg)]
2033reflectErr (CantUnify b t1 t2 e ctxt i) =
2034 raw_apply (Var $ reflErrName "CantUnify")
2041reflectErr (InfiniteUnify n tm ctxt) =
2042 raw_apply (Var $ reflErrName "InfiniteUnify")
2047reflectErr (CantConvert t t' ctxt) =
2048 raw_apply (Var $ reflErrName "CantConvert")
2053reflectErr (CantSolveGoal t ctxt) =
2054 raw_apply (Var $ reflErrName "CantSolveGoal")
2058reflectErr (UnifyScope n n' t ctxt) =
2059 raw_apply (Var $ reflErrName "UnifyScope")
2065reflectErr (CantInferType str) =
2066 raw_apply (Var $ reflErrName "CantInferType") [RConstant (Str str)]
2067reflectErr (NonFunctionType t t') =
2068 raw_apply (Var $ reflErrName "NonFunctionType") [reflect t, reflect t']
2069reflectErr (NotEquality t t') =
2070 raw_apply (Var $ reflErrName "NotEquality") [reflect t, reflect t']
2071reflectErr (TooManyArguments n) = raw_apply (Var $ reflErrName "TooManyArguments") [reflectName n]
2072reflectErr (CantIntroduce t) = raw_apply (Var $ reflErrName "CantIntroduce") [reflect t]
2073reflectErr (NoSuchVariable n) = raw_apply (Var $ reflErrName "NoSuchVariable") [reflectName n]
2074reflectErr (NoTypeDecl n) = raw_apply (Var $ reflErrName "NoTypeDecl") [reflectName n]
2075reflectErr (NotInjective t1 t2 t3) =
2076 raw_apply (Var $ reflErrName "NotInjective")
2081reflectErr (CantResolve t) = raw_apply (Var $ reflErrName "CantResolve") [reflect t]
2082reflectErr (CantResolveAlts ss) =
2083 raw_apply (Var $ reflErrName "CantResolveAlts")
2084 [rawList (Var $ (sUN "String")) (map Var ss)]
2085reflectErr (IncompleteTerm t) = raw_apply (Var $ reflErrName "IncompleteTerm") [reflect t]
2086reflectErr UniverseError = Var $ reflErrName "UniverseError"
2087reflectErr ProgramLineComment = Var $ reflErrName "ProgramLineComment"
2088reflectErr (Inaccessible n) = raw_apply (Var $ reflErrName "Inaccessible") [reflectName n]
2089reflectErr (NonCollapsiblePostulate n) = raw_apply (Var $ reflErrName "NonCollabsiblePostulate") [reflectName n]
2090reflectErr (AlreadyDefined n) = raw_apply (Var $ reflErrName "AlreadyDefined") [reflectName n]
2091reflectErr (ProofSearchFail e) = raw_apply (Var $ reflErrName "ProofSearchFail") [reflectErr e]
2092reflectErr (NoRewriting tm) = raw_apply (Var $ reflErrName "NoRewriting") [reflect tm]
2093reflectErr (ProviderError str) =
2094 raw_apply (Var $ reflErrName "ProviderError") [RConstant (Str str)]
2095reflectErr (LoadingFailed str err) =
2096 raw_apply (Var $ reflErrName "LoadingFailed") [RConstant (Str str)]
2097reflectErr x = raw_apply (Var (sNS (sUN "Msg") ["Errors", "Reflection", "Language"])) [RConstant . Str $ "Default reflection: " ++ show x]
2099elaboratingArgErr :: [(Name, Name)] -> Err -> Err
2100elaboratingArgErr [] err = err
2101elaboratingArgErr ((f,x):during) err = fromMaybe err (rewrite err)
2102 where rewrite (ElaboratingArg _ _ _ _) = Nothing
2103 rewrite (ProofSearchFail e) = fmap ProofSearchFail (rewrite e)
2104 rewrite (At fc e) = fmap (At fc) (rewrite e)
2105 rewrite err = Just (ElaboratingArg f x during err)
2108withErrorReflection :: Idris a -> Idris a
2109withErrorReflection x = idrisCatch x (\ e -> handle e >>= ierror)
2110 where handle :: Err -> Idris Err
2111 handle e@(ReflectionError _ _) = do logLvl 3 "Skipping reflection of error reflection result"
2112 return e -- Don't do meta-reflection of errors
2113 handle e@(ReflectionFailed _ _) = do logLvl 3 "Skipping reflection of reflection failure"
2115 -- At and Elaborating are just plumbing - error reflection shouldn't rewrite them
2116 handle e@(At fc err) = do logLvl 3 "Reflecting body of At"
2119 handle e@(Elaborating what n err) = do logLvl 3 "Reflecting body of Elaborating"
2121 return (Elaborating what n err')
2122 handle e@(ElaboratingArg f a prev err) = do logLvl 3 "Reflecting body of ElaboratingArg"
2123 hs <- getFnHandlers f a
2126 else applyHandlers err hs
2127 return (ElaboratingArg f a prev err')
2128 -- ProofSearchFail is an internal detail - so don't expose it
2129 handle (ProofSearchFail e) = handle e
2130 -- TODO: argument-specific error handlers go here for ElaboratingArg
2131 handle e = do ist <- getIState
2132 logLvl 2 "Starting error reflection"
2133 let handlers = idris_errorhandlers ist
2134 applyHandlers e handlers
2135 getFnHandlers :: Name -> Name -> Idris [Name]
2136 getFnHandlers f arg = do ist <- getIState
2137 let funHandlers = maybe M.empty id .
2139 idris_function_errorhandlers $ ist
2140 return . maybe [] S.toList . M.lookup arg $ funHandlers
2143 applyHandlers e handlers =
2145 let err = fmap (errReverse ist) e
2146 logLvl 3 $ "Using reflection handlers " ++
2147 concat (intersperse ", " (map show handlers))
2148 let reports = map (\n -> RApp (Var n) (reflectErr err)) handlers
2150 -- Typecheck error handlers - if this fails, then something else was wrong earlier!
2151 handlers <- case mapM (check (tt_ctxt ist) []) reports of
2152 Error e -> ierror $ ReflectionFailed "Type error while constructing reflected error" e
2155 -- Normalize error handler terms to produce the new messages
2157 let results = map (normalise ctxt []) (map fst handlers)
2158 logLvl 3 $ "New error message info: " ++ concat (intersperse " and " (map show results))
2160 -- For each handler term output, either discard it if it is Nothing or reify it the Haskell equivalent
2161 let errorpartsTT = mapMaybe unList (mapMaybe fromTTMaybe results)
2162 errorparts <- case mapM (mapM reifyReportPart) errorpartsTT of
2163 Left err -> ierror err
2164 Right ok -> return ok
2165 return $ case errorparts of
2167 parts -> ReflectionError errorparts e
2169fromTTMaybe :: Term -> Maybe Term -- WARNING: Assumes the term has type Maybe a
2170fromTTMaybe (App (App (P (DCon _ _ _) (NS (UN just) _) _) ty) tm)
2171 | just == txt "Just" = Just tm
2172fromTTMaybe x = Nothing
2174reflErrName :: String -> Name
2175reflErrName n = sNS (sUN n) ["Errors", "Reflection", "Language"]
2177-- | Attempt to reify a report part from TT to the internal
2178-- representation. Not in Idris or ElabD monads because it should be usable
2180reifyReportPart :: Term -> Either Err ErrorReportPart
2181reifyReportPart (App (P (DCon _ _ _) n _) (Constant (Str msg))) | n == reflm "TextPart" =
2182 Right (TextPart msg)
2183reifyReportPart (App (P (DCon _ _ _) n _) ttn)
2184 | n == reflm "NamePart" =
2185 case runElab [] (reifyTTName ttn) (initElaborator NErased initContext Erased) of
2186 Error e -> Left . InternalMsg $
2187 "could not reify name term " ++
2189 " when reflecting an error:" ++ show e
2190 OK (n', _)-> Right $ NamePart n'
2191reifyReportPart (App (P (DCon _ _ _) n _) tm)
2192 | n == reflm "TermPart" =
2193 case runElab [] (reifyTT tm) (initElaborator NErased initContext Erased) of
2194 Error e -> Left . InternalMsg $
2195 "could not reify reflected term " ++
2197 " when reflecting an error:" ++ show e
2198 OK (tm', _) -> Right $ TermPart tm'
2199reifyReportPart (App (P (DCon _ _ _) n _) tm)
2200 | n == reflm "SubReport" =
2202 Just xs -> do subParts <- mapM reifyReportPart xs
2203 Right (SubReport subParts)
2204 Nothing -> Left . InternalMsg $ "could not reify subreport " ++ show tm
2205reifyReportPart x = Left . InternalMsg $ "could not reify " ++ show x
2209 = raw_apply (Var pairTy) [ (Var $ reflm "TTName")
2210 , (RApp (Var $ reflm "Binder") (Var $ reflm "TT"))
2213solveAll = try (do solve; solveAll) (return ())
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list