on master help sign in
Merge pull request #2275 from david-christiansen/wip/tactical
1d8723bDavid Christiansen
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.
1module Language.Reflection.Elab
6module Language.Reflection.Elab
2
7
3import Builtins
8import Builtins
@@ -8,31 +13,62 @@ import Prelude.Maybe
8import Prelude.Monad
13import Prelude.Monad
9import Language.Reflection
14import Language.Reflection
10
15
16+||| Arguments, with plicity.
11data Arg : Type where
17data Arg : Type where
18+ ||| An explicit argument
12 Explicit : TTName -> Raw -> Arg
19 Explicit : TTName -> Raw -> Arg
20+
21+ ||| An implicit argument, to be solved by unification
13 Implicit : TTName -> Raw -> Arg
22 Implicit : TTName -> Raw -> Arg
23+
24+ ||| A type-class constraint argument, to be solved by type class
25+ ||| resolution
14 Constraint : TTName -> Raw -> Arg
26 Constraint : TTName -> Raw -> Arg
15
27
28+||| A type declaration
16data TyDecl : Type where
29data TyDecl : Type where
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
17− Declare : TTName -> List Arg -> Raw -> TyDecl
39+ Declare : (fn : TTName) -> (args : List Arg) -> (ret : Raw) -> TyDecl
18−
40+
41+||| A single pattern-matching clause
19data FunClause : Type where
42data FunClause : Type where
20 MkFunClause : (lhs, rhs : Raw) -> FunClause
43 MkFunClause : (lhs, rhs : Raw) -> FunClause
21 MkImpossibleClause : (lhs : Raw) -> FunClause
44 MkImpossibleClause : (lhs : Raw) -> FunClause
22
45
46+||| A reflected function definition.
23data FunDefn : Type where
47data FunDefn : Type where
24 DefineFun : TTName -> List FunClause -> FunDefn
48 DefineFun : TTName -> List FunClause -> FunDefn
25
49
50+||| An argument to a type constructor.
26data TyConArg : Type where
51data TyConArg : Type where
52+ ||| Parameters are consistent across all constructors of the type
27 Parameter : TTName -> Raw -> TyConArg
53 Parameter : TTName -> Raw -> TyConArg
54+
55+ ||| Indices are allowed to vary across constructors
28 Index : TTName -> Raw -> TyConArg
56 Index : TTName -> Raw -> TyConArg
29
57
58+||| A reflected datatype definition
30data Datatype : Type where
59data 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
31 MkDatatype : (familyName : TTName) ->
66 MkDatatype : (familyName : TTName) ->
32 (tyConArgs : List TyConArg) -> (tyConRes : Raw) ->
67 (tyConArgs : List TyConArg) -> (tyConRes : Raw) ->
33 (constrs : List (TTName, Raw)) ->
68 (constrs : List (TTName, Raw)) ->
34 Datatype
69 Datatype
35
70
71+||| A reflected elaboration script.
36abstract
72abstract
37data Elab : Type -> Type where
73data Elab : Type -> Type where
38 -- obligatory control stuff
74 -- obligatory control stuff
@@ -74,7 +110,9 @@ data Elab : Type -> Type where
74
110
75 prim__DeclareType : TyDecl -> Elab ()
111 prim__DeclareType : TyDecl -> Elab ()
76 prim__DefineFunction : FunDefn -> Elab ()
112 prim__DefineFunction : FunDefn -> Elab ()
113+ prim__AddInstance : TTName -> TTName -> Elab ()
77
114
115+ prim__ResolveTC : TTName -> Elab ()
78 prim__RecursiveElab : Raw -> Elab () -> Elab (TT, TT)
116 prim__RecursiveElab : Raw -> Elab () -> Elab (TT, TT)
79
117
80 prim__Debug : {a : Type} -> Maybe String -> Elab a
118 prim__Debug : {a : Type} -> Maybe String -> Elab a
@@ -84,131 +122,210 @@ data Elab : Type -> Type where
84-- Public API
122-- Public API
85-------------
123-------------
86%access public
124%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
87
331
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
353 where ptail [] = []
353 where ptail [] = []
354 ptail (x : xs) = xs
354 ptail (x : xs) = xs
355
355
356+-- | Add a class instance function.
357+--
358+-- Precondition: the instance should have the correct type.
359+--
356−-- Add a class instance function. Dodgy hack: Put integer instances first in the
360+-- Dodgy hack 1: Put integer instances first in the list so they are
357−-- list so they are resolved by default.
361+-- resolved by default.
362+--
358-- Dodgy hack 2: put constraint chasers (@@) last
363-- Dodgy hack 2: put constraint chasers (@@) last
359−
364+addInstance :: Bool -- ^ whether the name is an Integer instance
360−addInstance :: Bool -> Name -> Name -> Idris ()
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 ()
361−addInstance int n i
369+addInstance int res n i
362 = do ist <- getIState
370 = do ist <- getIState
363 case lookupCtxt n (idris_classes ist) of
371 case lookupCtxt n (idris_classes ist) of
364 [CI a b c d e ins fds] ->
372 [CI a b c d e ins fds] ->
365 do let cs = addDef n (CI a b c d e (addI i ins) fds) (idris_classes ist)
373 do let cs = addDef n (CI a b c d e (addI i ins) fds) (idris_classes ist)
366 putIState $ ist { idris_classes = cs }
374 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)
368 putIState $ ist { idris_classes = cs }
376 putIState $ ist { idris_classes = cs }
377+ where addI, insI :: Name -> [(Name, Bool)] -> [(Name, Bool)]
369− where addI i ins | int = i : ins
378+ addI i ins | int = (i, res) : ins
370− | chaser n = ins ++ [i]
379+ | chaser n = ins ++ [(i, res)]
371 | otherwise = insI i ins
380 | otherwise = insI i ins
372− insI i [] = [i]
381+ insI i [] = [(i, res)]
373− insI i (n : ns) | chaser n = i : n : ns
382+ insI i (n : ns) | chaser (fst n) = (i, res) : n : ns
374 | otherwise = n : insI i ns
383 | otherwise = n : insI i ns
375
384
376 chaser (UN nm)
385 chaser (UN nm)
src/Idris/AbsSyntaxTree.hs+3−2
@@ -274,7 +274,7 @@ data IBCWrite = IBCFix FixDecl
274 | IBCImp Name
274 | IBCImp Name
275 | IBCStatic Name
275 | IBCStatic Name
276 | IBCClass Name
276 | IBCClass Name
277− | IBCInstance Bool Name Name
277+ | IBCInstance Bool Bool Name Name
278 | IBCDSL Name
278 | IBCDSL Name
279 | IBCData Name
279 | IBCData Name
280 | IBCOpt Name
280 | IBCOpt Name
@@ -672,6 +672,7 @@ data Directive = DLib Codegen String |
672-- after a term elaboration when there's been reflected elaboration.
672-- after a term elaboration when there's been reflected elaboration.
673data RDeclInstructions = RTyDeclInstrs Name FC [PArg] Type
673data RDeclInstructions = RTyDeclInstrs Name FC [PArg] Type
674 | RClausesInstrs Name [([Name], Term, Term)]
674 | RClausesInstrs Name [([Name], Term, Term)]
675+ | RAddInstance Name Name
675
676
676-- | For elaborator state
677-- | For elaborator state
677data EState = EState {
678data EState = EState {
@@ -1083,7 +1084,7 @@ data ClassInfo = CI { instanceCtorName :: Name,
1083 class_defaults :: [(Name, (Name, PDecl))], -- method name -> default impl
1084 class_defaults :: [(Name, (Name, PDecl))], -- method name -> default impl
1084 class_default_superclasses :: [PDecl],
1085 class_default_superclasses :: [PDecl],
1085 class_params :: [Name],
1086 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
1087 class_determiners :: [Int] }
1088 class_determiners :: [Int] }
1088 deriving Show
1089 deriving Show
1089{-!
1090{-!
src/Idris/Docs.hs+2−2
@@ -232,7 +232,7 @@ getDocs n w
232 classNameForInst ist n =
232 classNameForInst ist n =
233 listToMaybe [ cn
233 listToMaybe [ cn
234 | (cn, ci) <- toAlist (idris_classes ist)
234 | (cn, ci) <- toAlist (idris_classes ist)
235− , n `elem` class_instances ci
235+ , n `elem` map fst (class_instances ci)
236 ]
236 ]
237
237
238docData :: Name -> TypeInfo -> Idris Docs
238docData :: Name -> TypeInfo -> Idris Docs
@@ -254,7 +254,7 @@ docClass n ci
254 instances = map (\inst -> (namedInst inst,
254 instances = map (\inst -> (namedInst inst,
255 delabTy i inst,
255 delabTy i inst,
256 docsForInstance inst))
256 docsForInstance inst))
257− (nub (class_instances ci))
257+ (nub (map fst (class_instances ci)))
258 (subclasses, instances') = partition (isSubclass . (\(_,tm,_) -> tm)) instances
258 (subclasses, instances') = partition (isSubclass . (\(_,tm,_) -> tm)) instances
259 superclasses = catMaybes $ map getDInst (class_default_superclasses ci)
259 superclasses = catMaybes $ map getDInst (class_default_superclasses ci)
260 mdocs <- mapM (docFun . fst) (class_methods ci)
260 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
209 let conn' = case lookupCtxtName conn (idris_classes i) of
209 let conn' = case lookupCtxtName conn (idris_classes i) of
210 [(n, _)] -> n
210 [(n, _)] -> n
211 _ -> conn
211 _ -> conn
212− addInstance False conn' cfn
212+ addInstance False True conn' cfn
213− addIBC (IBCInstance False conn' cfn)
213+ addIBC (IBCInstance False True conn' cfn)
214-- iputStrLn ("Added " ++ show (conn, cfn, ty))
214-- iputStrLn ("Added " ++ show (conn, cfn, ty))
215 return [PTy emptyDocstring [] syn fc [] cfn NoFC ty,
215 return [PTy emptyDocstring [] syn fc [] cfn NoFC ty,
216 PClauses fc [Dictionary] cfn [PClause fc cfn lhs [] rhs []]]
216 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
77 -- and it's not a named instance, then it's overlapping, so report an error
77 -- and it's not a named instance, then it's overlapping, so report an error
78 case expn of
78 case expn of
79 Nothing -> do mapM_ (maybe (return ()) overlapping . findOverlapping i (class_determiners ci) (delab i nty))
79 Nothing -> do mapM_ (maybe (return ()) overlapping . findOverlapping i (class_determiners ci) (delab i nty))
80− (class_instances ci)
80+ (map fst $ class_instances ci)
81− addInstance intInst n iname
81+ addInstance intInst True n iname
82− Just _ -> addInstance intInst n iname
82+ Just _ -> addInstance intInst False n iname
83 when (what /= ETypes && (not (null ds && not emptyclass))) $ do
83 when (what /= ETypes && (not (null ds && not emptyclass))) $ do
84 let ips = zip (class_params ci) ps
84 let ips = zip (class_params ci) ps
85 let ns = case n of
85 let ns = case n of
@@ -143,7 +143,7 @@ elabInstance info syn doc argDocs what fc cs n nfc ps t expn ds = do
143 mapM_ (rec_elabDecl info EAll info) idecls
143 mapM_ (rec_elabDecl info EAll info) idecls
144 ist <- getIState
144 ist <- getIState
145 checkInjectiveArgs fc n (class_determiners ci) (lookupTyExact iname (tt_ctxt ist))
145 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)
147
147
148 where
148 where
149 intInst = case ps of
149 intInst = case ps of
@@ -186,7 +186,7 @@ elabInstance info syn doc argDocs what fc cs n nfc ps t expn ds = do
186 ctxt <- getContext
186 ctxt <- getContext
187 (cty, _) <- recheckC fc id [] tyT
187 (cty, _) <- recheckC fc id [] tyT
188 let nty = normalise ctxt [] cty
188 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)
190
190
191 findOverlapping i dets t n
191 findOverlapping i dets t n
192 | take 2 (show n) == "@@" = Nothing
192 | take 2 (show n) == "@@" = Nothing
src/Idris/Elab/Term.hs+42−25
@@ -15,6 +15,7 @@ import Idris.Core.Elaborate hiding (Tactic(..))
15import Idris.Core.TT
15import Idris.Core.TT
16import Idris.Core.Evaluate
16import Idris.Core.Evaluate
17import Idris.Core.Unify
17import Idris.Core.Unify
18+import Idris.Core.ProofTerm (getProofTerm)
18import Idris.Core.Typecheck (check, recheck, isType)
19import Idris.Core.Typecheck (check, recheck, isType)
19import Idris.Coverage (buildSCG, checkDeclTotality, genClauses, recoverableCoverage, validCoverageCase)
20import Idris.Coverage (buildSCG, checkDeclTotality, genClauses, recoverableCoverage, validCoverageCase)
20import Idris.ErrReverse (errReverse)
21import Idris.ErrReverse (errReverse)
@@ -1156,7 +1157,7 @@ elab ist info emode opts fn tm
1156 focus n
1157 focus n
1157 elab' ina (Just fc') tm
1158 elab' ina (Just fc') tm
1158 env <- get_env
1159 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)
1160 solve
1161 solve
1161 elab' ina fc x = fail $ "Unelaboratable syntactic form " ++ showTmImpls x
1162 elab' ina fc x = fail $ "Unelaboratable syntactic form " ++ showTmImpls x
1162
1163
@@ -1431,12 +1432,14 @@ findHighlight n = do ctxt <- get_context
1431 Nothing -> lift . tfail . InternalMsg $
1432 Nothing -> lift . tfail . InternalMsg $
1432 "Can't find name" ++ show n
1433 "Can't find name" ++ show n
1433
1434
1434−
1435+-- | Find the names of instances that have been designeated for
1436+-- searching (i.e. non-named instances or instances from Elab scripts)
1435findInstances :: IState -> Term -> [Name]
1437findInstances :: IState -> Term -> [Name]
1436findInstances ist t
1438findInstances ist t
1437 | (P _ n _, _) <- unApply (getRetTy t)
1439 | (P _ n _, _) <- unApply (getRetTy t)
1438 = case lookupCtxt n (idris_classes ist) of
1440 = case lookupCtxt n (idris_classes ist) of
1439− [CI _ _ _ _ _ ins _] -> filter accessible ins
1441+ [CI _ _ _ _ _ ins _] ->
1442+ [n | (n, True) <- ins, accessible n]
1440 _ -> []
1443 _ -> []
1441 | otherwise = []
1444 | otherwise = []
1442 where accessible n = case lookupDefAccExact n False (tt_ctxt ist) of
1445 where accessible n = case lookupDefAccExact n False (tt_ctxt ist) of
@@ -1466,15 +1469,14 @@ proofSearch' ist rec ambigok depth prv top n hints
1466 proofSearch rec prv ambigok (not prv) depth
1469 proofSearch rec prv ambigok (not prv) depth
1467 (elab ist toplevel ERHS [] (sMN 0 "tac")) top n hints ist
1470 (elab ist toplevel ERHS [] (sMN 0 "tac")) top n hints ist
1468
1471
1469−-- Resolve type classes. This will only pick up 'normal' instances, never
1472+-- | Resolve type classes. This will only pick up 'normal' instances, never
1470−-- named instances (hence using 'tcname' to check it's a generated instance
1473+-- named instances (which is enforced by 'findInstances').
1471−-- name).
1472−resolveTC :: Bool -- using default Int
1474+resolveTC :: Bool -- ^ using default Int
1473− -> Bool -- allow metavariables in the goal
1475+ -> Bool -- ^ allow metavariables in the goal
1474− -> Int -- depth
1476+ -> Int -- ^ depth
1475− -> Term -- top level goal
1477+ -> Term -- ^ top level goal, for error messages
1476− -> Name -- top level function name
1478+ -> Name -- ^ top level function name, to prevent loops
1477− -> IState -> ElabD ()
1479+ -> IState -> ElabD ()
1478resolveTC def mvok depth top fn ist
1480resolveTC def mvok depth top fn ist
1479 = do hs <- get_holes
1481 = do hs <- get_holes
1480 resTC' [] def hs depth top fn ist
1482 resTC' [] def hs depth top fn ist
@@ -1527,9 +1529,6 @@ resTC' tcs defaultOn topholes depth topg fn ist
1527 | Constant _ <- c = not (n `elem` hs)
1529 | Constant _ <- c = not (n `elem` hs)
1528 notHole _ _ = True
1530 notHole _ _ = True
1529
1531
1530− elabTC n | n /= fn && tcname n = (resolve n depth, show n)
1531− | otherwise = (fail "Can't resolve", show n)
1532−
1533 -- HACK! Rather than giving a special name, better to have some kind
1532 -- HACK! Rather than giving a special name, better to have some kind
1534 -- of flag in ClassInfo structure
1533 -- of flag in ClassInfo structure
1535 chaser (UN nm)
1534 chaser (UN nm)
@@ -1555,11 +1554,11 @@ resTC' tcs defaultOn topholes depth topg fn ist
1555 -- ps <- get_probs
1554 -- ps <- get_probs
1556 lift $ tfail $ CantResolve False topg
1555 lift $ tfail $ CantResolve False topg
1557 blunderbuss t d stk (n:ns)
1556 blunderbuss t d stk (n:ns)
1558− | n /= fn && (n `elem` stk || tcname n)
1557+ | n /= fn -- && (n `elem` stk)
1559− = tryCatch (resolve n d)
1558+ = tryCatch (resolve n d)
1560 (\e -> case e of
1559 (\e -> case e of
1561 CantResolve True _ -> lift $ tfail e
1560 CantResolve True _ -> lift $ tfail e
1562− _ -> blunderbuss t d stk ns)
1561+ _ -> blunderbuss t d stk ns)
1563 | otherwise = blunderbuss t d stk ns
1562 | otherwise = blunderbuss t d stk ns
1564
1563
1565 introImps = do g <- goal
1564 introImps = do g <- goal
@@ -1673,16 +1672,16 @@ case_ ind autoSolve ist fn tm = do
1673 when autoSolve solveAll
1672 when autoSolve solveAll
1674
1673
1675
1674
1676−runTactical :: FC -> Env -> Term -> ElabD ()
1675+runTactical :: IState -> FC -> Env -> Term -> ElabD ()
1677−runTactical fc env tm = do tm' <- eval tm
1676+runTactical ist fc env tm = do tm' <- eval tm
1678− runTacTm tm'
1677+ runTacTm tm'
1679− return ()
1678+ return ()
1680 where
1679 where
1681 eval tm = do ctxt <- get_context
1680 eval tm = do ctxt <- get_context
1682 env <- get_env
1681 env <- get_env
1683 return $ normaliseAll ctxt env (finalise tm)
1682 return $ normaliseAll ctxt env (finalise tm)
1684
1683
1685− returnUnit = fmap fst $ get_type_val (Var unitCon)
1684+ returnUnit = return $ P (DCon 0 0 False) unitCon (P (TCon 0 0) unitTy Erased)
1686
1685
1687 patvars :: [Name] -> Term -> ([Name], Term)
1686 patvars :: [Name] -> Term -> ([Name], Term)
1688 patvars ns (Bind n (PVar t) sc) = patvars (n : ns) (instantiate (P Bound n t) sc)
1687 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
1888 = do defn <- reifyFunDefn decl
1887 = do defn <- reifyFunDefn decl
1889 defineFunction defn
1888 defineFunction defn
1890 returnUnit
1889 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
1891 | n == tacN "prim__RecursiveElab", [goal, script] <- args
1901 | n == tacN "prim__RecursiveElab", [goal, script] <- args
1892 = do goal' <- reifyRaw goal
1902 = do goal' <- reifyRaw goal
1893 ctxt <- get_context
1903 ctxt <- get_context
@@ -1898,9 +1908,10 @@ runTactical fc env tm = do tm' <- eval tm
1898 aux <- getAux
1908 aux <- getAux
1899 datatypes <- get_datatypes
1909 datatypes <- get_datatypes
1900 env <- get_env
1910 env <- get_env
1901− (tm_out, ES (_, aux') _ _) <-
1911+ (_, ES (p, aux') _ _) <-
1902− lift $ runElab aux (runTactical fc env script >> solve >> get_term)
1912+ lift $ runElab aux (runTactical ist fc [] script)
1903 (newProof recH ctxt datatypes goalTT)
1913 (newProof recH ctxt datatypes goalTT)
1914+ let tm_out = getProofTerm (pterm p)
1904 updateAux $ const aux'
1915 updateAux $ const aux'
1905 env' <- get_env
1916 env' <- get_env
1906 (tm, ty, _) <- lift $ recheck ctxt env (forget tm_out) tm_out
1917 (tm, ty, _) <- lift $ recheck ctxt env (forget tm_out) tm_out
@@ -2266,6 +2277,12 @@ processTacticDecls info steps =
2266 let ds' = map (\(n, (i, top, t)) -> (n, (i, top, t, True))) ds
2277 let ds' = map (\(n, (i, top, t)) -> (n, (i, top, t, True))) ds
2267 in addDeferred ds'
2278 in addDeferred ds'
2268 _ -> return ()
2279 _ -> 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)
2269 RClausesInstrs n cs ->
2286 RClausesInstrs n cs ->
2270 do logLvl 3 $ "Pattern-matching definition from tactics: " ++ show n
2287 do logLvl 3 $ "Pattern-matching definition from tactics: " ++ show n
2271 solveDeferred n
2288 solveDeferred n
src/Idris/IBC.hs+6−6
@@ -41,7 +41,7 @@ import Codec.Archive.Zip
41import Util.Zlib (decompressEither)
41import Util.Zlib (decompressEither)
42
42
43ibcVersion :: Word16
43ibcVersion :: Word16
44−ibcVersion = 108
44+ibcVersion = 109
45
45
46data IBCFile = IBCFile { ver :: Word16,
46data IBCFile = IBCFile { ver :: Word16,
47 sourcefile :: FilePath,
47 sourcefile :: FilePath,
@@ -52,7 +52,7 @@ data IBCFile = IBCFile { ver :: Word16,
52 ibc_fixes :: ![FixDecl],
52 ibc_fixes :: ![FixDecl],
53 ibc_statics :: ![(Name, [Bool])],
53 ibc_statics :: ![(Name, [Bool])],
54 ibc_classes :: ![(Name, ClassInfo)],
54 ibc_classes :: ![(Name, ClassInfo)],
55− ibc_instances :: ![(Bool, Name, Name)],
55+ ibc_instances :: ![(Bool, Bool, Name, Name)],
56 ibc_dsls :: ![(Name, DSL)],
56 ibc_dsls :: ![(Name, DSL)],
57 ibc_datatypes :: ![(Name, TypeInfo)],
57 ibc_datatypes :: ![(Name, TypeInfo)],
58 ibc_optimise :: ![(Name, OptInfo)],
58 ibc_optimise :: ![(Name, OptInfo)],
@@ -229,8 +229,8 @@ ibc i (IBCClass n) f
229 = case lookupCtxtExact n (idris_classes i) of
229 = case lookupCtxtExact n (idris_classes i) of
230 Just v -> return f { ibc_classes = (n,v): ibc_classes f }
230 Just v -> return f { ibc_classes = (n,v): ibc_classes f }
231 _ -> ifail "IBC write failed"
231 _ -> ifail "IBC write failed"
232−ibc i (IBCInstance int n ins) f
232+ibc i (IBCInstance int res n ins) f
233− = return f { ibc_instances = (int,n,ins): ibc_instances f }
233+ = return f { ibc_instances = (int, res, n, ins) : ibc_instances f }
234ibc i (IBCDSL n) f
234ibc i (IBCDSL n) f
235 = case lookupCtxtExact n (idris_dsls i) of
235 = case lookupCtxtExact n (idris_dsls i) of
236 Just v -> return f { ibc_dsls = (n,v): ibc_dsls f }
236 Just v -> return f { ibc_dsls = (n,v): ibc_dsls f }
@@ -439,8 +439,8 @@ pClasses cs = mapM_ (\ (n, c) ->
439 = addDef n c' (idris_classes i) }))
439 = addDef n c' (idris_classes i) }))
440 cs
440 cs
441
441
442−pInstances :: [(Bool, Name, Name)] -> Idris ()
442+pInstances :: [(Bool, Bool, Name, Name)] -> Idris ()
443−pInstances cs = mapM_ (\ (i, n, ins) -> addInstance i n ins) cs
443+pInstances cs = mapM_ (\ (i, res, n, ins) -> addInstance i res n ins) cs
444
444
445pDSLs :: [(Name, DSL)] -> Idris ()
445pDSLs :: [(Name, DSL)] -> Idris ()
446pDSLs cs = mapM_ (\ (n, c) -> updateIState (\i ->
446pDSLs cs = mapM_ (\ (n, c) -> updateIState (\i ->
src/Idris/TypeSearch.hs+1−1
@@ -439,7 +439,7 @@ matchTypesBulk istate maxScore type1 types = getAllResults startQueueOfQueues wh
439 className <- getClassName clss
439 className <- getClassName clss
440 classDef <- lookupCtxt className classInfo
440 classDef <- lookupCtxt className classInfo
441 n <- class_instances classDef
441 n <- class_instances classDef
442− def <- lookupCtxt n (definitions ctxt)
442+ def <- lookupCtxt (fst n) (definitions ctxt)
443 nty <- normaliseC ctxt [] <$> (case typeFromDef def of Just x -> [x]; Nothing -> [])
443 nty <- normaliseC ctxt [] <$> (case typeFromDef def of Just x -> [x]; Nothing -> [])
444 let ty' = vToP (uniqueBinders usedns nty)
444 let ty' = vToP (uniqueBinders usedns nty)
445 return ty'
445 return ty'