on master help sign in
Handle impossible cases on defineFunction

Previously, impossible cases were not treated properly when defining functions through reflection. Now they are checked for impossibility.

commit3edbd8ee5db3b2a606eed0bd9bbfea136958be01 authorDavid Raymond Christiansen <david@davidchristiansen.dk> dateWed 2 Dec 2015, 20:28 (11 years ago) parent1527899
3 files changed+49−3
src/Idris/Elab/Term.hs+23−3 test/meta004/expected+3 test/meta004/meta004.idr+23
src/Idris/Elab/Term.hs+23−3
@@ -1782,6 +1782,25 @@ runElabAction ist fc env tm ns = do tm' <- eval tm
17821782 pullVars :: (Term, Term) -> ([(Name, Term)], Term, Term)
17831783 pullVars (lhs, rhs) = (fst (patvars [] lhs), snd (patvars [] lhs), snd (patvars [] rhs)) -- TODO alpha-convert rhs
17841784
1785+ requireError :: Err -> ElabD a -> ElabD ()
1786+ requireError orErr elab =
1787+ do state <- get
1788+ case runStateT elab state of
1789+ OK (_, state') -> lift (tfail orErr)
1790+ Error e -> return ()
1791+
1792+ -- create a fake TT term for the LHS of an impossible case
1793+ fakeTT :: Raw -> Term
1794+ fakeTT (Var n) =
1795+ case lookupNameDef n (tt_ctxt ist) of
1796+ [(n', TyDecl nt _)] -> P nt n' Erased
1797+ _ -> P Ref n Erased
1798+ fakeTT (RBind n b body) = Bind n (fmap fakeTT b) (fakeTT body)
1799+ fakeTT (RApp f a) = App Complete (fakeTT f) (fakeTT a)
1800+ fakeTT RType = TType (UVar (-1))
1801+ fakeTT (RUType u) = UType u
1802+ fakeTT (RConstant c) = Constant c
1803+
17851804 defineFunction :: RFunDefn Raw -> ElabD ()
17861805 defineFunction (RDefineFun n clauses) =
17871806 do ctxt <- get_context
@@ -1794,10 +1813,11 @@ runElabAction ist fc env tm ns = do tm' <- eval tm
17941813 lift $ converts ctxt [] lty rty
17951814 return $ Right (lhs', rhs')
17961815 RMkImpossibleClause lhs ->
1797− do lhs' <- fmap fst . lift $ check ctxt [] lhs
1798− return $ Left lhs')
1816+ do requireError (Msg "Not an impossible case") . lift $
1817+ check ctxt [] lhs
1818+ return $ Left (fakeTT lhs))
17991819 let clauses'' = map (\case Right c -> pullVars c
1800− Left lhs -> let (ns, lhs') = patvars [] lhs'
1820+ Left lhs -> let (ns, lhs') = patvars [] lhs
18011821 in (ns, lhs', Impossible))
18021822 clauses'
18031823 let clauses''' = map (\(ns, lhs, rhs) -> (map fst ns, lhs, rhs)) clauses''
test/meta004/expected+3
@@ -0,0 +1,3 @@
1+meta004.idr:48:1-9:
2+While running an elaboration script, the following error occurred:
3+Not an impossible case
test/meta004/meta004.idr+23
@@ -1,3 +1,4 @@
1+import Data.Fin
12import Language.Reflection.Utils
23import Pruviloj.Core
34
@@ -23,3 +24,25 @@ total
2324p : (a : Nat) -> (b : Nat) -> plus a b = plus' a b
2425p Z right = Refl
2526p (S left) right = Refl
27+
28+
29+-- Test handling of impossible clauses in function definitions
30+foo : Fin Z -> Nat
31+bar : Nat -> Fin Z
32+
33+doit : Elab ()
34+doit = defineFunction $
35+ DefineFun `{foo} [MkImpossibleClause
36+ (RBind `{{n}}
37+ (PVar (Var `{Nat}))
38+ (RApp (Var `{foo})
39+ (RApp (Var `{FZ}) (Var `{{n}}))))]
40+
41+domore : Elab ()
42+domore = defineFunction $
43+ DefineFun `{foo} [MkImpossibleClause $
44+ RBind `{{k}} (PVar `(Nat)) $
45+ RApp (Var `{bar}) (Var `{{k}})]
46+
47+%runElab doit
48+%runElab domore