on master help sign in
Merge pull request #2275 from david-christiansen/wip/tactical

Further Elab reflection updates

commit1d8723b72c701f560a80721504808a691ec52abb authorDavid Christiansen <david@davidchristiansen.dk> dateSat 16 May 2015, 22:22 (11 years ago) parentcf9251191649d4
9 files changed+326−182
libs/prelude/Language/Reflection/Elab.idr+246−129 src/Idris/AbsSyntax.hs+19−10 src/Idris/AbsSyntaxTree.hs+3−2 src/Idris/Docs.hs+2−2 src/Idris/Elab/Class.hs+2−2 src/Idris/Elab/Instance.hs+5−5 src/Idris/Elab/Term.hs+42−25 src/Idris/IBC.hs+6−6 src/Idris/TypeSearch.hs+1−1
libs/prelude/Language/Reflection/Elab.idr+246−129
@@ -1,3 +1,8 @@
1+||| Primitives and tactics for elaborator reflection.
2+|||
3+||| Elaborator reflection allows Idris code to control Idris's
4+||| built-in elaborator, and re-use features like the unifier, the
5+||| type checker, and the hole mechanism.
16module Language.Reflection.Elab
27
38import Builtins
@@ -8,31 +13,62 @@ import Prelude.Maybe
813import Prelude.Monad
914import Language.Reflection
1015
16+||| Arguments, with plicity.
1117data Arg : Type where
18+ ||| An explicit argument
1219 Explicit : TTName -> Raw -> Arg
20+
21+ ||| An implicit argument, to be solved by unification
1322 Implicit : TTName -> Raw -> Arg
23+
24+ ||| A type-class constraint argument, to be solved by type class
25+ ||| resolution
1426 Constraint : TTName -> Raw -> Arg
1527
28+||| A type declaration
1629data TyDecl : Type where
17− Declare : TTName -> List Arg -> Raw -> TyDecl
18−
30+ ||| A type declaration.
31+ |||
32+ ||| Each argument is in the scope of the names of previous
33+ ||| arguments, and the return type is in the scope of all the
34+ ||| argument names.
35+ |||
36+ ||| @ fn the name to be declared, fully-qualified
37+ ||| @ args the arguments to the function
38+ ||| @ ret the final return type
39+ Declare : (fn : TTName) -> (args : List Arg) -> (ret : Raw) -> TyDecl
40+
41+||| A single pattern-matching clause
1942data FunClause : Type where
2043 MkFunClause : (lhs, rhs : Raw) -> FunClause
2144 MkImpossibleClause : (lhs : Raw) -> FunClause
2245
46+||| A reflected function definition.
2347data FunDefn : Type where
2448 DefineFun : TTName -> List FunClause -> FunDefn
2549
50+||| An argument to a type constructor.
2651data TyConArg : Type where
52+ ||| Parameters are consistent across all constructors of the type
2753 Parameter : TTName -> Raw -> TyConArg
54+
55+ ||| Indices are allowed to vary across constructors
2856 Index : TTName -> Raw -> TyConArg
2957
58+||| A reflected datatype definition
3059data Datatype : Type where
60+ ||| A reflected datatype definition
61+ |||
62+ ||| @ familyName the name of the type constructor
63+ ||| @ tyConArgs the arguments to the type constructor
64+ ||| @ tyConRes the result of the type constructor
65+ ||| @ constrs the constructors, with their types
3166 MkDatatype : (familyName : TTName) ->
3267 (tyConArgs : List TyConArg) -> (tyConRes : Raw) ->
3368 (constrs : List (TTName, Raw)) ->
3469 Datatype
3570
71+||| A reflected elaboration script.
3672abstract
3773data Elab : Type -> Type where
3874 -- obligatory control stuff
@@ -74,7 +110,9 @@ data Elab : Type -> Type where
74110
75111 prim__DeclareType : TyDecl -> Elab ()
76112 prim__DefineFunction : FunDefn -> Elab ()
113+ prim__AddInstance : TTName -> TTName -> Elab ()
77114
115+ prim__ResolveTC : TTName -> Elab ()
78116 prim__RecursiveElab : Raw -> Elab () -> Elab (TT, TT)
79117
80118 prim__Debug : {a : Type} -> Maybe String -> Elab a
@@ -84,131 +122,210 @@ data Elab : Type -> Type where
84122-- Public API
85123-------------
86124%access public
125+namespace Tactics
126+ instance Functor Elab where
127+ map f t = prim__BindElab t (\x => prim__PureElab (f x))
128+
129+ instance Applicative Elab where
130+ pure x = prim__PureElab x
131+ f <*> x = prim__BindElab f $ \g =>
132+ prim__BindElab x $ \y =>
133+ prim__PureElab $ g y
134+
135+ ||| The Alternative instance on Elab represents left-biased error
136+ ||| handling. In other words, `t <|> t'` will run `t`, and if it
137+ ||| fails, roll back the elaboration state and run `t'`.
138+ instance Alternative Elab where
139+ empty = prim__Fail [TextPart "empty"]
140+ x <|> y = prim__Try x y
141+
142+ instance Monad Elab where
143+ x >>= f = prim__BindElab x f
144+
145+ ||| Halt elaboration with an error
146+ fail : List ErrorReportPart -> Elab a
147+ fail err = prim__Fail err
148+
149+ ||| Look up the lexical binding at the focused hole
150+ getEnv : Elab (List (TTName, Binder TT))
151+ getEnv = prim__Env
152+
153+ ||| Get the name and type of the focused hole
154+ getGoal : Elab (TTName, TT)
155+ getGoal = prim__Goal
156+
157+ ||| Get the hole queue, in order
158+ getHoles : Elab (List TTName)
159+ getHoles = prim__Holes
160+
161+ ||| If the current hole contains a guess, return it
162+ getGuess : Elab (Maybe TT)
163+ getGuess = prim__Guess
164+
165+ ||| Look up the types of every overloading of a name
166+ lookupTy : TTName -> Elab (List (TTName, NameType, TT))
167+ lookupTy n = prim__LookupTy n
168+
169+ ||| Get the type of a fully-qualified name
170+ lookupTyExact : TTName -> Elab (TTName, NameType, TT)
171+ lookupTyExact n = case !(lookupTy n) of
172+ [res] => return res
173+ [] => fail [NamePart n, TextPart "is not defined."]
174+ xs => fail [NamePart n, TextPart "is ambiguous."]
175+
176+ ||| Find the reflected representation of all datatypes whose names
177+ ||| are overloadings of some name
178+ lookupDatatype : TTName -> Elab (List Datatype)
179+ lookupDatatype n = prim__LookupDatatype n
180+
181+ ||| Find the reflected representation of a datatype, given its
182+ ||| fully-qualified name.
183+ lookupDatatypeExact : TTName -> Elab Datatype
184+ lookupDatatypeExact n = case !(lookupDatatype n) of
185+ [res] => return res
186+ [] => fail [TextPart "No datatype named", NamePart n]
187+ xs => fail [TextPart "More than one datatype named", NamePart n]
188+
189+ ||| Convert a type-annotated reflected term to its untyped
190+ ||| equivalent
191+ forgetTypes : TT -> Elab Raw
192+ forgetTypes tt = prim__Forget tt
193+
194+ ||| Generate a unique name based on some hint.
195+ |||
196+ ||| **NB**: the generated name is unique _for this run of the
197+ ||| elaborator_. Do not assume that they are globally unique.
198+ gensym : (hint : String) -> Elab TTName
199+ gensym hint = prim__Gensym hint
200+
201+ ||| Substitute a guess into a hole.
202+ solve : Elab ()
203+ solve = prim__Solve
204+
205+ ||| Place a term into a hole, unifying its type
206+ fill : Raw -> Elab ()
207+ fill tm = prim__Fill tm
208+
209+ ||| Fill with unification
210+ apply : Raw -> Elab ()
211+ apply tm = prim__Apply tm
212+
213+ ||| Move the focus to the specified hole
214+ |||
215+ ||| @ hole the hole to focus on
216+ focus : (hole : TTName) -> Elab ()
217+ focus hole = prim__Focus hole
218+
219+ ||| Send the currently-focused hole to the end of the hole queue and
220+ ||| focus on the next hole.
221+ unfocus : TTName -> Elab ()
222+ unfocus hole = prim__Unfocus hole
223+
224+ ||| Convert a hole to make it suitable for bindings.
225+ |||
226+ ||| The binding tactics require that a hole be directly under its
227+ ||| binding, or else the scopes of the generated terms won't make
228+ ||| sense. This tactic creates a new hole of the proper form, and
229+ ||| points the old hole at it.
230+ attack : Elab ()
231+ attack = prim__Attack
232+
233+ ||| Introduce a new hole with a specified name and type.
234+ |||
235+ ||| The new hole will be focused, and the previously-focused hole
236+ ||| will be immediately after it in the hole queue.
237+ claim : TTName -> Raw -> Elab ()
238+ claim n ty = prim__Claim n ty
239+
240+ ||| Introduce a lambda binding around the current hole and focus on
241+ ||| the body. Requires that the hole be in binding form (use
242+ ||| `attack`).
243+ |||
244+ ||| @ n the name to use for the argument, or `Nothing` to use the name
245+ ||| in the corresponding hole type (a dependent function)
246+ intro : (n : Maybe TTName) -> Elab ()
247+ intro n = prim__Intro n
248+
249+ ||| Introduce a dependent function type binding into the current hole,
250+ ||| and focus on the body.
251+ forall : TTName -> Raw -> Elab ()
252+ forall n ty = prim__Forall n ty
253+
254+ ||| Convert a hole into a pattern variable.
255+ patvar : TTName -> Elab ()
256+ patvar n = prim__PatVar n
257+
258+ ||| Introduce a new pattern binding.
259+ patbind : TTName -> Elab ()
260+ patbind n = prim__PatBind n
261+
262+ ||| Normalise the goal.
263+ compute : Elab ()
264+ compute = prim__Compute
265+
266+ ||| Find the source context for the elaboration script
267+ getSourceLocation : Elab SourceLocation
268+ getSourceLocation = prim__SourceLocation
269+
270+ ||| Attempt to solve the current goal with the source code location
271+ sourceLocation : Elab ()
272+ sourceLocation = do loc <- getSourceLocation
273+ fill (quote loc)
274+ solve
275+
276+ ||| Attempt to rewrite the goal using an equality.
277+ |||
278+ ||| The tactic searches the goal for applicable subterms, and
279+ ||| constructs a context for `replace` using them. In some cases,
280+ ||| this is not possible, and `replace` must be called manually with
281+ ||| an appropriate context.
282+ rewriteWith : Raw -> Elab ()
283+ rewriteWith rule = prim__Rewrite rule
284+
285+ ||| Add a type declaration to the global context.
286+ declareType : TyDecl -> Elab ()
287+ declareType decl = prim__DeclareType decl
288+
289+ ||| Define a function in the global context. The function must have
290+ ||| already been declared, either in ordinary Idris code or using
291+ ||| `declareType`.
292+ defineFunction : FunDefn -> Elab ()
293+ defineFunction defun = prim__DefineFunction defun
294+
295+ ||| Register a new instance for type class resolution
296+ |||
297+ ||| @ className the name of the class for which an instance is being registered
298+ ||| @ instName the name of the definition to use in instance search
299+ addInstance : (className, instName : TTName) -> Elab ()
300+ addInstance className instName = prim__AddInstance className instName
301+
302+ ||| Attempt to solve the current goal with a type class dictionary
303+ |||
304+ ||| @ fn the name of the definition being elaborated (to prevent Idris
305+ ||| from looping)
306+ resolveTC : (fn : TTName) -> Elab ()
307+ resolveTC fn = prim__ResolveTC fn
308+
309+ ||| Halt elaboration, dumping the internal state for inspection.
310+ |||
311+ ||| This is intended for elaboration script developers, not for
312+ ||| end-users. Use `fail` for final scripts.
313+ debug : Elab a
314+ debug = prim__Debug Nothing
315+
316+ ||| Halt elaboration, dumping the internal state and displaying a
317+ ||| message.
318+ |||
319+ ||| This is intended for elaboration script developers, not for
320+ ||| end-users. Use `fail` for final scripts.
321+ |||
322+ ||| @ msg the message to display
323+ debugMessage : (msg : String) -> Elab a
324+ debugMessage msg = prim__Debug (Just msg)
325+
326+ ||| Recursively invoke the reflected elaborator with some goal.
327+ |||
328+ ||| The result is the final term and its type.
329+ runElab : Raw -> Elab () -> Elab (TT, TT)
330+ runElab goal script = prim__RecursiveElab goal script
87331
88−instance Functor Elab where
89− map f t = prim__BindElab t (\x => prim__PureElab (f x))
90−
91−instance Applicative Elab where
92− pure x = prim__PureElab x
93− f <*> x = prim__BindElab f $ \g =>
94− prim__BindElab x $ \y =>
95− prim__PureElab $ g y
96−
97−instance Alternative Elab where
98− empty = prim__Fail [TextPart "empty"]
99− x <|> y = prim__Try x y
100−
101−instance Monad Elab where
102− x >>= f = prim__BindElab x f
103−
104−fail : List ErrorReportPart -> Elab a
105−fail err = prim__Fail err
106−
107−getEnv : Elab (List (TTName, Binder TT))
108−getEnv = prim__Env
109−
110−getGoal : Elab (TTName, TT)
111−getGoal = prim__Goal
112−
113−getHoles : Elab (List TTName)
114−getHoles = prim__Holes
115−
116−getGuess : Elab (Maybe TT)
117−getGuess = prim__Guess
118−
119−lookupTy : TTName -> Elab (List (TTName, NameType, TT))
120−lookupTy n = prim__LookupTy n
121−
122−lookupTyExact : TTName -> Elab (TTName, NameType, TT)
123−lookupTyExact n = case !(lookupTy n) of
124− [res] => return res
125− [] => fail [NamePart n, TextPart "is not defined."]
126− xs => fail [NamePart n, TextPart "is ambiguous."]
127−
128−lookupDatatype : TTName -> Elab (List Datatype)
129−lookupDatatype n = prim__LookupDatatype n
130−
131−lookupDatatypeExact : TTName -> Elab Datatype
132−lookupDatatypeExact n = case !(lookupDatatype n) of
133− [res] => return res
134− [] => fail [TextPart "No datatype named", NamePart n]
135− xs => fail [TextPart "More than one datatype named", NamePart n]
136−
137−forgetTypes : TT -> Elab Raw
138−forgetTypes tt = prim__Forget tt
139−
140−gensym : (hint : String) -> Elab TTName
141−gensym hint = prim__Gensym hint
142−
143−solve : Elab ()
144−solve = prim__Solve
145−
146−fill : Raw -> Elab ()
147−fill tm = prim__Fill tm
148−
149−||| Fill with unification
150−apply : Raw -> Elab ()
151−apply tm = prim__Apply tm
152−
153−focus : (hole : TTName) -> Elab ()
154−focus hole = prim__Focus hole
155−
156−unfocus : TTName -> Elab ()
157−unfocus hole = prim__Unfocus hole
158−
159−attack : Elab ()
160−attack = prim__Attack
161−
162−claim : TTName -> Raw -> Elab ()
163−claim n ty = prim__Claim n ty
164−
165−||| Introduce a lambda binding around the current hole and focus on
166−||| the body. Requires that the hole be in binding form (use
167−||| `attack`).
168−|||
169−||| @ n the name to use for the argument, or `Nothing` to use the name
170−||| in the corresponding hole type (a dependent function)
171−intro : (n : Maybe TTName) -> Elab ()
172−intro n = prim__Intro n
173−
174−||| Introduce a dependent function type binding into the current hole,
175−||| and focus on the body.
176−forall : TTName -> Raw -> Elab ()
177−forall n ty = prim__Forall n ty
178−
179−patvar : TTName -> Elab ()
180−patvar n = prim__PatVar n
181−
182−patbind : TTName -> Elab ()
183−patbind n = prim__PatBind n
184−
185−compute : Elab ()
186−compute = prim__Compute
187−
188−||| Find out the present source context for the tactic script
189−getSourceLocation : Elab SourceLocation
190−getSourceLocation = prim__SourceLocation
191−
192−||| Attempt to solve the current goal with the source code location
193−sourceLocation : Elab ()
194−sourceLocation = do loc <- getSourceLocation
195− fill (quote loc)
196− solve
197−
198−rewriteWith : Raw -> Elab ()
199−rewriteWith rule = prim__Rewrite rule
200−
201−declareType : TyDecl -> Elab ()
202−declareType decl = prim__DeclareType decl
203−
204−defineFunction : FunDefn -> Elab ()
205−defineFunction defun = prim__DefineFunction defun
206−
207−debug : Elab a
208−debug = prim__Debug Nothing
209−
210−runElab : Raw -> Elab () -> Elab (TT, TT)
211−runElab goal script = prim__RecursiveElab goal script
212−
213−debugMessage : String -> Elab a
214−debugMessage msg = prim__Debug (Just msg)
src/Idris/AbsSyntax.hs+19−10
@@ -353,24 +353,33 @@ pop_estack = do i <- getIState
353353 where ptail [] = []
354354 ptail (x : xs) = xs
355355
356−-- Add a class instance function. Dodgy hack: Put integer instances first in the
357−-- list so they are resolved by default.
356+-- | Add a class instance function.
357+--
358+-- Precondition: the instance should have the correct type.
359+--
360+-- Dodgy hack 1: Put integer instances first in the list so they are
361+-- resolved by default.
362+--
358363-- Dodgy hack 2: put constraint chasers (@@) last
359−
360−addInstance :: Bool -> Name -> Name -> Idris ()
361−addInstance int n i
364+addInstance :: Bool -- ^ whether the name is an Integer instance
365+ -> Bool -- ^ whether to include the instance in instance search
366+ -> Name -- ^ the name of the class
367+ -> Name -- ^ the name of the instance
368+ -> Idris ()
369+addInstance int res n i
362370 = do ist <- getIState
363371 case lookupCtxt n (idris_classes ist) of
364372 [CI a b c d e ins fds] ->
365373 do let cs = addDef n (CI a b c d e (addI i ins) fds) (idris_classes ist)
366374 putIState $ ist { idris_classes = cs }
367− _ -> do let cs = addDef n (CI (sMN 0 "none") [] [] [] [] [i] []) (idris_classes ist)
375+ _ -> do let cs = addDef n (CI (sMN 0 "none") [] [] [] [] [(i, res)] []) (idris_classes ist)
368376 putIState $ ist { idris_classes = cs }
369− where addI i ins | int = i : ins
370− | chaser n = ins ++ [i]
377+ where addI, insI :: Name -> [(Name, Bool)] -> [(Name, Bool)]
378+ addI i ins | int = (i, res) : ins
379+ | chaser n = ins ++ [(i, res)]
371380 | otherwise = insI i ins
372− insI i [] = [i]
373− insI i (n : ns) | chaser n = i : n : ns
381+ insI i [] = [(i, res)]
382+ insI i (n : ns) | chaser (fst n) = (i, res) : n : ns
374383 | otherwise = n : insI i ns
375384
376385 chaser (UN nm)
src/Idris/AbsSyntaxTree.hs+3−2
@@ -274,7 +274,7 @@ data IBCWrite = IBCFix FixDecl
274274 | IBCImp Name
275275 | IBCStatic Name
276276 | IBCClass Name
277− | IBCInstance Bool Name Name
277+ | IBCInstance Bool Bool Name Name
278278 | IBCDSL Name
279279 | IBCData Name
280280 | IBCOpt Name
@@ -672,6 +672,7 @@ data Directive = DLib Codegen String |
672672-- after a term elaboration when there's been reflected elaboration.
673673data RDeclInstructions = RTyDeclInstrs Name FC [PArg] Type
674674 | RClausesInstrs Name [([Name], Term, Term)]
675+ | RAddInstance Name Name
675676
676677-- | For elaborator state
677678data EState = EState {
@@ -1083,7 +1084,7 @@ data ClassInfo = CI { instanceCtorName :: Name,
10831084 class_defaults :: [(Name, (Name, PDecl))], -- method name -> default impl
10841085 class_default_superclasses :: [PDecl],
10851086 class_params :: [Name],
1086− class_instances :: [Name],
1087+ class_instances :: [(Name, Bool)], -- the Bool is whether to include in instance search, so named instances are excluded
10871088 class_determiners :: [Int] }
10881089 deriving Show
10891090{-!
src/Idris/Docs.hs+2−2
@@ -232,7 +232,7 @@ getDocs n w
232232 classNameForInst ist n =
233233 listToMaybe [ cn
234234 | (cn, ci) <- toAlist (idris_classes ist)
235− , n `elem` class_instances ci
235+ , n `elem` map fst (class_instances ci)
236236 ]
237237
238238docData :: Name -> TypeInfo -> Idris Docs
@@ -254,7 +254,7 @@ docClass n ci
254254 instances = map (\inst -> (namedInst inst,
255255 delabTy i inst,
256256 docsForInstance inst))
257− (nub (class_instances ci))
257+ (nub (map fst (class_instances ci)))
258258 (subclasses, instances') = partition (isSubclass . (\(_,tm,_) -> tm)) instances
259259 superclasses = catMaybes $ map getDInst (class_default_superclasses ci)
260260 mdocs <- mapM (docFun . fst) (class_methods ci)
src/Idris/Elab/Class.hs+2−2
@@ -209,8 +209,8 @@ elabClass info syn_in doc fc constraints tn tnfc ps pDocs fds ds mcn cd
209209 let conn' = case lookupCtxtName conn (idris_classes i) of
210210 [(n, _)] -> n
211211 _ -> conn
212− addInstance False conn' cfn
213− addIBC (IBCInstance False conn' cfn)
212+ addInstance False True conn' cfn
213+ addIBC (IBCInstance False True conn' cfn)
214214-- iputStrLn ("Added " ++ show (conn, cfn, ty))
215215 return [PTy emptyDocstring [] syn fc [] cfn NoFC ty,
216216 PClauses fc [Dictionary] cfn [PClause fc cfn lhs [] rhs []]]
src/Idris/Elab/Instance.hs+5−5
@@ -77,9 +77,9 @@ elabInstance info syn doc argDocs what fc cs n nfc ps t expn ds = do
7777 -- and it's not a named instance, then it's overlapping, so report an error
7878 case expn of
7979 Nothing -> do mapM_ (maybe (return ()) overlapping . findOverlapping i (class_determiners ci) (delab i nty))
80− (class_instances ci)
81− addInstance intInst n iname
82− Just _ -> addInstance intInst n iname
80+ (map fst $ class_instances ci)
81+ addInstance intInst True n iname
82+ Just _ -> addInstance intInst False n iname
8383 when (what /= ETypes && (not (null ds && not emptyclass))) $ do
8484 let ips = zip (class_params ci) ps
8585 let ns = case n of
@@ -143,7 +143,7 @@ elabInstance info syn doc argDocs what fc cs n nfc ps t expn ds = do
143143 mapM_ (rec_elabDecl info EAll info) idecls
144144 ist <- getIState
145145 checkInjectiveArgs fc n (class_determiners ci) (lookupTyExact iname (tt_ctxt ist))
146− addIBC (IBCInstance intInst n iname)
146+ addIBC (IBCInstance intInst (isNothing expn) n iname)
147147
148148 where
149149 intInst = case ps of
@@ -186,7 +186,7 @@ elabInstance info syn doc argDocs what fc cs n nfc ps t expn ds = do
186186 ctxt <- getContext
187187 (cty, _) <- recheckC fc id [] tyT
188188 let nty = normalise ctxt [] cty
189− return $ any (isJust . findOverlapping i (class_determiners ci) (delab i nty)) (class_instances ci)
189+ return $ any (isJust . findOverlapping i (class_determiners ci) (delab i nty)) (map fst $ class_instances ci)
190190
191191 findOverlapping i dets t n
192192 | take 2 (show n) == "@@" = Nothing
src/Idris/Elab/Term.hs+42−25
@@ -15,6 +15,7 @@ import Idris.Core.Elaborate hiding (Tactic(..))
1515import Idris.Core.TT
1616import Idris.Core.Evaluate
1717import Idris.Core.Unify
18+import Idris.Core.ProofTerm (getProofTerm)
1819import Idris.Core.Typecheck (check, recheck, isType)
1920import Idris.Coverage (buildSCG, checkDeclTotality, genClauses, recoverableCoverage, validCoverageCase)
2021import Idris.ErrReverse (errReverse)
@@ -1156,7 +1157,7 @@ elab ist info emode opts fn tm
11561157 focus n
11571158 elab' ina (Just fc') tm
11581159 env <- get_env
1159− runTactical (maybe fc' id fc) env (P Bound n' Erased)
1160+ runTactical ist (maybe fc' id fc) env (P Bound n' Erased)
11601161 solve
11611162 elab' ina fc x = fail $ "Unelaboratable syntactic form " ++ showTmImpls x
11621163
@@ -1431,12 +1432,14 @@ findHighlight n = do ctxt <- get_context
14311432 Nothing -> lift . tfail . InternalMsg $
14321433 "Can't find name" ++ show n
14331434
1434−
1435+-- | Find the names of instances that have been designeated for
1436+-- searching (i.e. non-named instances or instances from Elab scripts)
14351437findInstances :: IState -> Term -> [Name]
14361438findInstances ist t
14371439 | (P _ n _, _) <- unApply (getRetTy t)
14381440 = case lookupCtxt n (idris_classes ist) of
1439− [CI _ _ _ _ _ ins _] -> filter accessible ins
1441+ [CI _ _ _ _ _ ins _] ->
1442+ [n | (n, True) <- ins, accessible n]
14401443 _ -> []
14411444 | otherwise = []
14421445 where accessible n = case lookupDefAccExact n False (tt_ctxt ist) of
@@ -1466,15 +1469,14 @@ proofSearch' ist rec ambigok depth prv top n hints
14661469 proofSearch rec prv ambigok (not prv) depth
14671470 (elab ist toplevel ERHS [] (sMN 0 "tac")) top n hints ist
14681471
1469−-- Resolve type classes. This will only pick up 'normal' instances, never
1470−-- named instances (hence using 'tcname' to check it's a generated instance
1471−-- name).
1472−resolveTC :: Bool -- using default Int
1473− -> Bool -- allow metavariables in the goal
1474− -> Int -- depth
1475− -> Term -- top level goal
1476− -> Name -- top level function name
1477− -> IState -> ElabD ()
1472+-- | Resolve type classes. This will only pick up 'normal' instances, never
1473+-- named instances (which is enforced by 'findInstances').
1474+resolveTC :: Bool -- ^ using default Int
1475+ -> Bool -- ^ allow metavariables in the goal
1476+ -> Int -- ^ depth
1477+ -> Term -- ^ top level goal, for error messages
1478+ -> Name -- ^ top level function name, to prevent loops
1479+ -> IState -> ElabD ()
14781480resolveTC def mvok depth top fn ist
14791481 = do hs <- get_holes
14801482 resTC' [] def hs depth top fn ist
@@ -1527,9 +1529,6 @@ resTC' tcs defaultOn topholes depth topg fn ist
15271529 | Constant _ <- c = not (n `elem` hs)
15281530 notHole _ _ = True
15291531
1530− elabTC n | n /= fn && tcname n = (resolve n depth, show n)
1531− | otherwise = (fail "Can't resolve", show n)
1532−
15331532 -- HACK! Rather than giving a special name, better to have some kind
15341533 -- of flag in ClassInfo structure
15351534 chaser (UN nm)
@@ -1555,11 +1554,11 @@ resTC' tcs defaultOn topholes depth topg fn ist
15551554 -- ps <- get_probs
15561555 lift $ tfail $ CantResolve False topg
15571556 blunderbuss t d stk (n:ns)
1558− | n /= fn && (n `elem` stk || tcname n)
1559− = tryCatch (resolve n d)
1557+ | n /= fn -- && (n `elem` stk)
1558+ = tryCatch (resolve n d)
15601559 (\e -> case e of
15611560 CantResolve True _ -> lift $ tfail e
1562− _ -> blunderbuss t d stk ns)
1561+ _ -> blunderbuss t d stk ns)
15631562 | otherwise = blunderbuss t d stk ns
15641563
15651564 introImps = do g <- goal
@@ -1673,16 +1672,16 @@ case_ ind autoSolve ist fn tm = do
16731672 when autoSolve solveAll
16741673
16751674
1676−runTactical :: FC -> Env -> Term -> ElabD ()
1677−runTactical fc env tm = do tm' <- eval tm
1678− runTacTm tm'
1679− return ()
1675+runTactical :: IState -> FC -> Env -> Term -> ElabD ()
1676+runTactical ist fc env tm = do tm' <- eval tm
1677+ runTacTm tm'
1678+ return ()
16801679 where
16811680 eval tm = do ctxt <- get_context
16821681 env <- get_env
16831682 return $ normaliseAll ctxt env (finalise tm)
16841683
1685− returnUnit = fmap fst $ get_type_val (Var unitCon)
1684+ returnUnit = return $ P (DCon 0 0 False) unitCon (P (TCon 0 0) unitTy Erased)
16861685
16871686 patvars :: [Name] -> Term -> ([Name], Term)
16881687 patvars ns (Bind n (PVar t) sc) = patvars (n : ns) (instantiate (P Bound n t) sc)
@@ -1888,6 +1887,17 @@ runTactical fc env tm = do tm' <- eval tm
18881887 = do defn <- reifyFunDefn decl
18891888 defineFunction defn
18901889 returnUnit
1890+ | n == tacN "prim__AddInstance", [cls, inst] <- args
1891+ = do className <- reifyTTName cls
1892+ instName <- reifyTTName inst
1893+ updateAux $ \e -> e { new_tyDecls = RAddInstance className instName :
1894+ new_tyDecls e}
1895+ returnUnit
1896+ | n == tacN "prim__ResolveTC", [fn] <- args
1897+ = do g <- goal
1898+ fn <- reifyTTName fn
1899+ resolveTC False True 100 g fn ist
1900+ returnUnit
18911901 | n == tacN "prim__RecursiveElab", [goal, script] <- args
18921902 = do goal' <- reifyRaw goal
18931903 ctxt <- get_context
@@ -1898,9 +1908,10 @@ runTactical fc env tm = do tm' <- eval tm
18981908 aux <- getAux
18991909 datatypes <- get_datatypes
19001910 env <- get_env
1901− (tm_out, ES (_, aux') _ _) <-
1902− lift $ runElab aux (runTactical fc env script >> solve >> get_term)
1911+ (_, ES (p, aux') _ _) <-
1912+ lift $ runElab aux (runTactical ist fc [] script)
19031913 (newProof recH ctxt datatypes goalTT)
1914+ let tm_out = getProofTerm (pterm p)
19041915 updateAux $ const aux'
19051916 env' <- get_env
19061917 (tm, ty, _) <- lift $ recheck ctxt env (forget tm_out) tm_out
@@ -2266,6 +2277,12 @@ processTacticDecls info steps =
22662277 let ds' = map (\(n, (i, top, t)) -> (n, (i, top, t, True))) ds
22672278 in addDeferred ds'
22682279 _ -> return ()
2280+ RAddInstance className instName ->
2281+ do -- The type class resolution machinery relies on a special
2282+ logLvl 2 $ "Adding elab script instance " ++ show instName ++
2283+ " for " ++ show className
2284+ addInstance False True className instName
2285+ addIBC (IBCInstance False True className instName)
22692286 RClausesInstrs n cs ->
22702287 do logLvl 3 $ "Pattern-matching definition from tactics: " ++ show n
22712288 solveDeferred n
src/Idris/IBC.hs+6−6
@@ -41,7 +41,7 @@ import Codec.Archive.Zip
4141import Util.Zlib (decompressEither)
4242
4343ibcVersion :: Word16
44−ibcVersion = 108
44+ibcVersion = 109
4545
4646data IBCFile = IBCFile { ver :: Word16,
4747 sourcefile :: FilePath,
@@ -52,7 +52,7 @@ data IBCFile = IBCFile { ver :: Word16,
5252 ibc_fixes :: ![FixDecl],
5353 ibc_statics :: ![(Name, [Bool])],
5454 ibc_classes :: ![(Name, ClassInfo)],
55− ibc_instances :: ![(Bool, Name, Name)],
55+ ibc_instances :: ![(Bool, Bool, Name, Name)],
5656 ibc_dsls :: ![(Name, DSL)],
5757 ibc_datatypes :: ![(Name, TypeInfo)],
5858 ibc_optimise :: ![(Name, OptInfo)],
@@ -229,8 +229,8 @@ ibc i (IBCClass n) f
229229 = case lookupCtxtExact n (idris_classes i) of
230230 Just v -> return f { ibc_classes = (n,v): ibc_classes f }
231231 _ -> ifail "IBC write failed"
232−ibc i (IBCInstance int n ins) f
233− = return f { ibc_instances = (int,n,ins): ibc_instances f }
232+ibc i (IBCInstance int res n ins) f
233+ = return f { ibc_instances = (int, res, n, ins) : ibc_instances f }
234234ibc i (IBCDSL n) f
235235 = case lookupCtxtExact n (idris_dsls i) of
236236 Just v -> return f { ibc_dsls = (n,v): ibc_dsls f }
@@ -439,8 +439,8 @@ pClasses cs = mapM_ (\ (n, c) ->
439439 = addDef n c' (idris_classes i) }))
440440 cs
441441
442−pInstances :: [(Bool, Name, Name)] -> Idris ()
443−pInstances cs = mapM_ (\ (i, n, ins) -> addInstance i n ins) cs
442+pInstances :: [(Bool, Bool, Name, Name)] -> Idris ()
443+pInstances cs = mapM_ (\ (i, res, n, ins) -> addInstance i res n ins) cs
444444
445445pDSLs :: [(Name, DSL)] -> Idris ()
446446pDSLs cs = mapM_ (\ (n, c) -> updateIState (\i ->
src/Idris/TypeSearch.hs+1−1
@@ -439,7 +439,7 @@ matchTypesBulk istate maxScore type1 types = getAllResults startQueueOfQueues wh
439439 className <- getClassName clss
440440 classDef <- lookupCtxt className classInfo
441441 n <- class_instances classDef
442− def <- lookupCtxt n (definitions ctxt)
442+ def <- lookupCtxt (fst n) (definitions ctxt)
443443 nty <- normaliseC ctxt [] <$> (case typeFromDef def of Just x -> [x]; Nothing -> [])
444444 let ty' = vToP (uniqueBinders usedns nty)
445445 return ty'