1{-# LANGUAGE PatternGuards, ViewPatterns #-}
2{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
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
56 when (not pattern) $ solveAutos ist fn True
61 -- Resolve remaining type classes. Two passes - first to get the
62 -- default Num instances, second to clean up the rest
64 mapM_ (\n -> when (n `elem` hs) $
67 try (resolveTC True 7 g fn ist)
72 mapM_ (\n -> when (n `elem` hs) $
75 resolveTC True 7 g fn ist) ivs
83 traceWhen u ("Remaining holes:\n" ++ show hs ++ "\n" ++
84 "Remaining problems:\n" ++ qshow probs) $
85 do unify_all; matchProblems True; unifyProblems
90 ((_,_,_,_,e,_,_):es) -> traceWhen u ("Final problems:\n" ++ show probs) $
94 when tydecl (do update_term orderPats
96-- update_term liftPats)
99 let (tm, ds) = runState (collectDeferred (Just fn) tt) []
101 if (log /= "") then trace log $ return (tm, ds, is)
102 else return (tm, ds, is)
103 where pattern = emode == ELHS
104 tydecl = emode == ETyDecl
106 mkPat = do hs <- get_holes
109 (h: hs) -> do patvar h; mkPat
112-- Build a term autogenerated as a typeclass method definition
113-- (Separate, so we don't go overboard resolving things that we don't
114-- know about yet on the LHS of a pattern def)
116buildTC :: IState -> ElabInfo -> ElabMode -> FnOpts -> Name -> PTerm ->
117 ElabD (Term, [(Name, (Int, Maybe Name, Type))], [PDecl])
118buildTC ist info emode opts fn tm
119 = do -- set name supply to begin after highest index in tm
120 let ns = allNamesIn tm
122 let inf = case lookupCtxt fn (idris_tyinfodata ist) of
126 elab ist info emode opts fn tm
131 ((_,_,_,_,e,_,_):es) -> if inf then return ()
134 -- 'dots' are the PHidden things which have not been solved by
136 when (not (null dots)) $
137 lift (Error (CantMatch (getInferTerm tm)))
138 EState is _ <- getAux
140 let (tm, ds) = runState (collectDeferred (Just fn) tt) []
142 if (log /= "") then trace log $ return (tm, ds, is)
143 else return (tm, ds, is)
144 where pattern = emode == ELHS
146-- return whether arguments of the given constructor name can be
147-- matched on. If they're polymorphic, no, unless the type has beed made
148-- concrete by the time we get around to elaborating the argument.
149getUnmatchable :: Context -> Name -> [Bool]
150getUnmatchable ctxt n | isDConName n ctxt && n /= inferCon
151 = case lookupTyExact n ctxt of
153 Just ty -> checkArgs [] [] ty
154 where checkArgs :: [Name] -> [[Name]] -> Type -> [Bool]
155 checkArgs env ns (Bind n (Pi _ t _) sc)
156 = let env' = case t of
159 checkArgs env' (intersect env (refsIn t) : ns)
160 (instantiate (P Bound n t) sc)
162 = map (not . null) (reverse ns)
164getUnmatchable ctxt n = []
166data ElabCtxt = ElabCtxt { e_inarg :: Bool,
167 e_isfn :: Bool, -- ^ Function part of application
171 e_nomatching :: Bool -- ^ can't pattern match
174initElabCtxt = ElabCtxt False False False False False False
176goal_polymorphic :: ElabD Bool
180 P _ n _ -> do env <- get_env
182 Nothing -> return False
186-- Returns the set of declarations we need to add to complete the definition
187-- (most likely case blocks to elaborate)
189elab :: IState -> ElabInfo -> ElabMode -> FnOpts -> Name -> PTerm ->
191elab ist info emode opts fn tm
192 = do let loglvl = opt_logLevel (idris_options ist)
193 when (loglvl > 5) $ unifyLog True
194 compute -- expand type synonyms, etc
195 let fc = maybe "(unknown)"
196 elabE initElabCtxt (elabFC info) tm -- (in argument, guarded, in type, in qquote)
198 sequence_ (delayed_elab est)
201 when pattern -- convert remaining holes to pattern vars
202 (do update_term orderPats
204 matchProblems False -- only the ones we matched earlier
208 pattern = emode == ELHS
209 bindfree = emode == ETyDecl || emode == ELHS
211 tcgen = Dictionary `elem` opts
212 reflection = Reflection `elem` opts
214 isph arg = case getTm arg of
215 Placeholder -> (True, priority arg)
216 tm -> (False, priority arg)
218 toElab ina arg = case getTm arg of
219 Placeholder -> Nothing
220 v -> Just (priority arg, elabE ina (elabFC info) v)
222 toElab' ina arg = case getTm arg of
223 Placeholder -> Nothing
224 v -> Just (elabE ina (elabFC info) v)
226 mkPat = do hs <- get_holes
229 (h: hs) -> do patvar h; mkPat
232 -- | elabE elaborates an expression, possibly wrapping implicit coercions
233 -- and forces/delays. If you make a recursive call in elab', it is
234 -- normally correct to call elabE - the ones that don't are desugarings
236 elabE :: ElabCtxt -> Maybe FC -> PTerm -> ElabD ()
239 --trace ("Elaborating " ++ show t ++ " : " ++ show g) $
240 do solved <- get_recents
242 -- If any of the autos use variables which have recently been solved,
243 -- have another go at solving them now.
244 mapM_ (\(a, ns) -> if any (\n -> n `elem` solved) ns
245 then solveAuto ist fn False a
248 itm <- if not pattern then insertImpLam ina t else return t
249 ct <- insertCoerce ina itm
256 --trace ("Elaborating " ++ show t' ++ " in " ++ show g
257 -- ++ "\n" ++ show tm
258 -- ++ "\nholes " ++ show hs
259 -- ++ "\nproblems " ++ show ps
260 -- ++ "\n-----------\n") $
261 --trace ("ELAB " ++ show t') $
262 let fc = fileFC "Force"
264 handleError (forceErr env)
266 (elab' ina fc' (PApp fc (PRef fc (sUN "Force"))
267 [pimp (sUN "t") Placeholder True,
268 pimp (sUN "a") Placeholder True,
271 forceErr env (CantUnify _ (t,_) (t',_) _ _ _)
272 | (P _ (UN ht) _, _) <- unApply (normalise (tt_ctxt ist) env t),
273 ht == txt "Lazy'" = True
274 forceErr env (CantUnify _ (t,_) (t',_) _ _ _)
275 | (P _ (UN ht) _, _) <- unApply (normalise (tt_ctxt ist) env t'),
276 ht == txt "Lazy'" = True
277 forceErr env (InfiniteUnify _ t _)
278 | (P _ (UN ht) _, _) <- unApply (normalise (tt_ctxt ist) env t),
279 ht == txt "Lazy'" = True
280 forceErr env (Elaborating _ _ t) = forceErr env t
281 forceErr env (ElaboratingArg _ _ _ t) = forceErr env t
282 forceErr env (At _ t) = forceErr env t
283 forceErr env t = False
285 local f = do e <- get_env
286 return (f `elem` map fst e)
288 -- | Is a constant a type?
289 constType :: Const -> Bool
290 constType (AType _) = True
291 constType StrType = True
292 constType PtrType = True
293 constType VoidType = True
296 -- "guarded" means immediately under a constructor, to help find patvars
298 elab' :: ElabCtxt -- ^ (in an argument, guarded, in a type, in a quasiquote)
299 -> Maybe FC -- ^ The closest FC in the syntax tree, if applicable
300 -> PTerm -- ^ The term to elaborate
302 elab' ina fc (PNoImplicits t) = elab' ina fc t -- skip elabE step
303 elab' ina fc PType = do apply RType []; solve
304 elab' ina fc (PUniverse u) = do apply (RUType u) []; solve
305-- elab' (_,_,inty) (PConstant c)
306-- | constType c && pattern && not reflection && not inty
307-- = lift $ tfail (Msg "Typecase is not allowed")
308 elab' ina fc tm@(PConstant c)
309 | pattern && not reflection && not (e_qq ina) && not (e_intype ina)
311 = lift $ tfail $ Msg ("No explicit types on left hand side: " ++ show tm)
312 | pattern && not reflection && not (e_qq ina) && e_nomatching ina
313 = lift $ tfail $ Msg ("Attempting concrete match on polymorphic argument: " ++ show tm)
314 | otherwise = do apply (RConstant c) []; solve
315 elab' ina fc (PQuote r) = do fill r; solve
316 elab' ina _ (PTrue fc _) =
320 TType _ -> elab' ina (Just fc) (PRef fc unitTy)
321 UType _ -> elab' ina (Just fc) (PRef fc unitTy)
322 _ -> elab' ina (Just fc) (PRef fc unitCon)
323 elab' ina fc (PResolveTC (FC "HACK" _ _)) -- for chasing parent classes
324 = do g <- goal; resolveTC False 5 g fn ist
325 elab' ina fc (PResolveTC fc')
326 = do c <- getNameFrom (sMN 0 "class")
328 elab' ina _ (PRefl fc t)
329 = elab' ina (Just fc) (PApp fc (PRef fc eqCon) [pimp (sMN 0 "A") Placeholder True,
330 pimp (sMN 0 "x") t False])
331 elab' ina _ (PEq fc Placeholder Placeholder l r)
332 = try (do tyn <- getNameFrom (sMN 0 "aqty")
335 elab' ina (Just fc) (PApp fc (PRef fc eqTy)
336 [pimp (sUN "A") (PRef fc tyn) True,
337 pimp (sUN "B") (PRef fc tyn) False,
339 (do atyn <- getNameFrom (sMN 0 "aqty")
340 btyn <- getNameFrom (sMN 0 "bqty")
345 elab' ina (Just fc) (PApp fc (PRef fc eqTy)
346 [pimp (sUN "A") (PRef fc atyn) True,
347 pimp (sUN "B") (PRef fc btyn) False,
350 elab' ina _ (PEq fc lt rt l r) = elab' ina (Just fc) (PApp fc (PRef fc eqTy)
351 [pimp (sUN "A") lt True,
352 pimp (sUN "B") rt False,
354 elab' ina _ (PPair fc _ l r)
357 let (tc, _) = unApply g
359 TType _ -> elab' ina (Just fc) (PApp fc (PRef fc pairTy)
361 UType _ -> elab' ina (Just fc) (PApp fc (PRef fc upairTy)
364 P _ n _ | n == upairTy
365 -> elab' ina (Just fc) (PApp fc (PRef fc upairCon)
366 [pimp (sUN "A") Placeholder False,
367 pimp (sUN "B") Placeholder False,
369 _ -> elab' ina (Just fc) (PApp fc (PRef fc pairCon)
370 [pimp (sUN "A") Placeholder False,
371 pimp (sUN "B") Placeholder False,
373-- _ -> try' (elab' ina (Just fc) (PApp fc (PRef fc pairCon)
374-- [pimp (sUN "A") Placeholder False,
375-- pimp (sUN "B") Placeholder False,
377-- (elab' ina (Just fc) (PApp fc (PRef fc upairCon)
378-- [pimp (sUN "A") Placeholder False,
379-- pimp (sUN "B") Placeholder False,
383 elab' ina _ (PDPair fc p l@(PRef _ n) t r)
392 where asType = elab' ina (Just fc) (PApp fc (PRef fc sigmaTy)
394 pexp (PLam fc n Placeholder r)])
395 asValue = elab' ina (Just fc) (PApp fc (PRef fc existsCon)
396 [pimp (sMN 0 "a") t False,
397 pimp (sMN 0 "P") Placeholder True,
399 elab' ina _ (PDPair fc p l t r) = elab' ina (Just fc) (PApp fc (PRef fc existsCon)
400 [pimp (sMN 0 "a") t False,
401 pimp (sMN 0 "P") Placeholder True,
403 elab' ina fc (PAlternative True as)
407 let (tc, _) = unApply ty
409 let as' = pruneByType (map fst env) tc ctxt as
410-- trace (-- show tc ++ " " ++ show as ++ "\n ==> " ++
411-- show (length as') ++ "\n" ++
412-- showSep ", " (map showTmImpls as') ++ "\nEND") $
413 tryAll (zip (map (elab' ina fc) as') (map showHd as'))
414 where showHd (PApp _ (PRef _ n) _) = n
415 showHd (PRef _ n) = n
416 showHd (PApp _ h _) = showHd h
417 showHd x = NErased -- We probably should do something better than this here
418 elab' ina fc (PAlternative False as)
420 where -- if none work, take the error from the first
421 trySeq (x : xs) = let e1 = elab' ina fc x in
422 try' e1 (trySeq' e1 xs) True
423 trySeq [] = fail "Nothing to try in sequence"
424 trySeq' deferr [] = proofFail deferr
425 trySeq' deferr (x : xs)
426 = try' (do elab' ina fc x
427 solveAutos ist fn False) (trySeq' deferr xs) True
428 elab' ina _ (PPatvar fc n) | bindfree = do patvar n; update_term liftPats
429-- elab' (_, _, inty) (PRef fc f)
430-- | isTConName f (tt_ctxt ist) && pattern && not reflection && not inty
431-- = lift $ tfail (Msg "Typecase is not allowed")
432 elab' ec _ tm@(PRef fc n)
433 | pattern && not reflection && not (e_qq ec) && not (e_intype ec)
434 && isTConName n (tt_ctxt ist)
435 = lift $ tfail $ Msg ("No explicit types on left hand side: " ++ show tm)
436 | pattern && not reflection && not (e_qq ec) && e_nomatching ec
437 = lift $ tfail $ Msg ("Attempting concrete match on polymorphic argument: " ++ show tm)
438 | (pattern || (bindfree && bindable n)) && not (inparamBlock n) && not (e_qq ec)
439 = do let ina = e_inarg ec
440 guarded = e_guarded ec
443 let defined = case lookupTy n ctxt of
446 -- this is to stop us resolve type classes recursively
447 -- trace (show (n, guarded)) $
448 if (tcname n && ina) then erun fc $ do patvar n; -- update_term liftPats
449 else if (defined && not guarded)
450 then do apply (Var n) []; solve
451 else try (do apply (Var n) []; solve)
452 (do patvar n; update_term liftPats)
453 where inparamBlock n = case lookupCtxtName n (inblock info) of
456 bindable (NS _ _) = False
457 bindable (UN xs) = True
458 bindable n = implicitable n
459 elab' ina _ f@(PInferRef fc n) = elab' ina (Just fc) (PApp fc f [])
460 elab' ina fc' tm@(PRef fc n)
461 | pattern && not reflection && not (e_qq ina) && not (e_intype ina)
462 && isTConName n (tt_ctxt ist)
463 = lift $ tfail $ Msg ("No explicit types on left hand side: " ++ show tm)
464 | pattern && not reflection && not (e_qq ina) && e_nomatching ina
465 = lift $ tfail $ Msg ("Attempting concrete match on polymorphic argument: " ++ show tm)
467 do fty <- get_type (Var n) -- check for implicits
470 let a' = insertScopedImps fc (normalise ctxt env fty) []
472 then erun fc $ do apply (Var n) []; solve
473 else elab' ina fc' (PApp fc tm [])
474 elab' ina _ (PLam fc n Placeholder sc)
475 = do -- if n is a type constructor name, this makes no sense...
477 when (isTConName n ctxt) $
478 lift $ tfail (Msg $ "Can't use type constructor " ++ show n ++ " here")
480 attack; intro (Just n);
481 -- trace ("------ intro " ++ show n ++ " ---- \n" ++ show ptm)
482 elabE (ina { e_inarg = True } ) (Just fc) sc; solve
483 elab' ec _ (PLam fc n ty sc)
484 = do tyn <- getNameFrom (sMN 0 "lamty")
485 -- if n is a type constructor name, this makes no sense...
487 when (isTConName n ctxt) $
488 lift $ tfail (Msg $ "Can't use type constructor " ++ show n ++ " here")
495 introTy (Var tyn) (Just n)
498 elabE (ec { e_inarg = True, e_intype = True }) (Just fc) ty
499 elabE (ec { e_inarg = True }) (Just fc) sc
501 elab' ina fc (PPi p n Placeholder sc)
502 = do attack; arg n (is_scoped p) (sMN 0 "ty")
503 elabE (ina { e_inarg = True, e_intype = True }) fc sc
505 elab' ina fc (PPi p n ty sc)
506 = do attack; tyn <- getNameFrom (sMN 0 "ty")
509 MN _ _ -> unique_hole n
511 forall n' (is_scoped p) (Var tyn)
513 let ec' = ina { e_inarg = True, e_intype = True }
517 elab' ina _ (PLet fc n ty val sc)
520 tyn <- getNameFrom (sMN 0 "letty")
522 valn <- getNameFrom (sMN 0 "letval")
525 letbind n (Var tyn) (Var valn)
527 Placeholder -> return ()
530 elabE (ina { e_inarg = True, e_intype = True })
533 elabE (ina { e_inarg = True, e_intype = True })
535 ivs' <- get_instances
537 elabE (ina { e_inarg = True }) (Just fc) sc
539 mapM_ (\n -> do focus n
542 if all (\n -> n == tyn || not (n `elem` hs)) (freeNames g)
543 then try (resolveTC True 7 g fn ist)
547 -- HACK: If the name leaks into its type, it may leak out of
548 -- scope outside, so substitute in the outer scope.
549 expandLet n (case lookup n env of
551 other -> error ("Value not a let binding: " ++ show other))
553 elab' ina _ (PGoal fc r n sc) = do
556 tyn <- getNameFrom (sMN 0 "letty")
558 valn <- getNameFrom (sMN 0 "letval")
560 letbind n (Var tyn) (Var valn)
562 elabE (ina { e_inarg = True, e_intype = True }) (Just fc) (PApp fc r [pexp (delab ist rty)])
565 elabE (ina { e_inarg = True }) (Just fc) sc
567-- elab' ina fc (PLet n Placeholder
568-- (PApp fc r [pexp (delab ist rty)]) sc)
569 elab' ina _ tm@(PApp fc (PInferRef _ f) args) = do
573 -- make a function type a -> b -> c -> ... -> rty for the
576 argTys <- claimArgTys env args
577 fn <- getNameFrom (sMN 0 "inf_fn")
578 let fty = fnTy argTys rty
579-- trace (show (ptm, map fst argTys)) $ focus fn
580 -- build and defer the function application
581 attack; deferType (mkN f) fty (map fst argTys); solve
582 -- elaborate the arguments, to unify their types. They all have to
584 mapM_ elabIArg (zip argTys args)
585 where claimArgTys env [] = return []
586 claimArgTys env (arg : xs) | Just n <- localVar env (getTm arg)
587 = do nty <- get_type (Var n)
588 ans <- claimArgTys env xs
589 return ((n, (False, forget nty)) : ans)
590 claimArgTys env (_ : xs)
591 = do an <- getNameFrom (sMN 0 "inf_argTy")
592 aval <- getNameFrom (sMN 0 "inf_arg")
595 ans <- claimArgTys env xs
596 return ((aval, (True, (Var an))) : ans)
597 fnTy [] ret = forget ret
598 fnTy ((x, (_, xt)) : xs) ret = RBind x (Pi Nothing xt RType) (fnTy xs ret)
600 localVar env (PRef _ x)
601 = case lookup x env of
604 localVar env _ = Nothing
606 elabIArg ((n, (True, ty)), def) =
607 do focus n; elabE ina (Just fc) (getTm def)
608 elabIArg _ = return () -- already done, just a name
612 mkN n = case namespace info of
613 Just xs@(_:_) -> sNS n xs
616 elab' ina _ (PMatchApp fc fn)
617 = do (fn', imps) <- case lookupCtxtName fn (idris_implicits ist) of
618 [(n, args)] -> return (n, map (const True) args)
619 _ -> lift $ tfail (NoSuchVariable fn)
620 ns <- match_apply (Var fn') (map (\x -> (x,0)) imps)
622 -- if f is local, just do a simple_app
623 -- FIXME: Anyone feel like refactoring this mess? - EB
624 elab' ina topfc tm@(PApp fc (PRef _ f) args_in)
625 | pattern && not reflection && not (e_qq ina) && e_nomatching ina
626 = lift $ tfail $ Msg ("Attempting concrete match on polymorphic argument: " ++ show tm)
627 | otherwise = implicitApp $
630 fty <- get_type (Var f)
632 let args = insertScopedImps fc (normalise ctxt env fty) args_in
633 let unmatchableArgs = if pattern
634 then getUnmatchable (tt_ctxt ist) f
636-- trace ("BEFORE " ++ show f ++ ": " ++ show ty) $
637 when (pattern && not reflection && not (e_qq ina) && not (e_intype ina)
638 && isTConName f (tt_ctxt ist)) $
639 lift $ tfail $ Msg ("No explicit types on left hand side: " ++ show tm)
640 if (f `elem` map fst env && length args == 1 && length args_in == 1)
641 then -- simple app, as below
643 (elabE (ina { e_isfn = True }) (Just fc) (PRef fc f))
644 (elabE (ina { e_inarg = True }) (Just fc) (getTm (head args)))
649 do ivs <- get_instances
651 -- HACK: we shouldn't resolve type classes if we're defining an instance
652 -- function or default definition.
653 let isinf = f == inferCon || tcname f
654 -- if f is a type class, we need to know its arguments so that
655 -- we can unify with them
656 case lookupCtxt f (idris_classes ist) of
658 _ -> do mapM_ setInjective (map getTm args)
659 -- maybe more things are solvable now
661 let guarded = isConName f ctxt
662-- trace ("args is " ++ show args) $ return ()
663 ns <- apply (Var f) (map isph args)
664-- trace ("ns is " ++ show ns) $ return ()
665 -- mark any type class arguments as injective
666 mapM_ checkIfInjective (map snd ns)
667 unifyProblems -- try again with the new information,
668 -- to help with disambiguation
669 -- Sort so that the implicit tactics and alternatives go last
670 let (ns', eargs) = unzip $
671 sortBy cmpArg (zip ns args)
673 elabArgs ist (ina { e_inarg = e_inarg ina || not isinf })
675 (zip ns' (unmatchableArgs ++ repeat False))
677 (map (\x -> getTm x) eargs) -- TODO: remove this False arg
678 imp <- if (e_isfn ina) then
679 do guess <- get_guess
680 gty <- get_type (forget guess)
682 let ty_n = normalise ctxt env gty
683 return $ getReqImps ty_n
685 -- Now we find out how many implicits we needed at the
686 -- end of the application by looking at the goal again
687 -- - Have another go, but this time add the
688 -- implicits (can't think of a better way than this...)
690 rs@(_:_) | not pattern -> return rs -- quit, try again
693 ivs' <- get_instances
694 -- Attempt to resolve any type classes which have 'complete' types,
695 -- i.e. no holes in them
696 when (not pattern || (e_inarg ina && not tcgen &&
697 not (e_guarded ina))) $
698 mapM_ (\n -> do focus n
702 if all (\n -> not (n `elem` hs)) (freeNames g)
703 then try (resolveTC False 7 g fn ist)
709 -- Run the elaborator, which returns how many implicit
710 -- args were needed, then run it again with those args. We need
711 -- this because we have to elaborate the whole application to
712 -- find out whether any computations have caused more implicits
714 implicitApp :: ElabD [ImplicitInfo] -> ElabD ()
716 | pattern = do elab; return ()
723 elab' ina topfc (PAppImpl tm es)
725 getReqImps (Bind x (Pi (Just i) ty _) sc)
729 -- normal < alternatives < lambdas < rewrites < tactic < default tactic
730 -- reason for lambdas after alternatives is that having
731 -- the alternative resolved can help with typechecking the lambda
732 -- or the rewrite. Rewrites/tactics need as much information
733 -- as possible about the type.
734 -- FIXME: Better would be to allow alternative resolution to be
735 -- retried after more information is in.
737 | constraint x && not (constraint y) = LT
738 | constraint y && not (constraint x) = GT
740 = compare (conDepth 0 (getTm x) + priority x + alt x)
741 (conDepth 0 (getTm y) + priority y + alt y)
742 where alt t = case getTm t of
743 PAlternative False _ -> 5
744 PAlternative True _ -> 2
747 PRewrite _ _ _ _ -> 4
752 constraint (PConstraint _ _ _ _) = True
755 -- Score a point for every level where there is a non-constructor
756 -- function (so higher score --> done later), and lots of points
757 -- if there is a PHidden since this should be unifiable.
758 -- Only relevant when on lhs
759 conDepth d t | not pattern = 0
760 conDepth d (PRef _ f) | isConName f (tt_ctxt ist) = 0
761 | otherwise = max (100 - d) 1
762 conDepth d (PApp _ f as)
763 = conDepth d f + sum (map (conDepth (d+1)) (map getTm as))
764 conDepth d (PPatvar _ _) = 0
765 conDepth d (PAlternative _ as) = maximum (map (conDepth d) as)
766 conDepth d (PHidden _) = 150
767 conDepth d Placeholder = 0
768 conDepth d (PResolveTC _) = 0
769 conDepth d t = max (100 - d) 1
771 checkIfInjective n = do
776 case unApply (binderTy b) of
778 case lookupCtxt c (idris_classes ist) of
780 _ -> -- type class, set as injective
781 do mapM_ setinjArg args
782 -- maybe we can solve more things now...
785 traceWhen ulog ("Injective now " ++ show args ++ "\n" ++ qshow probs) $
788 traceWhen ulog (qshow probs) $ return ()
791 setinjArg (P _ n _) = setinj n
792 setinjArg _ = return ()
794 tacTm (PTactics _) = True
795 tacTm (PProof _) = True
798 setInjective (PRef _ n) = setinj n
799 setInjective (PApp _ (PRef _ n) _) = setinj n
800 setInjective _ = return ()
802 elab' ina _ tm@(PApp fc f [arg]) =
804 do simple_app (not $ headRef f)
805 (elabE (ina { e_isfn = True }) (Just fc) f)
806 (elabE (ina { e_inarg = True }) (Just fc) (getTm arg))
809 where headRef (PRef _ _) = True
810 headRef (PApp _ f _) = headRef f
813 elab' ina fc (PAppImpl f es) = do appImpl (reverse es) -- not that we look...
815 where appImpl [] = elab' (ina { e_isfn = False }) fc f -- e_isfn not set, so no recursive expansion of implicits
816 appImpl (e : es) = simple_app False
818 (elab' ina fc Placeholder)
820 elab' ina fc Placeholder
821 = do (h : hs) <- get_holes
823 elab' ina fc (PMetavar n) =
825 -- When building the metavar application, leave out the unique
826 -- names which have been used elsewhere in the term, since we
827 -- won't be able to use them in the resulting application.
828 let unique_used = getUniqueUsed (tt_ctxt ist) ptm
833 where mkN n@(NS _ _) = n
834 mkN n = case namespace info of
835 Just xs@(_:_) -> sNS n xs
837 elab' ina fc (PProof ts) = do compute; mapM_ (runTac True ist (elabFC info) fn) ts
838 elab' ina fc (PTactics ts)
839 | not pattern = do mapM_ (runTac False ist fc fn) ts
840 | otherwise = elab' ina fc Placeholder
841 elab' ina fc (PElabError e) = lift $ tfail e
842 elab' ina _ (PRewrite fc r sc newg)
844 tyn <- getNameFrom (sMN 0 "rty")
846 valn <- getNameFrom (sMN 0 "rval")
848 letn <- getNameFrom (sMN 0 "_rewrite_rule")
849 letbind letn (Var tyn) (Var valn)
851 elab' ina (Just fc) r
856 when (g == g') $ lift $ tfail (NoRewriting g)
858 Nothing -> elab' ina (Just fc) sc
859 Just t -> doEquiv t sc
863 tyn <- getNameFrom (sMN 0 "ety")
865 valn <- getNameFrom (sMN 0 "eqval")
867 letn <- getNameFrom (sMN 0 "equiv_val")
868 letbind letn (Var tyn) (Var valn)
870 elab' ina (Just fc) t
872 elab' ina (Just fc) sc
873 elab' ina (Just fc) (PRef fc letn)
875 elab' ina _ c@(PCase fc scr opts)
877 tyn <- getNameFrom (sMN 0 "scty")
879 valn <- getNameFrom (sMN 0 "scval")
880 scvn <- getNameFrom (sMN 0 "scvar")
882 letbind scvn (Var tyn) (Var valn)
884 elabE (ina { e_inarg = True }) (Just fc) scr
885 -- Solve any remaining implicits - we need to solve as many
886 -- as possible before making the 'case' type
890 envU <- mapM (getKind args) args
891 let namesUsedInRHS = nub $ scvn : concatMap (\(_,rhs) -> allNamesIn rhs) opts
893 -- Drop the unique arguments used in the term already
894 -- and in the scrutinee (since it's
895 -- not valid to use them again anyway)
897 -- Also drop unique arguments which don't appear explicitly
898 -- in either case branch so they don't count as used
899 -- unnecessarily (can only do this for unique things, since we
900 -- assume they don't appear implicitly in types)
902 let inOpts = (filter (/= scvn) (map fst args)) \\ (concatMap (\x -> allNamesIn (snd x)) opts)
904 let argsDropped = filter (isUnique envU)
905 (nub $ allNamesIn scr ++ inApp ptm ++
908 let args' = filter (\(n, _) -> n `notElem` argsDropped) args
910 cname <- unique_hole' True (mkCaseName fn)
911 let cname' = mkN cname
912-- elab' ina fc (PMetavar cname')
913 attack; defer argsDropped cname'; solve
915 -- if the scrutinee is one of the 'args' in env, we should
916 -- inspect it directly, rather than adding it as a new argument
917 let newdef = PClauses fc [] cname'
919 (map (isScr scr) (reverse args')) opts)
921 updateAux (\e -> e { case_decls = newdef : case_decls e } )
922 -- if we haven't got the type yet, hopefully we'll get it later!
925 where mkCaseName (NS n ns) = NS (mkCaseName n) ns
926 mkCaseName n = SN (CaseN n)
927-- mkCaseName (UN x) = UN (x ++ "_case")
928-- mkCaseName (MN i x) = MN i (x ++ "_case")
930 mkN n = case namespace info of
931 Just xs@(_:_) -> sNS n xs
934 inApp (P _ n _) = [n]
935 inApp (App f a) = inApp f ++ inApp a
936 inApp (Bind n (Let _ v) sc) = inApp v ++ inApp sc
937 inApp (Bind n (Guess _ v) sc) = inApp v ++ inApp sc
938 inApp (Bind n b sc) = inApp sc
941 isUnique envk n = case lookup n envk of
946 = case lookup n env of
947 Nothing -> return (n, False) -- can't happen, actually...
949 do ty <- get_type (forget (binderTy b))
951 UType UniqueType -> return (n, True)
952 UType AllTypes -> return (n, True)
953 _ -> return (n, False)
955 tcName tm | (P _ n _, _) <- unApply tm
956 = case lookupCtxt n (idris_classes ist) of
963 || any (\x -> x `elem` ns) (allTTNames (binderTy b))
965 elab' ina fc (PUnifyLog t) = do unifyLog True
968 elab' ina fc (PQuasiquote t goal)
969 = do -- First extract the unquoted subterms, replacing them with fresh
970 -- names in the quasiquoted term. Claim their reflections to be
971 -- an inferred type (to support polytypic quasiquotes).
972 (t, unq) <- extractUnquotes 0 t
973 let unquoteNames = map fst unq
974 mapM_ (\uqn -> do uqh <- getNameFrom (sMN 0 "uqh")
977 claim uqn (Var uqh)) unquoteNames
980 -- Save the old state - we need a fresh proof state to avoid
981 -- capturing lexically available variables in the quoted term.
985 newProof (sMN 0 "q") ctxt $
986 P Ref (reflm "TT") Erased)
988 -- Re-add the unquotes, letting Idris infer the (fictional)
989 -- types. Here, they represent the real type rather than the type
990 -- of their reflection.
991 mapM_ (\n -> do ty <- getNameFrom (sMN 0 "unqTy")
998 -- Determine whether there's an explicit goal type, and act accordingly
999 -- Establish holes for the type and value of the term to be
1001 qTy <- getNameFrom (sMN 0 "qquoteTy")
1004 qTm <- getNameFrom (sMN 0 "qquoteTm")
1007 -- Let-bind the result of elaborating the contained term, so that
1008 -- the hole doesn't disappear
1009 nTm <- getNameFrom (sMN 0 "quotedTerm")
1010 letbind nTm (Var qTy) (Var qTm)
1012 -- Fill out the goal type, if relevant
1014 Nothing -> return ()
1015 Just gTy -> do focus qTy
1016 elabE (ina { e_qq = True }) fc gTy
1018 -- Elaborate the quasiquoted term into the hole
1020 elabE (ina { e_qq = True }) fc t
1023 -- We now have an elaborated term. Reflect it and solve the
1024 -- original goal in the original proof state.
1027 let quoted = fmap (explicitNames . binderVal) $ lookup nTm env
1030 Just q -> do ctxt <- get_context
1031 (q', _, _) <- lift $ recheck ctxt [(uq, Lam Erased) | uq <- unquoteNames] (forget q) q
1033 then do try' (reflectTTQuotePattern unquoteNames q')
1034 (reflectRawQuotePattern unquoteNames (forget q'))
1036 else do try' (fill $ reflectTTQuote unquoteNames q')
1037 -- we forget q' instead of using q to ensure rechecking
1038 (fill $ reflectRawQuote unquoteNames (forget q'))
1039 True -- ignore errors like proof search does
1042 Nothing -> lift . tfail . Msg $ "Broken elaboration of quasiquote"
1044 -- Finally fill in the terms or patterns from the unquotes. This
1045 -- happens last so that their holes still exist while elaborating
1046 -- the main quotation.
1047 mapM_ elabUnquote unq
1048 where elabUnquote (n, tm)
1050 elabE (ina { e_qq = False }) fc tm
1053 elab' ina fc (PUnquote t) = fail "Found unquote outside of quasiquote"
1054 elab' ina fc (PAs _ n t) = lift . tfail . Msg $ "@-pattern not allowed here"
1055 elab' ina fc (PHidden t)
1056 | reflection = elab' ina fc t
1058 = do (h : hs) <- get_holes
1059 -- Dotting a hole means that either the hole or any outer
1060 -- hole (a hole outside any occurrence of it)
1061 -- must be solvable by unification as well as being filled
1063 -- Delay dotted things to the end, then when we elaborate them
1064 -- we can check the result against what was inferred
1066 delayElab $ do focus h
1069 elab' ina fc (PRunTactics fc' tm) =
1071 n <- getNameFrom (sMN 0 "tacticScript")
1072 n' <- getNameFrom (sMN 0 "tacticExpr")
1073 let scriptTy = RApp (Var (sNS (sUN "Tactical") ["Tactical", "Reflection", "Language"])) (Var unitTy)
1076 letbind n' scriptTy (Var n)
1078 elab' ina (Just fc') tm
1081 runTactical (maybe fc' id fc) ctxt env (P Bound n' Erased)
1083 elab' ina fc x = fail $ "Unelaboratable syntactic form " ++ showTmImpls x
1085 delayElab t = updateAux (\e -> e { delayed_elab = delayed_elab e ++ [t] })
1087 isScr :: PTerm -> (Name, Binder Term) -> (Name, (Bool, Binder Term))
1088 isScr (PRef _ n) (n', b) = (n', (n == n', b))
1089 isScr _ (n', b) = (n', (False, b))
1091 caseBlock :: FC -> Name ->
1092 [(Name, (Bool, Binder Term))] -> [(PTerm, PTerm)] -> [PClause]
1093 caseBlock fc n env opts
1094 = let args' = findScr env
1095 args = map mkarg (map getNmScr args') in
1096 map (mkClause args) opts
1098 where -- Find the variable we want as the scrutinee and mark it as
1099 -- 'True'. If the scrutinee is in the environment, match on that
1100 -- otherwise match on the new argument we're adding.
1101 findScr ((n, (True, t)) : xs)
1102 = (n, (True, t)) : scrName n xs
1103 findScr [(n, (_, t))] = [(n, (True, t))]
1104 findScr (x : xs) = x : findScr xs
1105 -- [] can't happen since scrutinee is in the environment!
1106 findScr [] = error "The impossible happened - the scrutinee was not in the environment"
1108 -- To make sure top level pattern name remains in scope, put
1109 -- it at the end of the environment
1111 scrName n [(_, t)] = [(n, t)]
1112 scrName n (x : xs) = x : scrName n xs
1114 getNmScr (n, (s, _)) = (n, s)
1116 mkarg (n, s) = (PRef fc n, s)
1117 -- may be shadowed names in the new pattern - so replace the
1118 -- old ones with an _
1119 mkClause args (l, r)
1120 = let args' = map (shadowed (allNamesIn l)) args
1121 lhs = PApp (getFC fc l) (PRef (getFC fc l) n)
1122 (map (mkLHSarg l) args') in
1123 PClause (getFC fc l) n lhs [] r []
1125 mkLHSarg l (tm, True) = pexp l
1126 mkLHSarg l (tm, False) = pexp tm
1128 shadowed new (PRef _ n, s) | n `elem` new = (Placeholder, s)
1131 getFC d (PApp fc _ _) = fc
1132 getFC d (PRef fc _) = fc
1133 getFC d (PAlternative _ (x:_)) = getFC d x
1136 insertLazy :: PTerm -> ElabD PTerm
1137 insertLazy t@(PApp _ (PRef _ (UN l)) _) | l == txt "Delay" = return t
1138 insertLazy t@(PApp _ (PRef _ (UN l)) _) | l == txt "Force" = return t
1139 insertLazy (PCoerced t) = return t
1143 let (tyh, _) = unApply (normalise (tt_ctxt ist) env ty)
1144 let tries = if pattern then [t, mkDelay env t] else [mkDelay env t, t]
1146 P _ (UN l) _ | l == txt "Lazy'"
1147 -> return (PAlternative False tries)
1150 mkDelay env (PAlternative b xs) = PAlternative b (map (mkDelay env) xs)
1152 = let fc = fileFC "Delay" in
1153 addImplBound ist (map fst env) (PApp fc (PRef fc (sUN "Delay"))
1157 -- Don't put implicit coercions around applications which are marked
1158 -- as '%noImplicit', or around case blocks, otherwise we get exponential
1159 -- blowup especially where there are errors deep in large expressions.
1160 notImplicitable (PApp _ f _) = notImplicitable f
1161 -- TMP HACK no coercing on bind (make this configurable)
1162 notImplicitable (PRef _ n)
1163 | [opts] <- lookupCtxt n (idris_flags ist)
1164 = NoImplicit `elem` opts
1165 notImplicitable (PAlternative True as) = any notImplicitable as
1166 -- case is tricky enough without implicit coercions! If they are needed,
1167 -- they can go in the branches separately.
1168 notImplicitable (PCase _ _ _) = True
1169 notImplicitable _ = False
1171 insertScopedImps fc (Bind n (Pi im@(Just i) _ _) sc) xs
1173 = pimp n (PResolveTC fc) True : insertScopedImps fc sc xs
1175 = pimp n Placeholder True : insertScopedImps fc sc xs
1176 insertScopedImps fc (Bind n (Pi _ _ _) sc) (x : xs)
1177 = x : insertScopedImps fc sc xs
1178 insertScopedImps _ _ xs = xs
1180 insertImpLam ina t =
1183 let ty' = normalise (tt_ctxt ist) env ty
1186 -- just one level at a time
1187 addLam (Bind n (Pi (Just _) _ _) sc) t =
1188 do impn <- unique_hole (sMN 0 "imp")
1189 if e_isfn ina -- apply to an implicit immediately
1190 then return (PApp emptyFC
1191 (PLam emptyFC impn Placeholder t)
1193 else return (PLam emptyFC impn Placeholder t)
1194 addLam _ t = return t
1196 insertCoerce ina t@(PCase _ _ _) = return t
1197 insertCoerce ina t | notImplicitable t = return t
1198 insertCoerce ina t =
1200 -- Check for possible coercions to get to the goal
1201 -- and add them as 'alternatives'
1203 let ty' = normalise (tt_ctxt ist) env ty
1204 let cs = getCoercionsTo ist ty'
1205 let t' = case (t, cs) of
1206 (PCoerced tm, _) -> tm
1208 (_, cs) -> PAlternative False [t ,
1209 PAlternative True (map (mkCoerce env t) cs)]
1212 mkCoerce env t n = let fc = maybe (fileFC "Coercion") id (highestFC t) in
1213 addImplBound ist (map fst env)
1214 (PApp fc (PRef fc n) [pexp (PCoerced t)])
1216 -- | Elaborate the arguments to a function
1217 elabArgs :: IState -- ^ The current Idris state
1218 -> ElabCtxt -- ^ (in an argument, guarded, in a type, in a qquote)
1220 -> FC -- ^ Source location
1222 -> Name -- ^ Name of the function being applied
1223 -> [((Name, Name), Bool)] -- ^ (Argument Name, Hole Name, unmatchable)
1224 -> Bool -- ^ under a 'force'
1225 -> [PTerm] -- ^ argument
1227 elabArgs ist ina failed fc retry f [] force _ = return ()
1228 elabArgs ist ina failed fc r f (((argName, holeName), unm):ns) force (t : args)
1229 = do hs <- get_holes
1230 if holeName `elem` hs then
1233 Placeholder -> do movelast holeName
1234 elabArgs ist ina failed fc r f ns force args
1236 else elabArgs ist ina failed fc r f ns force args
1238 do -- solveAutos ist fn False
1239 now_elaborating fc f argName
1240 wrapErr f argName $ do
1243 -- No coercing under an explicit Force (or it can Force/Delay
1245 let elab = if force then elab' else elabE
1246 failed' <- -- trace (show (n, t, hs, tm)) $
1247 -- traceWhen (not (null cs)) (show ty ++ "\n" ++ showImp True t) $
1250 -- Can't pattern match on polymorphic goals
1251 poly <- goal_polymorphic
1253 traceWhen ulog ("Elaborating argument " ++ show (argName, holeName, g)) $
1254 elab (ina { e_nomatching = unm && poly }) (Just fc) t
1256 done_elaborating_arg f argName
1257 elabArgs ist ina failed fc r f ns force args
1258 wrapErr f argName action =
1260 while <- elaborating_app
1261 let while' = map (\(x, y, z)-> (y, z)) while
1262 (result, newState) <- case runStateT action elabState of
1263 OK (res, newState) -> return (res, newState)
1264 Error e -> do done_elaborating_arg f argName
1265 lift (tfail (elaboratingArgErr while' e))
1268 elabArgs _ _ _ _ _ _ (((arg, hole), _) : _) _ [] =
1269 fail $ "Can't elaborate these args: " ++ show arg ++ " " ++ show hole
1271-- For every alternative, look at the function at the head. Automatically resolve
1272-- any nested alternatives where that function is also at the head
1274pruneAlt :: [PTerm] -> [PTerm]
1275pruneAlt xs = map prune xs
1277 prune (PApp fc1 (PRef fc2 f) as)
1278 = PApp fc1 (PRef fc2 f) (fmap (fmap (choose f)) as)
1281 choose f (PAlternative a as)
1282 = let as' = fmap (choose f) as
1283 fs = filter (headIs f) as' in
1286 _ -> PAlternative a as'
1288 choose f (PApp fc f' as) = PApp fc (choose f f') (fmap (fmap (choose f)) as)
1291 headIs f (PApp _ (PRef _ f') _) = f == f'
1292 headIs f (PApp _ f' _) = headIs f f'
1293 headIs f _ = True -- keep if it's not an application
1295-- Rule out alternatives that don't return the same type as the head of the goal
1296-- (If there are none left as a result, do nothing)
1297pruneByType :: [Name] -> Term -> -- head of the goal
1298 Context -> [PTerm] -> [PTerm]
1299-- if an alternative has a locally bound name at the head, take it
1300pruneByType env t c as
1301 | Just a <- locallyBound as = [a]
1303 locallyBound [] = Nothing
1305 | Just n <- getName t,
1306 n `elem` env = Just t
1307 | otherwise = locallyBound ts
1308 getName (PRef _ n) = Just n
1309 getName (PApp _ f _) = getName f
1310 getName (PHidden t) = getName t
1313pruneByType env (P _ n _) ctxt as
1314-- if the goal type is polymorphic, keep e
1315 | [] <- lookupTy n ctxt = as
1317 = let asV = filter (headIs True n) as
1318 as' = filter (headIs False n) as in
1325 headIs var f (PApp _ (PRef _ f') _) = typeHead var f f'
1326 headIs var f (PApp _ f' _) = headIs var f f'
1327 headIs var f (PPi _ _ _ sc) = headIs var f sc
1328 headIs var f (PHidden t) = headIs var f t
1329 headIs _ _ _ = True -- keep if it's not an application
1332 = -- trace ("Trying " ++ show f' ++ " for " ++ show n) $
1333 case lookupTy f' ctxt of
1334 [ty] -> case unApply (getRetTy ty) of
1335 (P _ ctyn _, _) | isConName ctyn ctxt -> ctyn == f
1336 _ -> let ty' = normalise ctxt [] ty in
1337 case unApply (getRetTy ty') of
1338 (P _ ftyn _, _) -> ftyn == f
1339 (V _, _) -> var -- keep, variable
1343pruneByType _ t _ as = as
1345findInstances :: IState -> Term -> [Name]
1347 | (P _ n _, _) <- unApply t
1348 = case lookupCtxt n (idris_classes ist) of
1349 [CI _ _ _ _ _ ins] -> ins
1353-- Try again to solve auto implicits
1354solveAuto :: IState -> Name -> Bool -> Name -> ElabD ()
1355solveAuto ist fn ambigok n
1356 = do hs <- get_holes
1357 when (n `elem` hs) $ do
1360 isg <- is_guess -- if it's a guess, we're working on it recursively, so stop
1362 proofSearch' ist True ambigok 100 True Nothing fn []
1364solveAutos :: IState -> Name -> Bool -> ElabD ()
1365solveAutos ist fn ambigok
1366 = do autos <- get_autos
1367 mapM_ (solveAuto ist fn ambigok) (map fst autos)
1370 = trivial (elab ist toplevel ERHS [] (sMN 0 "tac")) ist
1371proofSearch' ist rec ambigok depth prv top n hints
1373 proofSearch rec prv ambigok (not prv) depth
1374 (elab ist toplevel ERHS [] (sMN 0 "tac")) top n hints ist
1376-- Resolve type classes. This will only pick up 'normal' instances, never
1377-- named instances (hence using 'tcname' to check it's a generated instance
1379resolveTC :: Bool -> Int -> Term -> Name -> IState -> ElabD ()
1380resolveTC = resTC' []
1382resTC' tcs def 0 topg fn ist = fail $ "Can't resolve type class"
1383resTC' tcs def 1 topg fn ist = try' (trivial' ist) (resolveTC def 0 topg fn ist) True
1384resTC' tcs defaultOn depth topg fn ist
1390 traceWhen ulog ("Resolving class " ++ show g) $
1393 let (tc, ttypes) = unApply t
1394 scopeOnly <- needsDefault t tc ttypes
1395 let stk = elab_stack ist
1396 let insts_in = findInstances ist t
1397 let insts = if scopeOnly then filter chaser insts_in
1400 let depth' = if scopeOnly then 2 else depth
1401 blunderbuss t depth' stk (stk ++ insts)) True
1403 elabTC n | n /= fn && tcname n = (resolve n depth, show n)
1404 | otherwise = (fail "Can't resolve", show n)
1406 -- HACK! Rather than giving a special name, better to have some kind
1407 -- of flag in ClassInfo structure
1409 | ('@':'@':_) <- str nm = True -- old way
1410 chaser (SN (ParentN _ _)) = True
1411 chaser (NS n _) = chaser n
1414 numclass = sNS (sUN "Num") ["Classes","Prelude"]
1416 needsDefault t num@(P _ nc _) [P Bound a _] | nc == numclass && defaultOn
1418 fill (RConstant (AType (ATInt ITBig))) -- default Integer
1422 | all boundVar as = return True -- fail $ "Can't resolve " ++ show t
1423 needsDefault t f a = return False -- trace (show t) $ return ()
1425 boundVar (P Bound _ _) = True
1428 blunderbuss t d stk [] = do -- c <- get_env
1430 lift $ tfail $ CantResolve topg
1431 blunderbuss t d stk (n:ns)
1432 | n /= fn && (n `elem` stk || tcname n)
1433 = try' (resolve n d) (blunderbuss t d stk ns) True
1434 | otherwise = blunderbuss t d stk ns
1437 | depth == 0 = fail $ "Can't resolve type class"
1440 let (tc, ttypes) = unApply t
1441-- if (all boundVar ttypes) then resolveTC (depth - 1) fn insts ist
1443 -- if there's a hole in the goal, don't even try
1444 let imps = case lookupCtxtName n (idris_implicits ist) of
1446 [args] -> map isImp (snd args) -- won't be overloaded!
1447 xs -> error "The impossible happened - overloading is not expected here!"
1450 args <- map snd <$> try' (apply (Var n) imps)
1451 (match_apply (Var n) imps) True
1453 when (length ps < length ps' || unrecoverable ps') $
1454 fail "Can't apply type class"
1455-- traceWhen (all boundVar ttypes) ("Progress: " ++ show t ++ " with " ++ show n) $
1456 mapM_ (\ (_,n) -> do focus n
1458 let (tc', ttype) = unApply t'
1459 let got = fst (unApply t)
1460 let depth' = if tc' `elem` tcs
1461 then depth - 1 else depth
1462 resTC' (got : tcs) defaultOn depth' topg fn ist)
1463 (filter (\ (x, y) -> not x) (zip (map fst imps) args))
1464 -- if there's any arguments left, we've failed to resolve
1468 traceWhen ulog ("Got " ++ show n) $ return ()
1469 where isImp (PImp p _ _ _ _) = (True, p)
1470 isImp arg = (False, priority arg)
1472collectDeferred :: Maybe Name ->
1473 Term -> State [(Name, (Int, Maybe Name, Type))] Term
1474collectDeferred top (Bind n (GHole i t) app) =
1476 t' <- collectDeferred top t
1477 when (not (n `elem` map fst ds)) $ put (ds ++ [(n, (i, top, t'))])
1478 collectDeferred top app
1479collectDeferred top (Bind n b t) = do b' <- cdb b
1480 t' <- collectDeferred top t
1481 return (Bind n b' t')
1483 cdb (Let t v) = liftM2 Let (collectDeferred top t) (collectDeferred top v)
1484 cdb (Guess t v) = liftM2 Guess (collectDeferred top t) (collectDeferred top v)
1485 cdb b = do ty' <- collectDeferred top (binderTy b)
1486 return (b { binderTy = ty' })
1487collectDeferred top (App f a) = liftM2 App (collectDeferred top f) (collectDeferred top a)
1488collectDeferred top t = return t
1490case_ :: Bool -> Bool -> IState -> Name -> PTerm -> ElabD ()
1491case_ ind autoSolve ist fn tm = do
1493 tyn <- getNameFrom (sMN 0 "ity")
1495 valn <- getNameFrom (sMN 0 "ival")
1496 claim valn (Var tyn)
1497 letn <- getNameFrom (sMN 0 "irule")
1498 letbind letn (Var tyn) (Var valn)
1500 elab ist toplevel ERHS [] (sMN 0 "tac") tm
1502 let (Just binding) = lookup letn env
1503 let val = binderVal binding
1504 if ind then induction (forget val)
1505 else casetac (forget val)
1506 when autoSolve solveAll
1508runTactical :: FC -> Context -> Env -> Term -> ElabD ()
1509runTactical fc ctxt env tm = runTacTm (eval tm) >> return ()
1511 eval = normaliseAll ctxt env . finalise
1512 tacN str = sNS (sUN str) ["Tactical", "Reflection", "Language"]
1513 returnUnit = fmap fst $ get_type_val (Var unitCon)
1515 -- | Do a step in the reflected elaborator monad. The input is the
1516 -- step, the output is the (reflected) term returned.
1517 runTacTm :: Term -> ElabD Term
1518 runTacTm (unApply -> tac@(P _ n _, args))
1519 | n == tacN "prim__Solve", [] <- args
1522 | n == tacN "prim__Goal", [] <- args
1523 = do (h:_) <- get_holes
1525 fmap fst . get_type_val $
1526 rawPair (Var (reflm "TTName"), Var (reflm "TT"))
1527 (reflectName h, reflect t)
1528 | n == tacN "prim__Holes", [] <- args
1529 = do hs <- get_holes
1530 fmap fst . get_type_val $
1531 mkList (Var $ reflm "TTName") (map reflectName hs)
1532 | n == tacN "prim__Guess", [] <- args
1535 then do guess <- fmap forget get_guess
1536 fmap fst . get_type_val $
1537 RApp (RApp (Var (sNS (sUN "Just") ["Maybe", "Prelude"]))
1540 else fmap fst . get_type_val $
1541 RApp (Var (sNS (sUN "Nothing") ["Maybe", "Prelude"]))
1543 | n == tacN "prim__SourceLocation", [] <- args
1544 = fmap fst . get_type_val $
1546 | n == tacN "prim__Env", [] <- args
1548 fmap fst . get_type_val $ reflectEnv env
1549 | n == tacN "prim__Fail", [_a, errs] <- args
1550 = do parts <- reifyReportParts (eval errs)
1551 lift . tfail $ ReflectionError [parts] (Msg "")
1552 | n == tacN "prim__PureTactical", [_a, tm] <- args
1554 | n == tacN "prim__BindTactical", [_a, _b, first, andThen] <- args
1555 = do let first' = eval first
1556 res <- runTacTm first'
1557 let next = eval (App andThen res)
1559 | n == tacN "prim__Try", [_a, first, alt] <- args
1560 = do let first' = eval first
1562 try' (runTacTm first') (runTacTm alt') True
1563 | n == tacN "prim__Fill", [raw] <- args
1564 = do raw' <- reifyRaw raw
1567 | n == tacN "prim__Gensym", [eval -> Constant (Str hint)] <- args
1568 = do n <- getNameFrom (sMN 0 hint)
1569 fmap fst $ get_type_val (reflectName n)
1570 | n == tacN "prim__Claim", [n, ty] <- args
1571 = do n' <- reifyTTName n
1575 | n == tacN "prim__Forget", [tt] <- args
1576 = do tt' <- reifyTT tt
1577 fmap fst . get_type_val $ reflect tt'
1578 | n == tacN "prim__Attack", [] <- args
1581 | n == tacN "prim__Rewrite", [rule] <- args
1582 = do r <- reifyRaw rule
1585 | n == tacN "prim__Focus", [what] <- args
1586 = do n' <- reifyTTName what
1589 | n == tacN "prim__Unfocus", [what] <- args
1590 = do n' <- reifyTTName what
1593 | n == tacN "prim__Intro", [mn] <- args
1594 = do n <- case fromTTMaybe mn of
1595 Nothing -> return Nothing
1596 Just name -> fmap Just $ reifyTTName name
1599 | n == tacN "prim__Debug", [ty, msg] <- args
1600 = do let msg' = fromTTMaybe msg
1602 Nothing -> debugElaborator Nothing
1603 Just (Constant (Str m)) -> debugElaborator (Just m)
1604 Just x -> lift . tfail . InternalMsg $ "Can't reify message for debugging: " ++ show x
1605 runTacTm x = lift . tfail . InternalMsg $ "tactical is not implemented for " ++ show x
1607-- Running tactics directly
1608-- if a tactic adds unification problems, return an error
1610runTac :: Bool -> IState -> Maybe FC -> Name -> PTactic -> ElabD ()
1611runTac autoSolve ist perhapsFC fn tac
1614 let tac' = fmap (addImplBound ist (map fst env)) tac
1617 else no_errors (runT tac')
1618 (Just (CantSolveGoal g (map (\(n, b) -> (n, binderTy b)) env)))
1620 runT (Intro []) = do g <- goal
1621 attack; intro (bname g)
1623 bname (Bind n _ _) = Just n
1625 runT (Intro xs) = mapM_ (\x -> do attack; intro (Just x)) xs
1626 runT Intros = do g <- goal
1627 attack; intro (bname g)
1631 bname (Bind n _ _) = Just n
1633 runT (Exact tm) = do elab ist toplevel ERHS [] (sMN 0 "tac") tm
1634 when autoSolve solveAll
1635 runT (MatchRefine fn)
1637 case lookupCtxtName fn (idris_implicits ist) of
1638 [] -> do a <- envArgs fn
1640 ns -> return (map (\ (n, a) -> (n, map (const True) a)) ns)
1641 let tacs = map (\ (fn', imps) ->
1642 (match_apply (Var fn') (map (\x -> (x, 0)) imps),
1645 when autoSolve solveAll
1646 where envArgs n = do e <- get_env
1648 Just t -> return $ map (const False)
1649 (getArgTys (binderTy t))
1653 case lookupCtxtName fn (idris_implicits ist) of
1654 [] -> do a <- envArgs fn
1656 ns -> return (map (\ (n, a) -> (n, map isImp a)) ns)
1657 let tacs = map (\ (fn', imps) ->
1658 (apply (Var fn') (map (\x -> (x, 0)) imps),
1661 when autoSolve solveAll
1662 where isImp (PImp _ _ _ _ _) = True
1664 envArgs n = do e <- get_env
1666 Just t -> return $ map (const False)
1667 (getArgTys (binderTy t))
1669 runT (Refine fn imps) = do ns <- apply (Var fn) (map (\x -> (x,0)) imps)
1670 when autoSolve solveAll
1671 runT DoUnify = do unify_all
1672 when autoSolve solveAll
1673 runT (Claim n tm) = do tmHole <- getNameFrom (sMN 0 "newGoal")
1675 claim n (Var tmHole)
1677 elab ist toplevel ERHS [] (sMN 0 "tac") tm
1679 runT (Equiv tm) -- let bind tm, then
1681 tyn <- getNameFrom (sMN 0 "ety")
1683 valn <- getNameFrom (sMN 0 "eqval")
1684 claim valn (Var tyn)
1685 letn <- getNameFrom (sMN 0 "equiv_val")
1686 letbind letn (Var tyn) (Var valn)
1688 elab ist toplevel ERHS [] (sMN 0 "tac") tm
1690 when autoSolve solveAll
1691 runT (Rewrite tm) -- to elaborate tm, let bind it, then rewrite by that
1692 = do attack; -- (h:_) <- get_holes
1693 tyn <- getNameFrom (sMN 0 "rty")
1696 valn <- getNameFrom (sMN 0 "rval")
1697 claim valn (Var tyn)
1698 letn <- getNameFrom (sMN 0 "rewrite_rule")
1699 letbind letn (Var tyn) (Var valn)
1701 elab ist toplevel ERHS [] (sMN 0 "tac") tm
1703 when autoSolve solveAll
1704 runT (Induction tm) -- let bind tm, similar to the others
1705 = case_ True autoSolve ist fn tm
1707 = case_ False autoSolve ist fn tm
1710 tyn <- getNameFrom (sMN 0 "letty")
1712 valn <- getNameFrom (sMN 0 "letval")
1713 claim valn (Var tyn)
1714 letn <- unique_hole n
1715 letbind letn (Var tyn) (Var valn)
1717 elab ist toplevel ERHS [] (sMN 0 "tac") tm
1718 when autoSolve solveAll
1719 runT (LetTacTy n ty tm)
1721 tyn <- getNameFrom (sMN 0 "letty")
1723 valn <- getNameFrom (sMN 0 "letval")
1724 claim valn (Var tyn)
1725 letn <- unique_hole n
1726 letbind letn (Var tyn) (Var valn)
1728 elab ist toplevel ERHS [] (sMN 0 "tac") ty
1730 elab ist toplevel ERHS [] (sMN 0 "tac") tm
1731 when autoSolve solveAll
1732 runT Compute = compute
1733 runT Trivial = do trivial' ist; when autoSolve solveAll
1734 runT TCInstance = runT (Exact (PResolveTC emptyFC))
1735 runT (ProofSearch rec prover depth top hints)
1736 = do proofSearch' ist rec False depth prover top fn hints
1737 when autoSolve solveAll
1738 runT (Focus n) = focus n
1739 runT Unfocus = do hs <- get_holes
1742 (h : _) -> movelast h
1744 runT (Try l r) = do try' (runT l) (runT r) True
1745 runT (TSeq l r) = do runT l; runT r
1746 runT (ApplyTactic tm) = do tenv <- get_env -- store the environment
1747 tgoal <- goal -- store the goal
1748 attack -- let f : List (TTName, Binder TT) -> TT -> Tactic = tm in ...
1749 script <- getNameFrom (sMN 0 "script")
1750 claim script scriptTy
1751 scriptvar <- getNameFrom (sMN 0 "scriptvar" )
1752 letbind scriptvar scriptTy (Var script)
1754 elab ist toplevel ERHS [] (sMN 0 "tac") tm
1755 (script', _) <- get_type_val (Var scriptvar)
1756 -- now that we have the script apply
1757 -- it to the reflected goal and context
1758 restac <- getNameFrom (sMN 0 "restac")
1759 claim restac tacticTy
1761 fill (raw_apply (forget script')
1762 [reflectEnv tenv, reflect tgoal])
1763 restac' <- get_guess
1765 -- normalise the result in order to
1769 let tactic = normalise ctxt env restac'
1771 where tacticTy = Var (reflm "Tactic")
1772 listTy = Var (sNS (sUN "List") ["List", "Prelude"])
1773 scriptTy = (RBind (sMN 0 "__pi_arg")
1774 (Pi Nothing (RApp listTy envTupleType) RType)
1775 (RBind (sMN 1 "__pi_arg")
1776 (Pi Nothing (Var $ reflm "TT") RType) tacticTy))
1777 runT (ByReflection tm) -- run the reflection function 'tm' on the
1778 -- goal, then apply the resulting reflected Tactic
1781 script <- getNameFrom (sMN 0 "script")
1782 claim script scriptTy
1783 scriptvar <- getNameFrom (sMN 0 "scriptvar" )
1784 letbind scriptvar scriptTy (Var script)
1787 elab ist toplevel ERHS [] (sMN 0 "tac")
1788 (PApp emptyFC tm [pexp (delabTy' ist [] tgoal True True)])
1789 (script', _) <- get_type_val (Var scriptvar)
1790 -- now that we have the script apply
1791 -- it to the reflected goal
1792 restac <- getNameFrom (sMN 0 "restac")
1793 claim restac tacticTy
1795 fill (forget script')
1796 restac' <- get_guess
1798 -- normalise the result in order to
1802 let tactic = normalise ctxt env restac'
1804 where tacticTy = Var (reflm "Tactic")
1807 runT (Reflect v) = do attack -- let x = reflect v in ...
1808 tyn <- getNameFrom (sMN 0 "letty")
1810 valn <- getNameFrom (sMN 0 "letval")
1811 claim valn (Var tyn)
1812 letn <- getNameFrom (sMN 0 "letvar")
1813 letbind letn (Var tyn) (Var valn)
1815 elab ist toplevel ERHS [] (sMN 0 "tac") v
1816 (value, _) <- get_type_val (Var letn)
1819 let value' = hnf ctxt env value
1820 runTac autoSolve ist perhapsFC fn (Exact $ PQuote (reflect value'))
1821 runT (Fill v) = do attack -- let x = fill x in ...
1822 tyn <- getNameFrom (sMN 0 "letty")
1824 valn <- getNameFrom (sMN 0 "letval")
1825 claim valn (Var tyn)
1826 letn <- getNameFrom (sMN 0 "letvar")
1827 letbind letn (Var tyn) (Var valn)
1829 elab ist toplevel ERHS [] (sMN 0 "tac") v
1830 (value, _) <- get_type_val (Var letn)
1833 let value' = normalise ctxt env value
1834 rawValue <- reifyRaw value'
1835 runTac autoSolve ist perhapsFC fn (Exact $ PQuote rawValue)
1836 runT (GoalType n tac) = do g <- goal
1839 if nsroot n' == sUN n
1841 else fail "Wrong goal type"
1842 _ -> fail "Wrong goal type"
1843 runT ProofState = do g <- goal
1845 runT Skip = return ()
1846 runT (TFail err) = lift . tfail $ ReflectionError [err] (Msg "")
1849 Nothing -> lift . tfail $ Msg "There is no source location available."
1851 do fill $ reflectFC fc
1853 runT Qed = lift . tfail $ Msg "The qed command is only valid in the interactive prover"
1854 runT x = fail $ "Not implemented " ++ show x
1856 runReflected t = do t' <- reify ist t
1857 runTac autoSolve ist perhapsFC fn t'
1859-- | Prefix a name with the "Language.Reflection" namespace
1860reflm :: String -> Name
1861reflm n = sNS (sUN n) ["Reflection", "Language"]
1864-- | Reify tactics from their reflected representation
1865reify :: IState -> Term -> ElabD PTactic
1866reify _ (P _ n _) | n == reflm "Intros" = return Intros
1867reify _ (P _ n _) | n == reflm "Trivial" = return Trivial
1868reify _ (P _ n _) | n == reflm "Instance" = return TCInstance
1869reify _ (P _ n _) | n == reflm "Solve" = return Solve
1870reify _ (P _ n _) | n == reflm "Compute" = return Compute
1871reify _ (P _ n _) | n == reflm "Skip" = return Skip
1872reify _ (P _ n _) | n == reflm "SourceFC" = return SourceFC
1873reify _ (P _ n _) | n == reflm "Unfocus" = return Unfocus
1874reify ist t@(App _ _)
1875 | (P _ f _, args) <- unApply t = reifyApp ist f args
1876reify _ t = fail ("Unknown tactic " ++ show t)
1878reifyApp :: IState -> Name -> [Term] -> ElabD PTactic
1879reifyApp ist t [l, r] | t == reflm "Try" = liftM2 Try (reify ist l) (reify ist r)
1880reifyApp _ t [Constant (I i)]
1881 | t == reflm "Search" = return (ProofSearch True True i Nothing [])
1883 | t == reflm "Refine" = do n <- reifyTTName x
1884 return $ Refine n []
1885reifyApp ist t [n, ty] | t == reflm "Claim" = do n' <- reifyTTName n
1887 return $ Claim n' (delab ist goal)
1888reifyApp ist t [l, r] | t == reflm "Seq" = liftM2 TSeq (reify ist l) (reify ist r)
1889reifyApp ist t [Constant (Str n), x]
1890 | t == reflm "GoalType" = liftM (GoalType n) (reify ist x)
1891reifyApp _ t [n] | t == reflm "Intro" = liftM (Intro . (:[])) (reifyTTName n)
1892reifyApp ist t [t'] | t == reflm "Induction" = liftM (Induction . delab ist) (reifyTT t')
1893reifyApp ist t [t'] | t == reflm "Case" = liftM (Induction . delab ist) (reifyTT t')
1895 | t == reflm "ApplyTactic" = liftM (ApplyTactic . delab ist) (reifyTT t')
1897 | t == reflm "Reflect" = liftM (Reflect . delab ist) (reifyTT t')
1899 | t == reflm "ByReflection" = liftM (ByReflection . delab ist) (reifyTT t')
1901 | t == reflm "Fill" = liftM (Fill . PQuote) (reifyRaw t')
1903 | t == reflm "Exact" = liftM (Exact . delab ist) (reifyTT t')
1905 | t == reflm "Focus" = liftM Focus (reifyTTName x)
1907 | t == reflm "Rewrite" = liftM (Rewrite . delab ist) (reifyTT t')
1908reifyApp ist t [n, t']
1909 | t == reflm "LetTac" = do n' <- reifyTTName n
1911 return $ LetTac n' (delab ist t')
1912reifyApp ist t [n, tt', t']
1913 | t == reflm "LetTacTy" = do n' <- reifyTTName n
1916 return $ LetTacTy n' (delab ist tt'') (delab ist t'')
1917reifyApp ist t [errs]
1918 | t == reflm "Fail" = fmap TFail (reifyReportParts errs)
1919reifyApp _ f args = fail ("Unknown tactic " ++ show (f, args)) -- shouldn't happen
1921reifyReportParts :: Term -> ElabD [ErrorReportPart]
1922reifyReportParts errs =
1924 Nothing -> fail "Failed to reify errors"
1926 let parts = mapM reifyReportPart errs' in
1928 Left err -> fail $ "Couldn't reify \"Fail\" tactic - " ++ show err
1932-- | Reify terms from their reflected representation
1933reifyTT :: Term -> ElabD Term
1935 | (P _ f _, args) <- unApply t = reifyTTApp f args
1937 | n == reflm "Erased" = return $ Erased
1939 | n == reflm "Impossible" = return $ Impossible
1940reifyTT t = fail ("Unknown reflection term: " ++ show t)
1942reifyTTApp :: Name -> [Term] -> ElabD Term
1943reifyTTApp t [nt, n, x]
1944 | t == reflm "P" = do nt' <- reifyTTNameType nt
1947 return $ P nt' n' x'
1948reifyTTApp t [Constant (I i)]
1949 | t == reflm "V" = return $ V i
1950reifyTTApp t [n, b, x]
1951 | t == reflm "Bind" = do n' <- reifyTTName n
1952 b' <- reifyTTBinder reifyTT (reflm "TT") b
1954 return $ Bind n' b' x'
1956 | t == reflm "App" = do f' <- reifyTT f
1960 | t == reflm "TConst" = liftM Constant (reifyTTConst c)
1961reifyTTApp t [t', Constant (I i)]
1962 | t == reflm "Proj" = do t'' <- reifyTT t'
1965 | t == reflm "TType" = liftM TType (reifyTTUExp tt)
1966reifyTTApp t args = fail ("Unknown reflection term: " ++ show (t, args))
1968-- | Reify raw terms from their reflected representation
1969reifyRaw :: Term -> ElabD Raw
1971 | (P _ f _, args) <- unApply t = reifyRawApp f args
1973 | n == reflm "RType" = return $ RType
1974reifyRaw t = fail ("Unknown reflection raw term in reifyRaw: " ++ show t)
1976reifyRawApp :: Name -> [Term] -> ElabD Raw
1978 | t == reflm "Var" = liftM Var (reifyTTName n)
1979reifyRawApp t [n, b, x]
1980 | t == reflm "RBind" = do n' <- reifyTTName n
1981 b' <- reifyTTBinder reifyRaw (reflm "Raw") b
1983 return $ RBind n' b' x'
1985 | t == reflm "RApp" = liftM2 RApp (reifyRaw f) (reifyRaw x)
1987 | t == reflm "RForce" = liftM RForce (reifyRaw t')
1989 | t == reflm "RConstant" = liftM RConstant (reifyTTConst c)
1990reifyRawApp t args = fail ("Unknown reflection raw term in reifyRawApp: " ++ show (t, args))
1992reifyTTName :: Term -> ElabD Name
1994 | (P _ f _, args) <- unApply t = reifyTTNameApp f args
1995reifyTTName t = fail ("Unknown reflection term name: " ++ show t)
1997reifyTTNameApp :: Name -> [Term] -> ElabD Name
1998reifyTTNameApp t [Constant (Str n)]
1999 | t == reflm "UN" = return $ sUN n
2000reifyTTNameApp t [n, ns]
2001 | t == reflm "NS" = do n' <- reifyTTName n
2002 ns' <- reifyTTNamespace ns
2004reifyTTNameApp t [Constant (I i), Constant (Str n)]
2005 | t == reflm "MN" = return $ sMN i n
2007 | t == reflm "NErased" = return NErased
2008reifyTTNameApp t args = fail ("Unknown reflection term name: " ++ show (t, args))
2010reifyTTNamespace :: Term -> ElabD [String]
2011reifyTTNamespace t@(App _ _)
2013 (P _ f _, [Constant StrType])
2014 | f == sNS (sUN "Nil") ["List", "Prelude"] -> return []
2015 (P _ f _, [Constant StrType, Constant (Str n), ns])
2016 | f == sNS (sUN "::") ["List", "Prelude"] -> liftM (n:) (reifyTTNamespace ns)
2017 _ -> fail ("Unknown reflection namespace arg: " ++ show t)
2018reifyTTNamespace t = fail ("Unknown reflection namespace arg: " ++ show t)
2020reifyTTNameType :: Term -> ElabD NameType
2021reifyTTNameType t@(P _ n _) | n == reflm "Bound" = return $ Bound
2022reifyTTNameType t@(P _ n _) | n == reflm "Ref" = return $ Ref
2023reifyTTNameType t@(App _ _)
2025 (P _ f _, [Constant (I tag), Constant (I num)])
2026 | f == reflm "DCon" -> return $ DCon tag num False -- FIXME: Uniqueness!
2027 | f == reflm "TCon" -> return $ TCon tag num
2028 _ -> fail ("Unknown reflection name type: " ++ show t)
2029reifyTTNameType t = fail ("Unknown reflection name type: " ++ show t)
2031reifyTTBinder :: (Term -> ElabD a) -> Name -> Term -> ElabD (Binder a)
2032reifyTTBinder reificator binderType t@(App _ _)
2034 (P _ f _, bt:args) | forget bt == Var binderType
2035 -> reifyTTBinderApp reificator f args
2036 _ -> fail ("Mismatching binder reflection: " ++ show t)
2037reifyTTBinder _ _ t = fail ("Unknown reflection binder: " ++ show t)
2039reifyTTBinderApp :: (Term -> ElabD a) -> Name -> [Term] -> ElabD (Binder a)
2040reifyTTBinderApp reif f [t]
2041 | f == reflm "Lam" = liftM Lam (reif t)
2042reifyTTBinderApp reif f [t, k]
2043 | f == reflm "Pi" = liftM2 (Pi Nothing) (reif t) (reif k)
2044reifyTTBinderApp reif f [x, y]
2045 | f == reflm "Let" = liftM2 Let (reif x) (reif y)
2046reifyTTBinderApp reif f [x, y]
2047 | f == reflm "NLet" = liftM2 NLet (reif x) (reif y)
2048reifyTTBinderApp reif f [t]
2049 | f == reflm "Hole" = liftM Hole (reif t)
2050reifyTTBinderApp reif f [t]
2051 | f == reflm "GHole" = liftM (GHole 0) (reif t)
2052reifyTTBinderApp reif f [x, y]
2053 | f == reflm "Guess" = liftM2 Guess (reif x) (reif y)
2054reifyTTBinderApp reif f [t]
2055 | f == reflm "PVar" = liftM PVar (reif t)
2056reifyTTBinderApp reif f [t]
2057 | f == reflm "PVTy" = liftM PVTy (reif t)
2058reifyTTBinderApp _ f args = fail ("Unknown reflection binder: " ++ show (f, args))
2060reifyTTConst :: Term -> ElabD Const
2061reifyTTConst (P _ n _) | n == reflm "StrType" = return $ StrType
2062reifyTTConst (P _ n _) | n == reflm "PtrType" = return $ PtrType
2063reifyTTConst (P _ n _) | n == reflm "VoidType" = return $ VoidType
2064reifyTTConst (P _ n _) | n == reflm "Forgot" = return $ Forgot
2065reifyTTConst t@(App _ _)
2066 | (P _ f _, [arg]) <- unApply t = reifyTTConstApp f arg
2067reifyTTConst t = fail ("Unknown reflection constant: " ++ show t)
2069reifyTTConstApp :: Name -> Term -> ElabD Const
2070reifyTTConstApp f aty
2071 | f == reflm "AType" = fmap AType (reifyArithTy aty)
2072reifyTTConstApp f (Constant c@(I _))
2073 | f == reflm "I" = return $ c
2074reifyTTConstApp f (Constant c@(BI _))
2075 | f == reflm "BI" = return $ c
2076reifyTTConstApp f (Constant c@(Fl _))
2077 | f == reflm "Fl" = return $ c
2078reifyTTConstApp f (Constant c@(I _))
2079 | f == reflm "Ch" = return $ c
2080reifyTTConstApp f (Constant c@(Str _))
2081 | f == reflm "Str" = return $ c
2082reifyTTConstApp f (Constant c@(B8 _))
2083 | f == reflm "B8" = return $ c
2084reifyTTConstApp f (Constant c@(B16 _))
2085 | f == reflm "B16" = return $ c
2086reifyTTConstApp f (Constant c@(B32 _))
2087 | f == reflm "B32" = return $ c
2088reifyTTConstApp f (Constant c@(B64 _))
2089 | f == reflm "B64" = return $ c
2090reifyTTConstApp f arg = fail ("Unknown reflection constant: " ++ show (f, arg))
2092reifyArithTy :: Term -> ElabD ArithTy
2093reifyArithTy (App (P _ n _) intTy) | n == reflm "ATInt" = fmap ATInt (reifyIntTy intTy)
2094reifyArithTy (P _ n _) | n == reflm "ATFloat" = return ATFloat
2095reifyArithTy x = fail ("Couldn't reify reflected ArithTy: " ++ show x)
2097reifyNativeTy :: Term -> ElabD NativeTy
2098reifyNativeTy (P _ n _) | n == reflm "IT8" = return IT8
2099reifyNativeTy (P _ n _) | n == reflm "IT8" = return IT8
2100reifyNativeTy (P _ n _) | n == reflm "IT8" = return IT8
2101reifyNativeTy (P _ n _) | n == reflm "IT8" = return IT8
2102reifyNativeTy x = fail $ "Couldn't reify reflected NativeTy " ++ show x
2104reifyIntTy :: Term -> ElabD IntTy
2105reifyIntTy (App (P _ n _) nt) | n == reflm "ITFixed" = fmap ITFixed (reifyNativeTy nt)
2106reifyIntTy (P _ n _) | n == reflm "ITNative" = return ITNative
2107reifyIntTy (P _ n _) | n == reflm "ITBig" = return ITBig
2108reifyIntTy (P _ n _) | n == reflm "ITChar" = return ITChar
2109reifyIntTy (App (App (P _ n _) nt) (Constant (I i))) | n == reflm "ITVec" = fmap (flip ITVec i)
2111reifyIntTy tm = fail $ "The term " ++ show tm ++ " is not a reflected IntTy"
2113reifyTTUExp :: Term -> ElabD UExp
2114reifyTTUExp t@(App _ _)
2116 (P _ f _, [Constant (I i)]) | f == reflm "UVar" -> return $ UVar i
2117 (P _ f _, [Constant (I i)]) | f == reflm "UVal" -> return $ UVal i
2118 _ -> fail ("Unknown reflection type universe expression: " ++ show t)
2119reifyTTUExp t = fail ("Unknown reflection type universe expression: " ++ show t)
2121-- | Create a reflected call to a named function/constructor
2122reflCall :: String -> [Raw] -> Raw
2123reflCall funName args
2124 = raw_apply (Var (reflm funName)) args
2126-- | Lift a term into its Language.Reflection.TT representation
2127reflect :: Term -> Raw
2128reflect = reflectTTQuote []
2130-- | Lift a term into its Language.Reflection.Raw representation
2131reflectRaw :: Raw -> Raw
2132reflectRaw = reflectRawQuote []
2134claimTT :: Name -> ElabD Name
2135claimTT n = do n' <- getNameFrom n
2136 claim n' (Var (sNS (sUN "TT") ["Reflection", "Language"]))
2139-- | Convert a reflected term to a more suitable form for pattern-matching.
2140-- In particular, the less-interesting bits are elaborated to _ patterns. This
2141-- happens to NameTypes, universe levels, names that are bound but not used,
2142-- and the type annotation field of the P constructor.
2143reflectTTQuotePattern :: [Name] -> Term -> ElabD ()
2144reflectTTQuotePattern unq (P _ n _)
2145 | n `elem` unq = -- the unquoted names have been claimed as TT already - just use them
2146 do fill (Var n) ; solve
2148 do tyannot <- claimTT (sMN 0 "pTyAnnot")
2149 movelast tyannot -- use a _ pattern here
2150 nt <- getNameFrom (sMN 0 "nt")
2151 claim nt (Var (reflm "NameType"))
2152 movelast nt -- use a _ pattern here
2153 n' <- getNameFrom (sMN 0 "n")
2154 claim n' (Var (reflm "TTName"))
2155 fill $ reflCall "P" [Var nt, Var n', Var tyannot]
2157 focus n'; reflectNameQuotePattern n
2158reflectTTQuotePattern unq (V n)
2159 = do fill $ reflCall "V" [RConstant (I n)]
2161reflectTTQuotePattern unq (Bind n b x)
2162 = do x' <- claimTT (sMN 0 "sc")
2164 b' <- getNameFrom (sMN 0 "binder")
2165 claim b' (RApp (Var (sNS (sUN "Binder") ["Reflection", "Language"]))
2166 (Var (sNS (sUN "TT") ["Reflection", "Language"])))
2167 if n `elem` freeNames x
2168 then do fill $ reflCall "Bind"
2173 else do any <- getNameFrom (sMN 0 "anyName")
2174 claim any (Var (reflm "TTName"))
2176 fill $ reflCall "Bind"
2181 focus x'; reflectTTQuotePattern unq x
2182 focus b'; reflectBinderQuotePattern reflectTTQuotePattern unq b
2183reflectTTQuotePattern unq (App f x)
2184 = do f' <- claimTT (sMN 0 "f"); movelast f'
2185 x' <- claimTT (sMN 0 "x"); movelast x'
2186 fill $ reflCall "App" [Var f', Var x']
2188 focus f'; reflectTTQuotePattern unq f
2189 focus x'; reflectTTQuotePattern unq x
2190reflectTTQuotePattern unq (Constant c)
2191 = do fill $ reflCall "TConst" [reflectConstant c]
2193reflectTTQuotePattern unq (Proj t i)
2194 = do t' <- claimTT (sMN 0 "t"); movelast t'
2195 fill $ reflCall "Proj" [Var t', RConstant (I i)]
2197 focus t'; reflectTTQuotePattern unq t
2198reflectTTQuotePattern unq (Erased)
2199 = do erased <- claimTT (sMN 0 "erased")
2203reflectTTQuotePattern unq (Impossible)
2204 = do fill $ Var (reflm "Impossible")
2206reflectTTQuotePattern unq (TType exp)
2207 = do ue <- getNameFrom (sMN 0 "uexp")
2208 claim ue (Var (sNS (sUN "TTUExp") ["Reflection", "Language"]))
2210 fill $ reflCall "TType" [Var ue]
2212reflectTTQuotePattern unq (UType u)
2213 = do uH <- getNameFrom (sMN 0 "someUniv")
2214 claim uH (Var (reflm "Universe"))
2216 fill $ reflCall "UType" [Var uH]
2219 fill (Var (reflm (case u of
2220 NullType -> "NullType"
2221 UniqueType -> "UniqueType"
2222 AllTypes -> "AllTypes")))
2225reflectRawQuotePattern :: [Name] -> Raw -> ElabD ()
2226reflectRawQuotePattern unq (Var n)
2227 -- the unquoted names already have types, just use them
2228 | n `elem` unq = do fill (Var n); solve
2229 | otherwise = do fill (reflCall "Var" [reflectName n]); solve
2230reflectRawQuotePattern unq (RBind n b sc) =
2231 do scH <- getNameFrom (sMN 0 "sc")
2232 claim scH (Var (reflm "Raw"))
2234 bH <- getNameFrom (sMN 0 "binder")
2235 claim bH (RApp (Var (reflm "Binder"))
2236 (Var (reflm "Raw")))
2237 if n `elem` freeNamesR sc
2238 then do fill $ reflCall "RBind" [reflectName n,
2242 else do any <- getNameFrom (sMN 0 "anyName")
2243 claim any (Var (reflm "TTName"))
2245 fill $ reflCall "RBind" [Var any, Var bH, Var scH]
2247 focus scH; reflectRawQuotePattern unq sc
2248 focus bH; reflectBinderQuotePattern reflectRawQuotePattern unq b
2249 where freeNamesR (Var n) = [n]
2250 freeNamesR (RBind n (Let t v) body) = concat [freeNamesR v,
2251 freeNamesR body \\ [n],
2253 freeNamesR (RBind n b body) = freeNamesR (binderTy b) ++
2254 (freeNamesR body \\ [n])
2255 freeNamesR (RApp f x) = freeNamesR f ++ freeNamesR x
2256 freeNamesR RType = []
2257 freeNamesR (RUType _) = []
2258 freeNamesR (RForce r) = freeNamesR r
2259 freeNamesR (RConstant _) = []
2260reflectRawQuotePattern unq (RApp f x) =
2261 do fH <- getNameFrom (sMN 0 "f")
2262 claim fH (Var (reflm "Raw"))
2264 xH <- getNameFrom (sMN 0 "x")
2265 claim xH (Var (reflm "Raw"))
2267 fill $ reflCall "RApp" [Var fH, Var xH]
2269 focus fH; reflectRawQuotePattern unq f
2270 focus xH; reflectRawQuotePattern unq x
2271reflectRawQuotePattern unq RType =
2272 do fill (Var (reflm "RType"))
2274reflectRawQuotePattern unq (RUType univ) =
2275 do uH <- getNameFrom (sMN 0 "universe")
2276 claim uH (Var (reflm "Universe"))
2278 fill $ reflCall "RUType" [Var uH]
2280 focus uH; fill (reflectUniverse univ); solve
2281reflectRawQuotePattern unq (RForce r) =
2282 do rH <- getNameFrom (sMN 0 "raw")
2283 claim rH (Var (reflm "Raw"))
2285 fill $ reflCall "RForce" [Var rH]
2287 focus rH; reflectRawQuotePattern unq r
2288reflectRawQuotePattern unq (RConstant c) =
2289 do cH <- getNameFrom (sMN 0 "const")
2290 claim cH (Var (reflm "Constant"))
2292 fill (reflCall "RConstant" [Var cH]); solve
2294 fill (reflectConstant c); solve
2296reflectBinderQuotePattern :: ([Name] -> a -> ElabD ()) -> [Name] -> Binder a -> ElabD ()
2297reflectBinderQuotePattern q unq (Lam t)
2298 = do t' <- claimTT (sMN 0 "ty"); movelast t'
2299 fill $ reflCall "Lam" [Var (reflm "TT"), Var t']
2302reflectBinderQuotePattern q unq (Pi _ t k)
2303 = do t' <- claimTT (sMN 0 "ty") ; movelast t'
2304 k' <- claimTT (sMN 0 "k"); movelast k';
2305 fill $ reflCall "Pi" [Var (reflm "TT"), Var t', Var k']
2308reflectBinderQuotePattern q unq (Let x y)
2309 = do x' <- claimTT (sMN 0 "ty"); movelast x';
2310 y' <- claimTT (sMN 0 "v"); movelast y';
2311 fill $ reflCall "Let" [Var (reflm "TT"), Var x', Var y']
2315reflectBinderQuotePattern q unq (NLet x y)
2316 = do x' <- claimTT (sMN 0 "ty"); movelast x'
2317 y' <- claimTT (sMN 0 "v"); movelast y'
2318 fill $ reflCall "NLet" [Var (reflm "TT"), Var x', Var y']
2322reflectBinderQuotePattern q unq (Hole t)
2323 = do t' <- claimTT (sMN 0 "ty"); movelast t'
2324 fill $ reflCall "Hole" [Var (reflm "TT"), Var t']
2327reflectBinderQuotePattern q unq (GHole _ t)
2328 = do t' <- claimTT (sMN 0 "ty"); movelast t'
2329 fill $ reflCall "GHole" [Var (reflm "TT"), Var t']
2332reflectBinderQuotePattern q unq (Guess x y)
2333 = do x' <- claimTT (sMN 0 "ty"); movelast x'
2334 y' <- claimTT (sMN 0 "v"); movelast y'
2335 fill $ reflCall "Guess" [Var (reflm "TT"), Var x', Var y']
2339reflectBinderQuotePattern q unq (PVar t)
2340 = do t' <- claimTT (sMN 0 "ty"); movelast t'
2341 fill $ reflCall "PVar" [Var (reflm "TT"), Var t']
2344reflectBinderQuotePattern q unq (PVTy t)
2345 = do t' <- claimTT (sMN 0 "ty"); movelast t'
2346 fill $ reflCall "PVTy" [Var (reflm "TT"), Var t']
2350reflectUniverse :: Universe -> Raw
2352 (Var (reflm (case u of
2353 NullType -> "NullType"
2354 UniqueType -> "UniqueType"
2355 AllTypes -> "AllTypes")))
2357-- | Create a reflected TT term, but leave refs to the provided name intact
2358reflectTTQuote :: [Name] -> Term -> Raw
2359reflectTTQuote unq (P nt n t)
2360 | n `elem` unq = Var n
2361 | otherwise = reflCall "P" [reflectNameType nt, reflectName n, reflectTTQuote unq t]
2362reflectTTQuote unq (V n)
2363 = reflCall "V" [RConstant (I n)]
2364reflectTTQuote unq (Bind n b x)
2365 = reflCall "Bind" [reflectName n, reflectBinderQuote reflectTTQuote unq b, reflectTTQuote unq x]
2366reflectTTQuote unq (App f x)
2367 = reflCall "App" [reflectTTQuote unq f, reflectTTQuote unq x]
2368reflectTTQuote unq (Constant c)
2369 = reflCall "TConst" [reflectConstant c]
2370reflectTTQuote unq (Proj t i)
2371 = reflCall "Proj" [reflectTTQuote unq t, RConstant (I i)]
2372reflectTTQuote unq (Erased) = Var (reflm "Erased")
2373reflectTTQuote unq (Impossible) = Var (reflm "Impossible")
2374reflectTTQuote unq (TType exp) = reflCall "TType" [reflectUExp exp]
2375reflectTTQuote unq (UType u) = reflCall "UType" [reflectUniverse u]
2377reflectRawQuote :: [Name] -> Raw -> Raw
2378reflectRawQuote unq (Var n)
2379 | n `elem` unq = Var n
2380 | otherwise = reflCall "Var" [reflectName n]
2381reflectRawQuote unq (RBind n b r) =
2382 reflCall "RBind" [reflectName n, reflectBinderQuote reflectRawQuote unq b, reflectRawQuote unq r]
2383reflectRawQuote unq (RApp f x) =
2384 reflCall "RApp" [reflectRawQuote unq f, reflectRawQuote unq x]
2385reflectRawQuote unq RType = Var (reflm "RType")
2386reflectRawQuote unq (RUType u) =
2387 reflCall "RUType" [reflectUniverse u]
2388reflectRawQuote unq (RForce r) = reflCall "RForce" [reflectRawQuote unq r]
2389reflectRawQuote unq (RConstant cst) = reflCall "RConstant" [reflectConstant cst]
2391reflectNameType :: NameType -> Raw
2392reflectNameType (Bound) = Var (reflm "Bound")
2393reflectNameType (Ref) = Var (reflm "Ref")
2394reflectNameType (DCon x y _)
2395 = reflCall "DCon" [RConstant (I x), RConstant (I y)] -- FIXME: Uniqueness!
2396reflectNameType (TCon x y)
2397 = reflCall "TCon" [RConstant (I x), RConstant (I y)]
2399reflectName :: Name -> Raw
2401 = reflCall "UN" [RConstant (Str (str s))]
2402reflectName (NS n ns)
2403 = reflCall "NS" [ reflectName n
2405 raw_apply ( Var $ sNS (sUN "::") ["List", "Prelude"] )
2406 [ RConstant StrType, RConstant (Str n), s ])
2407 ( raw_apply ( Var $ sNS (sUN "Nil") ["List", "Prelude"] )
2408 [ RConstant StrType ])
2412 = reflCall "MN" [RConstant (I i), RConstant (Str (str n))]
2413reflectName (NErased) = Var (reflm "NErased")
2414reflectName n = Var (reflm "NErased") -- special name, not yet implemented
2416-- | Elaborate a name to a pattern. This means that NS and UN will be intact.
2417-- MNs corresponding to will care about the string but not the number. All
2419reflectNameQuotePattern :: Name -> ElabD ()
2420reflectNameQuotePattern n@(UN s)
2421 = do fill $ reflectName n
2423reflectNameQuotePattern n@(NS _ _)
2424 = do fill $ reflectName n
2426reflectNameQuotePattern (MN _ n)
2427 = do i <- getNameFrom (sMN 0 "mnCounter")
2428 claim i (RConstant (AType (ATInt ITNative)))
2430 fill $ reflCall "MN" [Var i, RConstant (Str $ T.unpack n)]
2432reflectNameQuotePattern _ -- for all other names, match any
2433 = do nameHole <- getNameFrom (sMN 0 "name")
2434 claim nameHole (Var (reflm "TTName"))
2439reflectBinder :: Binder Term -> Raw
2440reflectBinder = reflectBinderQuote reflectTTQuote []
2442reflectBinderQuote :: ([Name] -> a -> Raw) -> [Name] -> Binder a -> Raw
2443reflectBinderQuote q unq (Lam t)
2444 = reflCall "Lam" [Var (reflm "TT"), q unq t]
2445reflectBinderQuote q unq (Pi _ t k)
2446 = reflCall "Pi" [Var (reflm "TT"), q unq t, q unq k]
2447reflectBinderQuote q unq (Let x y)
2448 = reflCall "Let" [Var (reflm "TT"), q unq x, q unq y]
2449reflectBinderQuote q unq (NLet x y)
2450 = reflCall "NLet" [Var (reflm "TT"), q unq x, q unq y]
2451reflectBinderQuote q unq (Hole t)
2452 = reflCall "Hole" [Var (reflm "TT"), q unq t]
2453reflectBinderQuote q unq (GHole _ t)
2454 = reflCall "GHole" [Var (reflm "TT"), q unq t]
2455reflectBinderQuote q unq (Guess x y)
2456 = reflCall "Guess" [Var (reflm "TT"), q unq x, q unq y]
2457reflectBinderQuote q unq (PVar t)
2458 = reflCall "PVar" [Var (reflm "TT"), q unq t]
2459reflectBinderQuote q unq (PVTy t)
2460 = reflCall "PVTy" [Var (reflm "TT"), q unq t]
2462mkList :: Raw -> [Raw] -> Raw
2463mkList ty [] = RApp (Var (sNS (sUN "Nil") ["List", "Prelude"])) ty
2464mkList ty (x:xs) = RApp (RApp (RApp (Var (sNS (sUN "::") ["List", "Prelude"])) ty)
2468reflectConstant :: Const -> Raw
2469reflectConstant c@(I _) = reflCall "I" [RConstant c]
2470reflectConstant c@(BI _) = reflCall "BI" [RConstant c]
2471reflectConstant c@(Fl _) = reflCall "Fl" [RConstant c]
2472reflectConstant c@(Ch _) = reflCall "Ch" [RConstant c]
2473reflectConstant c@(Str _) = reflCall "Str" [RConstant c]
2474reflectConstant c@(B8 _) = reflCall "B8" [RConstant c]
2475reflectConstant c@(B16 _) = reflCall "B16" [RConstant c]
2476reflectConstant c@(B32 _) = reflCall "B32" [RConstant c]
2477reflectConstant c@(B64 _) = reflCall "B64" [RConstant c]
2478reflectConstant (B8V ws) = reflCall "B8V" [mkList (Var (sUN "Bits8")) . map (RConstant . B8) . V.toList $ ws]
2479reflectConstant (B16V ws) = reflCall "B8V" [mkList (Var (sUN "Bits16")) . map (RConstant . B16) . V.toList $ ws]
2480reflectConstant (B32V ws) = reflCall "B8V" [mkList (Var (sUN "Bits32")) . map (RConstant . B32) . V.toList $ ws]
2481reflectConstant (B64V ws) = reflCall "B8V" [mkList (Var (sUN "Bits64")) . map (RConstant . B64) . V.toList $ ws]
2482reflectConstant (AType (ATInt ITNative)) = reflCall "AType" [reflCall "ATInt" [Var (reflm "ITNative")]]
2483reflectConstant (AType (ATInt ITBig)) = reflCall "AType" [reflCall "ATInt" [Var (reflm "ITBig")]]
2484reflectConstant (AType ATFloat) = reflCall "AType" [Var (reflm "ATFloat")]
2485reflectConstant (AType (ATInt ITChar)) = reflCall "AType" [reflCall "ATInt" [Var (reflm "ITChar")]]
2486reflectConstant StrType = Var (reflm "StrType")
2487reflectConstant (AType (ATInt (ITFixed IT8))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITFixed" [Var (reflm "IT8")]]]
2488reflectConstant (AType (ATInt (ITFixed IT16))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITFixed" [Var (reflm "IT16")]]]
2489reflectConstant (AType (ATInt (ITFixed IT32))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITFixed" [Var (reflm "IT32")]]]
2490reflectConstant (AType (ATInt (ITFixed IT64))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITFixed" [Var (reflm "IT64")]]]
2491reflectConstant (AType (ATInt (ITVec IT8 c))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITVec" [Var (reflm "IT8"), RConstant (I c)]]]
2492reflectConstant (AType (ATInt (ITVec IT16 c))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITVec" [Var (reflm "IT16"), RConstant (I c)]]]
2493reflectConstant (AType (ATInt (ITVec IT32 c))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITVec" [Var (reflm "IT32"), RConstant (I c)]]]
2494reflectConstant (AType (ATInt (ITVec IT64 c))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITVec" [Var (reflm "IT64"), RConstant (I c)]]]
2495reflectConstant PtrType = Var (reflm "PtrType")
2496reflectConstant ManagedPtrType = Var (reflm "ManagedPtrType")
2497reflectConstant BufferType = Var (reflm "BufferType")
2498reflectConstant VoidType = Var (reflm "VoidType")
2499reflectConstant Forgot = Var (reflm "Forgot")
2500reflectConstant WorldType = Var (reflm "WorldType")
2501reflectConstant TheWorld = Var (reflm "TheWorld")
2503reflectUExp :: UExp -> Raw
2504reflectUExp (UVar i) = reflCall "UVar" [RConstant (I i)]
2505reflectUExp (UVal i) = reflCall "UVal" [RConstant (I i)]
2507-- | Reflect the environment of a proof into a List (TTName, Binder TT)
2508reflectEnv :: Env -> Raw
2509reflectEnv = foldr consToEnvList emptyEnvList
2511 consToEnvList :: (Name, Binder Term) -> Raw -> Raw
2512 consToEnvList (n, b) l
2513 = raw_apply (Var (sNS (sUN "::") ["List", "Prelude"]))
2515 , raw_apply (Var pairCon) [ (Var $ reflm "TTName")
2516 , (RApp (Var $ reflm "Binder")
2525 emptyEnvList = raw_apply (Var (sNS (sUN "Nil") ["List", "Prelude"]))
2528-- | Reflect an error into the internal datatype of Idris -- TODO
2529rawBool :: Bool -> Raw
2530rawBool True = Var (sNS (sUN "True") ["Bool", "Prelude"])
2531rawBool False = Var (sNS (sUN "False") ["Bool", "Prelude"])
2534rawNil ty = raw_apply (Var (sNS (sUN "Nil") ["List", "Prelude"])) [ty]
2536rawCons :: Raw -> Raw -> Raw -> Raw
2537rawCons ty hd tl = raw_apply (Var (sNS (sUN "::") ["List", "Prelude"])) [ty, hd, tl]
2539rawList :: Raw -> [Raw] -> Raw
2540rawList ty = foldr (rawCons ty) (rawNil ty)
2542rawPairTy :: Raw -> Raw -> Raw
2543rawPairTy t1 t2 = raw_apply (Var pairTy) [t1, t2]
2545rawPair :: (Raw, Raw) -> (Raw, Raw) -> Raw
2546rawPair (a, b) (x, y) = raw_apply (Var pairCon) [a, b, x, y]
2548reflectCtxt :: [(Name, Type)] -> Raw
2549reflectCtxt ctxt = rawList (rawPairTy (Var $ reflm "TTName") (Var $ reflm "TT"))
2550 (map (\ (n, t) -> (rawPair (Var $ reflm "TTName", Var $ reflm "TT")
2551 (reflectName n, reflect t)))
2554reflectErr :: Err -> Raw
2555reflectErr (Msg msg) = raw_apply (Var $ reflErrName "Msg") [RConstant (Str msg)]
2556reflectErr (InternalMsg msg) = raw_apply (Var $ reflErrName "InternalMsg") [RConstant (Str msg)]
2557reflectErr (CantUnify b (t1,_) (t2,_) e ctxt i) =
2558 raw_apply (Var $ reflErrName "CantUnify")
2565reflectErr (InfiniteUnify n tm ctxt) =
2566 raw_apply (Var $ reflErrName "InfiniteUnify")
2571reflectErr (CantConvert t t' ctxt) =
2572 raw_apply (Var $ reflErrName "CantConvert")
2577reflectErr (CantSolveGoal t ctxt) =
2578 raw_apply (Var $ reflErrName "CantSolveGoal")
2582reflectErr (UnifyScope n n' t ctxt) =
2583 raw_apply (Var $ reflErrName "UnifyScope")
2589reflectErr (CantInferType str) =
2590 raw_apply (Var $ reflErrName "CantInferType") [RConstant (Str str)]
2591reflectErr (NonFunctionType t t') =
2592 raw_apply (Var $ reflErrName "NonFunctionType") [reflect t, reflect t']
2593reflectErr (NotEquality t t') =
2594 raw_apply (Var $ reflErrName "NotEquality") [reflect t, reflect t']
2595reflectErr (TooManyArguments n) = raw_apply (Var $ reflErrName "TooManyArguments") [reflectName n]
2596reflectErr (CantIntroduce t) = raw_apply (Var $ reflErrName "CantIntroduce") [reflect t]
2597reflectErr (NoSuchVariable n) = raw_apply (Var $ reflErrName "NoSuchVariable") [reflectName n]
2598reflectErr (WithFnType t) = raw_apply (Var $ reflErrName "WithFnType") [reflect t]
2599reflectErr (CantMatch t) = raw_apply (Var $ reflErrName "CantMatch") [reflect t]
2600reflectErr (NoTypeDecl n) = raw_apply (Var $ reflErrName "NoTypeDecl") [reflectName n]
2601reflectErr (NotInjective t1 t2 t3) =
2602 raw_apply (Var $ reflErrName "NotInjective")
2607reflectErr (CantResolve t) = raw_apply (Var $ reflErrName "CantResolve") [reflect t]
2608reflectErr (CantResolveAlts ss) =
2609 raw_apply (Var $ reflErrName "CantResolveAlts")
2610 [rawList (Var $ reflm "TTName") (map reflectName ss)]
2611reflectErr (IncompleteTerm t) = raw_apply (Var $ reflErrName "IncompleteTerm") [reflect t]
2612reflectErr UniverseError = Var $ reflErrName "UniverseError"
2613reflectErr ProgramLineComment = Var $ reflErrName "ProgramLineComment"
2614reflectErr (Inaccessible n) = raw_apply (Var $ reflErrName "Inaccessible") [reflectName n]
2615reflectErr (NonCollapsiblePostulate n) = raw_apply (Var $ reflErrName "NonCollabsiblePostulate") [reflectName n]
2616reflectErr (AlreadyDefined n) = raw_apply (Var $ reflErrName "AlreadyDefined") [reflectName n]
2617reflectErr (ProofSearchFail e) = raw_apply (Var $ reflErrName "ProofSearchFail") [reflectErr e]
2618reflectErr (NoRewriting tm) = raw_apply (Var $ reflErrName "NoRewriting") [reflect tm]
2619reflectErr (ProviderError str) =
2620 raw_apply (Var $ reflErrName "ProviderError") [RConstant (Str str)]
2621reflectErr (LoadingFailed str err) =
2622 raw_apply (Var $ reflErrName "LoadingFailed") [RConstant (Str str)]
2623reflectErr x = raw_apply (Var (sNS (sUN "Msg") ["Errors", "Reflection", "Language"])) [RConstant . Str $ "Default reflection: " ++ show x]
2625-- | Reflect a file context
2626reflectFC :: FC -> Raw
2627reflectFC fc = raw_apply (Var (reflm "FileLoc"))
2628 [ RConstant (Str (fc_fname fc))
2629 , raw_apply (Var pairCon) $
2635 , raw_apply (Var pairCon) $
2642 where intTy = RConstant (AType (ATInt ITNative))
2644elaboratingArgErr :: [(Name, Name)] -> Err -> Err
2645elaboratingArgErr [] err = err
2646elaboratingArgErr ((f,x):during) err = fromMaybe err (rewrite err)
2647 where rewrite (ElaboratingArg _ _ _ _) = Nothing
2648 rewrite (ProofSearchFail e) = fmap ProofSearchFail (rewrite e)
2649 rewrite (At fc e) = fmap (At fc) (rewrite e)
2650 rewrite err = Just (ElaboratingArg f x during err)
2653withErrorReflection :: Idris a -> Idris a
2654withErrorReflection x = idrisCatch x (\ e -> handle e >>= ierror)
2655 where handle :: Err -> Idris Err
2656 handle e@(ReflectionError _ _) = do logLvl 3 "Skipping reflection of error reflection result"
2657 return e -- Don't do meta-reflection of errors
2658 handle e@(ReflectionFailed _ _) = do logLvl 3 "Skipping reflection of reflection failure"
2660 -- At and Elaborating are just plumbing - error reflection shouldn't rewrite them
2661 handle e@(At fc err) = do logLvl 3 "Reflecting body of At"
2664 handle e@(Elaborating what n err) = do logLvl 3 "Reflecting body of Elaborating"
2666 return (Elaborating what n err')
2667 handle e@(ElaboratingArg f a prev err) = do logLvl 3 "Reflecting body of ElaboratingArg"
2668 hs <- getFnHandlers f a
2671 else applyHandlers err hs
2672 return (ElaboratingArg f a prev err')
2673 -- ProofSearchFail is an internal detail - so don't expose it
2674 handle (ProofSearchFail e) = handle e
2675 -- TODO: argument-specific error handlers go here for ElaboratingArg
2676 handle e = do ist <- getIState
2677 logLvl 2 "Starting error reflection"
2678 let handlers = idris_errorhandlers ist
2679 applyHandlers e handlers
2680 getFnHandlers :: Name -> Name -> Idris [Name]
2681 getFnHandlers f arg = do ist <- getIState
2682 let funHandlers = maybe M.empty id .
2684 idris_function_errorhandlers $ ist
2685 return . maybe [] S.toList . M.lookup arg $ funHandlers
2688 applyHandlers e handlers =
2690 let err = fmap (errReverse ist) e
2691 logLvl 3 $ "Using reflection handlers " ++
2692 concat (intersperse ", " (map show handlers))
2693 let reports = map (\n -> RApp (Var n) (reflectErr err)) handlers
2695 -- Typecheck error handlers - if this fails, then something else was wrong earlier!
2696 handlers <- case mapM (check (tt_ctxt ist) []) reports of
2697 Error e -> ierror $ ReflectionFailed "Type error while constructing reflected error" e
2700 -- Normalize error handler terms to produce the new messages
2702 let results = map (normalise ctxt []) (map fst handlers)
2703 logLvl 3 $ "New error message info: " ++ concat (intersperse " and " (map show results))
2705 -- For each handler term output, either discard it if it is Nothing or reify it the Haskell equivalent
2706 let errorpartsTT = mapMaybe unList (mapMaybe fromTTMaybe results)
2707 errorparts <- case mapM (mapM reifyReportPart) errorpartsTT of
2708 Left err -> ierror err
2709 Right ok -> return ok
2710 return $ case errorparts of
2712 parts -> ReflectionError errorparts e
2714fromTTMaybe :: Term -> Maybe Term -- WARNING: Assumes the term has type Maybe a
2715fromTTMaybe (App (App (P (DCon _ _ _) (NS (UN just) _) _) ty) tm)
2716 | just == txt "Just" = Just tm
2717fromTTMaybe x = Nothing
2719reflErrName :: String -> Name
2720reflErrName n = sNS (sUN n) ["Errors", "Reflection", "Language"]
2722-- | Attempt to reify a report part from TT to the internal
2723-- representation. Not in Idris or ElabD monads because it should be usable
2725reifyReportPart :: Term -> Either Err ErrorReportPart
2726reifyReportPart (App (P (DCon _ _ _) n _) (Constant (Str msg))) | n == reflm "TextPart" =
2727 Right (TextPart msg)
2728reifyReportPart (App (P (DCon _ _ _) n _) ttn)
2729 | n == reflm "NamePart" =
2730 case runElab initEState (reifyTTName ttn) (initElaborator NErased initContext Erased) of
2731 Error e -> Left . InternalMsg $
2732 "could not reify name term " ++
2734 " when reflecting an error:" ++ show e
2735 OK (n', _)-> Right $ NamePart n'
2736reifyReportPart (App (P (DCon _ _ _) n _) tm)
2737 | n == reflm "TermPart" =
2738 case runElab initEState (reifyTT tm) (initElaborator NErased initContext Erased) of
2739 Error e -> Left . InternalMsg $
2740 "could not reify reflected term " ++
2742 " when reflecting an error:" ++ show e
2743 OK (tm', _) -> Right $ TermPart tm'
2744reifyReportPart (App (P (DCon _ _ _) n _) tm)
2745 | n == reflm "SubReport" =
2747 Just xs -> do subParts <- mapM reifyReportPart xs
2748 Right (SubReport subParts)
2749 Nothing -> Left . InternalMsg $ "could not reify subreport " ++ show tm
2750reifyReportPart x = Left . InternalMsg $ "could not reify " ++ show x
2754 = raw_apply (Var pairTy) [ (Var $ reflm "TTName")
2755 , (RApp (Var $ reflm "Binder") (Var $ reflm "TT"))
2758solveAll = 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