on master help sign in
Merge branch 'master' into repl-definitions
ef36111Alyssa Carter
CHANGELOG+5
@@ -1,3 +1,8 @@
1+New in 0.9.15:
2+--------------
3+* Two new tactics: skip and fail. Skip does nothing, and fail takes a string as an argument and produces it as an error.
4+* Corresponding reflected tactics Skip and Fail. Reflected Fail takes a list of ErrorReportParts as an argument, like error handlers produce, allowing access to the pretty-printer.
5+
1New in 0.9.14:
6New in 0.9.14:
2--------------
7--------------
3* Tactic for case analysis in proofs
8* Tactic for case analysis in proofs
idris.cabal+25−2
@@ -1,5 +1,5 @@
1Name: idris
1Name: idris
2−Version: 0.9.14
2+Version: 0.9.14.1
3License: BSD3
3License: BSD3
4License-file: LICENSE
4License-file: LICENSE
5Author: Edwin Brady
5Author: Edwin Brady
@@ -241,6 +241,15 @@ Extra-source-files:
241 test/reg047/run
241 test/reg047/run
242 test/reg047/*.idr
242 test/reg047/*.idr
243 test/reg047/expected
243 test/reg047/expected
244+ test/reg048/run
245+ test/reg048/*.idr
246+ test/reg048/expected
247+ test/reg049/run
248+ test/reg049/*.idr
249+ test/reg049/expected
250+ test/reg050/run
251+ test/reg050/*.idr
252+ test/reg050/expected
244
253
245 test/basic001/run
254 test/basic001/run
246 test/basic001/*.idr
255 test/basic001/*.idr
@@ -425,6 +434,9 @@ Extra-source-files:
425 test/quasiquote003/run
434 test/quasiquote003/run
426 test/quasiquote003/*.idr
435 test/quasiquote003/*.idr
427 test/quasiquote003/expected
436 test/quasiquote003/expected
437+ test/quasiquote004/run
438+ test/quasiquote004/*.idr
439+ test/quasiquote004/expected
428
440
429
441
430 test/records001/run
442 test/records001/run
@@ -539,11 +551,22 @@ Library
539 , Idris.Core.Evaluate
551 , Idris.Core.Evaluate
540 , Idris.Core.Execute
552 , Idris.Core.Execute
541 , Idris.Core.ProofState
553 , Idris.Core.ProofState
554+ , Idris.Core.ProofTerm
542 , Idris.Core.TC
555 , Idris.Core.TC
543 , Idris.Core.TT
556 , Idris.Core.TT
544 , Idris.Core.Typecheck
557 , Idris.Core.Typecheck
545 , Idris.Core.Unify
558 , Idris.Core.Unify
546
559
560+ , Idris.Elab.Utils
561+ , Idris.Elab.Type
562+ , Idris.Elab.Clause
563+ , Idris.Elab.Data
564+ , Idris.Elab.Record
565+ , Idris.Elab.Class
566+ , Idris.Elab.Instance
567+ , Idris.Elab.Provider
568+ , Idris.Elab.Value
569+
547 , Idris.AbsSyntax
570 , Idris.AbsSyntax
548 , Idris.AbsSyntaxTree
571 , Idris.AbsSyntaxTree
549 , Idris.Apropos
572 , Idris.Apropos
@@ -646,7 +669,7 @@ Library
646 , language-java >= 0.2.6
669 , language-java >= 0.2.6
647 , lens >= 4.1.1
670 , lens >= 4.1.1
648 , mtl
671 , mtl
649− , parsers >= 0.9 && < 0.11.0.2
672+ , parsers >= 0.9 && < 0.13
650 , pretty
673 , pretty
651 , process
674 , process
652 , split
675 , split
libs/base/Language/Reflection.idr+358−87
@@ -2,32 +2,44 @@ module Language.Reflection
2
2
3%access public
3%access public
4
4
5−data TTName = UN String
5+data TTName =
6− -- ^ User-provided name
6+ ||| A user-provided name
7+ UN String |
8+ ||| A name in some namespace.
9+ |||
10+ ||| The namespace is in reverse order, so `(NS (UN "foo") ["B", "A"])` represents the name `A.B.foo`
7− | NS TTName (List String)
11+ NS TTName (List String) |
8− -- ^ Root, namespaces
9− | MN Int String
10− -- ^ Machine chosen names
12+ ||| Machine-chosen names
11− | NErased
13+ MN Int String |
12− -- ^ Name of somethng which is never used in scope
14+ ||| Name of something which is never used in scope
15+ NErased
13%name TTName n, n'
16%name TTName n, n'
14
17
15implicit
18implicit
16userSuppliedName : String -> TTName
19userSuppliedName : String -> TTName
17userSuppliedName = UN
20userSuppliedName = UN
18
21
19−data TTUExp = UVar Int
22+data TTUExp =
20− -- ^ universe variable
23+ ||| Universe variable
24+ UVar Int |
25+ ||| Explicit universe level
21− | UVal Int
26+ UVal Int
22− -- ^ explicit universe variable
23%name TTUExp uexp
27%name TTUExp uexp
24
28
29+data NativeTy = IT8 | IT16 | IT32 | IT64
30+
31+data IntTy = ITFixed NativeTy | ITNative | ITBig | ITChar
32+ | ITVec NativeTy Int
33+
34+data ArithTy = ATInt Language.Reflection.IntTy | ATFloat
35+
25||| Primitive constants
36||| Primitive constants
26data Const = I Int | BI Integer | Fl Float | Ch Char | Str String
37data Const = I Int | BI Integer | Fl Float | Ch Char | Str String
27− | IType | BIType | FlType | ChType | StrType
28 | B8 Bits8 | B16 Bits16 | B32 Bits32 | B64 Bits64
38 | B8 Bits8 | B16 Bits16 | B32 Bits32 | B64 Bits64
29− | B8Type | B16Type | B32Type | B64Type
39+ | B8V Bits8x16 | B16V Bits16x8
40+ | B32V Bits32x4 | B64V Bits64x2
41+ | AType ArithTy | StrType
30− | PtrType | VoidType | Forgot
42+ | PtrType | ManagedPtrType | BufferType | VoidType | Forgot
31
43
32%name Const c, c'
44%name Const c, c'
33
45
@@ -125,81 +137,340 @@ instance Traversable Binder where
125
137
126
138
127||| Reflection of the well typed core language
139||| Reflection of the well typed core language
140+data TT =
141+ ||| A reference to some name (P for Parameter)
128−data TT = P NameType TTName TT
142+ P NameType TTName TT |
129− -- ^ named binders
130− | V Int
131− -- ^ variables
143+ ||| de Bruijn variables
144+ V Int |
145+ ||| Bind a variable
132− | Bind TTName (Binder TT) TT
146+ Bind TTName (Binder TT) TT |
133− -- ^ type annotated named bindings
147+ ||| Apply one term to another
134− | App TT TT
148+ App TT TT |
135− -- ^ (named) application of a function to a value
149+ ||| Embed a constant
136− | TConst Const
150+ TConst Const |
137− -- ^ constants
138− | Proj TT Int
139− -- ^ argument projection; runtime only
151+ ||| Argument projection; runtime only
152+ Proj TT Int |
140− | Erased
153+ ||| Erased terms
141− -- ^ erased terms
154+ Erased |
142− | Impossible
155+ ||| Impossible terms
143− -- ^ impossible terms
156+ Impossible |
157+ ||| The type of types along (with universe constraints)
144− | TType TTUExp
158+ TType TTUExp
145− -- ^ types
146−
147%name TT tm, tm'
159%name TT tm, tm'
148
160
149||| Raw terms without types
161||| Raw terms without types
162+data Raw =
163+ ||| Variables, global or local
150−data Raw = Var TTName
164+ Var TTName |
165+ ||| Bind a variable
151− | RBind TTName (Binder Raw) Raw
166+ RBind TTName (Binder Raw) Raw |
167+ ||| Application
152− | RApp Raw Raw
168+ RApp Raw Raw |
169+ ||| The type of types
153− | RType
170+ RType |
154− | RForce Raw
171+ RForce Raw |
172+ ||| Embed a constant
155− | RConstant Const
173+ RConstant Const
156−
157%name Raw tm, tm'
174%name Raw tm, tm'
158
175
159−data Tactic = Try Tactic Tactic
176+||| Error reports are a list of report parts
177+data ErrorReportPart =
178+ ||| A human-readable string
179+ TextPart String |
180+ ||| An Idris name (to be semantically coloured)
181+ NamePart TTName |
182+ ||| An Idris term, to be pretty printed
183+ TermPart TT |
184+ ||| An indented sub-report, to provide more details
185+ SubReport (List ErrorReportPart)
186+%name ErrorReportPart part, p
187+
188+||| A representation of Idris's tactics that can be returned from custom
189+||| tactic implementations. Generate these using `applyTactic`.
190+data Tactic =
160− -- ^ try the first tactic and resort to the second one on failure
191+ ||| Try the first tactic and resort to the second one on failure
161− | GoalType String Tactic
192+ Try Tactic Tactic |
162− -- ^ only run if the goal has the right type
193+ ||| Only run if the goal has the right type
163− | Refine TTName
194+ GoalType String Tactic |
164− -- ^ resolve function name, find matching arguments in the
195+ ||| Resolve function name, find matching arguments in the
165− -- context and compute the proof target
196+ ||| context and compute the proof target
166− | Seq Tactic Tactic
197+ Refine TTName |
167− -- ^ apply both tactics in sequence
198+ ||| Apply both tactics in sequence
199+ Seq Tactic Tactic |
200+ ||| Intelligently construct the proof target from the context
168− | Trivial
201+ Trivial |
169− -- ^ intelligently construct the proof target from the context
170− | Search Int
171− -- ^ build a proof by applying contructors up to a maximum depth
202+ ||| Build a proof by applying contructors up to a maximum depth
203+ Search Int |
204+ ||| Resolve a type class
172− | Instance
205+ Instance |
173− -- ^ resolve a type class
206+ ||| Infer the proof target from the context
174− | Solve
207+ Solve |
175− -- ^ infer the proof target from the context
176− | Intros
177− -- ^ introduce all variables into the context
208+ ||| introduce all variables into the context
178− | Intro TTName
209+ Intros |
179− -- ^ introduce a named variable into the context, use the
210+ ||| Introduce a named variable into the context, use the
180− -- first one if the given name is not found
211+ ||| first one if the given name is not found
181− | ApplyTactic TT
212+ Intro TTName |
182− -- ^ invoke the reflected rep. of another tactic
213+ ||| Invoke the reflected rep. of another tactic
214+ ApplyTactic TT |
215+ ||| Turn a value into its reflected representation
183− | Reflect TT
216+ Reflect TT |
184− -- ^ turn a value into its reflected representation
217+ ||| Use a `%reflection` function
185− | ByReflection TT
218+ ByReflection TT |
186− -- ^ use a %reflection function
219+ ||| Turn a raw value back into a term
187− | Fill Raw
220+ Fill Raw |
188− -- ^ turn a raw value back into a term
221+ ||| Use the given value to conclude the proof
189− | Exact TT
222+ Exact TT |
190− -- ^ use the given value to conclude the proof
223+ ||| Focus on a particular hole
191− | Focus TTName
224+ Focus TTName |
192− -- ^ focus a named hole
225+ ||| Rewrite with an equality
193− | Rewrite TT
226+ Rewrite TT |
194− -- ^ rewrite using the reflected rep. of a equality proof
227+ ||| Perform induction on a particular expression
195− | Induction TT
228+ Induction TT |
196− -- ^ do induction on the particular expression
197− | Case TT
198− -- ^ do case analysis on particular expression
229+ ||| Perform case analysis on a particular expression
230+ Case TT |
231+ ||| Name a reflected term
199− | LetTac TTName TT
232+ LetTac TTName TT |
200− -- ^ name a reflected term
233+ ||| Name a reflected term and type it
201− | LetTacTy TTName TT TT
234+ LetTacTy TTName TT TT |
202− -- ^ name a reflected term and type it
235+ ||| Normalise the goal
203− | Compute
236+ Compute |
204− -- ^ normalise the context
237+ ||| Do nothing
238+ Skip |
239+ ||| Fail with an error message
240+ Fail (List ErrorReportPart)
205%name Tactic tac, tac'
241%name Tactic tac, tac'
242+
243+
244+||| Things with a canonical representation in the TT datatype.
245+|||
246+||| This type class is intended to be used during proof automation and the
247+||| construction of custom tactics.
248+|||
249+||| @ a the type to be quoted
250+class Quotable a where
251+ ||| A representation of the type `a`.
252+ |||
253+ ||| This is to enable quoting polymorphic datatypes
254+ quotedTy : TT
255+
256+ ||| Quote a particular element of `a`.
257+ |||
258+ ||| Each equation should look something like ```quote (Foo x y) = `(Foo ~(quote x) ~(quote y))```
259+ quote : a -> TT
260+
261+instance Quotable Nat where
262+ quotedTy = `(Nat)
263+
264+ quote Z = `(Z)
265+ quote (S k) = `(S ~(quote k))
266+
267+instance Quotable Int where
268+ quotedTy = `(Int)
269+ quote x = TConst (I x)
270+
271+instance Quotable Float where
272+ quotedTy = `(Float)
273+ quote x = TConst (Fl x)
274+
275+instance Quotable Char where
276+ quotedTy = `(Char)
277+ quote x = TConst (Ch x)
278+
279+instance Quotable Bits8 where
280+ quotedTy = `(Bits8)
281+ quote x = TConst (B8 x)
282+
283+instance Quotable Bits16 where
284+ quotedTy = `(Bits16)
285+ quote x = TConst (B16 x)
286+
287+instance Quotable Bits32 where
288+ quotedTy = `(Bits32)
289+ quote x = TConst (B32 x)
290+
291+instance Quotable Bits64 where
292+ quotedTy = `(Bits64)
293+ quote x = TConst (B64 x)
294+
295+instance Quotable Integer where
296+ quotedTy = `(Integer)
297+ quote x = TConst (BI x)
298+
299+instance Quotable Bits8x16 where
300+ quotedTy = `(Bits8x16)
301+ quote x = TConst (B8V x)
302+
303+instance Quotable Bits16x8 where
304+ quotedTy = `(Bits16x8)
305+ quote x = TConst (B16V x)
306+
307+instance Quotable Bits32x4 where
308+ quotedTy = `(Bits32x4)
309+ quote x = TConst (B32V x)
310+
311+instance Quotable Bits64x2 where
312+ quotedTy = `(Bits64x2)
313+ quote x = TConst (B64V x)
314+
315+instance Quotable String where
316+ quotedTy = `(String)
317+ quote x = TConst (Str x)
318+
319+instance Quotable NameType where
320+ quotedTy = `(NameType)
321+ quote Bound = `(Bound)
322+ quote Ref = `(Ref)
323+ quote (DCon x y) = `(DCon ~(quote x) ~(quote y))
324+ quote (TCon x y) = `(TCon ~(quote x) ~(quote y))
325+
326+instance Quotable a => Quotable (List a) where
327+ quotedTy = `(List ~(quotedTy {a=a}))
328+ quote [] = `(List.Nil {a=~quotedTy})
329+ quote (x :: xs) = `(List.(::) {a=~quotedTy} ~(quote x) ~(quote xs))
330+
331+instance Quotable TTName where
332+ quotedTy = `(TTName)
333+ quote (UN x) = `(UN ~(quote x))
334+ quote (NS n xs) = `(NS ~(quote n) ~(quote xs))
335+ quote (MN x y) = `(MN ~(quote x) ~(quote y))
336+ quote NErased = `(NErased)
337+
338+instance Quotable NativeTy where
339+ quotedTy = `(NativeTy)
340+ quote IT8 = `(Reflection.IT8)
341+ quote IT16 = `(Reflection.IT16)
342+ quote IT32 = `(Reflection.IT32)
343+ quote IT64 = `(Reflection.IT64)
344+
345+instance Quotable Reflection.IntTy where
346+ quotedTy = `(Reflection.IntTy)
347+ quote (ITFixed x) = `(ITFixed ~(quote x))
348+ quote ITNative = `(Reflection.ITNative)
349+ quote ITBig = `(ITBig)
350+ quote ITChar = `(Reflection.ITChar)
351+ quote (ITVec x y) = `(ITVec ~(quote x) ~(quote y))
352+
353+instance Quotable ArithTy where
354+ quotedTy = `(ArithTy)
355+ quote (ATInt x) = `(ATInt ~(quote x))
356+ quote ATFloat = `(ATFloat)
357+
358+instance Quotable Const where
359+ quotedTy = `(Const)
360+ quote (I x) = `(I ~(quote x))
361+ quote (BI x) = `(BI ~(quote x))
362+ quote (Fl x) = `(Fl ~(quote x))
363+ quote (Ch x) = `(Ch ~(quote x))
364+ quote (Str x) = `(Str ~(quote x))
365+ quote (B8 x) = `(B8 ~(quote x))
366+ quote (B16 x) = `(B16 ~(quote x))
367+ quote (B32 x) = `(B32 ~(quote x))
368+ quote (B64 x) = `(B64 ~(quote x))
369+ quote (B8V xs) = `(B8V ~(quote xs))
370+ quote (B16V xs) = `(B16V ~(quote xs))
371+ quote (B32V xs) = `(B32V ~(quote xs))
372+ quote (B64V xs) = `(B64V ~(quote xs))
373+ quote (AType x) = `(AType ~(quote x))
374+ quote StrType = `(StrType)
375+ quote PtrType = `(PtrType)
376+ quote ManagedPtrType = `(ManagedPtrType)
377+ quote BufferType = `(BufferType)
378+ quote VoidType = `(VoidType)
379+ quote Forgot = `(Forgot)
380+
381+
382+instance Quotable TTUExp where
383+ quotedTy = `(TTUExp)
384+ quote (UVar x) = `(UVar ~(quote x))
385+ quote (UVal x) = `(UVal ~(quote x))
386+
387+mutual
388+ instance Quotable TT where
389+ quotedTy = `(TT)
390+ quote (P nt n tm) = `(P ~(quote nt) ~(quote n) ~(quote tm))
391+ quote (V x) = `(V ~(quote x))
392+ quote (Bind n b tm) = `(Bind ~(quote n) ~(assert_total (quote b)) ~(quote tm))
393+ quote (App f x) = `(App ~(quote f) ~(quote x))
394+ quote (TConst c) = `(TConst ~(quote c))
395+ quote (Proj tm x) = `(Proj ~(quote tm) ~(quote x))
396+ quote Erased = `(Erased)
397+ quote Impossible = `(Impossible)
398+ quote (TType uexp) = `(TType ~(quote uexp))
399+
400+ instance Quotable (Binder TT) where
401+ quotedTy = `(Binder TT)
402+ quote (Lam x) = `(Lam {a=TT} ~(assert_total (quote x)))
403+ quote (Pi x) = `(Pi {a=TT} ~(assert_total (quote x)))
404+ quote (Let x y) = `(Let {a=TT} ~(assert_total (quote x))
405+ ~(assert_total (quote y)))
406+ quote (NLet x y) = `(NLet {a=TT} ~(assert_total (quote x))
407+ ~(assert_total (quote y)))
408+ quote (Hole x) = `(Hole {a=TT} ~(assert_total (quote x)))
409+ quote (GHole x) = `(GHole {a=TT} ~(assert_total (quote x)))
410+ quote (Guess x y) = `(Guess {a=TT} ~(assert_total (quote x))
411+ ~(assert_total (quote y)))
412+ quote (PVar x) = `(PVar {a=TT} ~(assert_total (quote x)))
413+ quote (PVTy x) = `(PVTy {a=TT} ~(assert_total (quote x)))
414+
415+
416+instance Quotable ErrorReportPart where
417+ quotedTy = `(ErrorReportPart)
418+ quote (TextPart x) = `(TextPart ~(quote x))
419+ quote (NamePart n) = `(NamePart ~(quote n))
420+ quote (TermPart tm) = `(TermPart ~(quote tm))
421+ quote (SubReport xs) = `(SubReport ~(assert_total $ quote xs))
422+
423+mutual
424+ quoteRaw : Raw -> TT
425+ quoteRaw (Var n) = `(Var ~(quote n))
426+ quoteRaw (RBind n b tm) = `(RBind ~(quote n) ~(assert_total $ quoteRawBinder b) ~(quoteRaw tm))
427+ quoteRaw (RApp tm tm') = `(RApp ~(quoteRaw tm) ~(quoteRaw tm'))
428+ quoteRaw RType = `(RType)
429+ quoteRaw (RForce tm) = `(RForce ~(quoteRaw tm))
430+ quoteRaw (RConstant c) = `(RConstant ~(quote c))
431+
432+ quoteRawBinder : Binder Raw -> TT
433+ quoteRawBinder (Lam x) = `(Lam {a=Raw} ~(quoteRaw x))
434+ quoteRawBinder (Pi x) = `(Pi {a=Raw} ~(quoteRaw x))
435+ quoteRawBinder (Let x y) = `(Let {a=Raw} ~(quoteRaw x) ~(quoteRaw y))
436+ quoteRawBinder (NLet x y) = `(NLet {a=Raw} ~(quoteRaw x) ~(quoteRaw y))
437+ quoteRawBinder (Hole x) = `(Hole {a=Raw} ~(quoteRaw x))
438+ quoteRawBinder (GHole x) = `(GHole {a=Raw} ~(quoteRaw x))
439+ quoteRawBinder (Guess x y) = `(Guess {a=Raw} ~(quoteRaw x) ~(quoteRaw y))
440+ quoteRawBinder (PVar x) = `(PVar {a=Raw} ~(quoteRaw x))
441+ quoteRawBinder (PVTy x) = `(PVTy {a=Raw} ~(quoteRaw x))
442+
443+instance Quotable Raw where
444+ quotedTy = `(Raw)
445+ quote = quoteRaw
446+
447+instance Quotable (Binder Raw) where
448+ quotedTy = `(Binder Raw)
449+ quote = quoteRawBinder
450+
451+instance Quotable Tactic where
452+ quotedTy = `(Tactic)
453+ quote (Try tac tac') = `(Try ~(quote tac) ~(quote tac'))
454+ quote (GoalType x tac) = `(GoalType ~(quote x) ~(quote tac))
455+ quote (Refine n) = `(Refine ~(quote n))
456+ quote (Seq tac tac') = `(Seq ~(quote tac) ~(quote tac'))
457+ quote Trivial = `(Trivial)
458+ quote (Search x) = `(Search ~(quote x))
459+ quote Instance = `(Instance)
460+ quote Solve = `(Solve)
461+ quote Intros = `(Intros)
462+ quote (Intro n) = `(Intro ~(quote n))
463+ quote (ApplyTactic tm) = `(ApplyTactic ~(quote tm))
464+ quote (Reflect tm) = `(Reflect ~(quote tm))
465+ quote (ByReflection tm) = `(ByReflection ~(quote tm))
466+ quote (Fill tm) = `(Fill ~(quote tm))
467+ quote (Exact tm) = `(Exact ~(quote tm))
468+ quote (Focus n) = `(Focus ~(quote n))
469+ quote (Rewrite tm) = `(Rewrite ~(quote tm))
470+ quote (Induction tm) = `(Induction ~(quote tm))
471+ quote (Case tm) = `(Case ~(quote tm))
472+ quote (LetTac n tm) = `(LetTac ~(quote n) ~(quote tm))
473+ quote (LetTacTy n tm tm') = `(LetTacTy ~(quote n) ~(quote tm) ~(quote tm'))
474+ quote Compute = `(Compute)
475+ quote Skip = `(Skip)
476+ quote (Fail xs) = `(Fail ~(quote xs))
libs/base/Language/Reflection/Errors.idr−7
@@ -40,13 +40,6 @@ data Err = Msg String
40
40
41%name Err err, e
41%name Err err, e
42
42
43−||| Error reports are a list of report parts
44−data ErrorReportPart = TextPart String
45− | NamePart TTName
46− | TermPart TT
47− | SubReport (List ErrorReportPart)
48−%name ErrorReportPart part, p
49−
50-- Error reports become functions in List (String, TT) -> Err -> ErrorReport
43-- Error reports become functions in List (String, TT) -> Err -> ErrorReport
51ErrorHandler : Type
44ErrorHandler : Type
52ErrorHandler = Err -> Maybe (List ErrorReportPart)
45ErrorHandler = Err -> Maybe (List ErrorReportPart)
libs/base/Language/Reflection/Utils.idr+55−34
@@ -3,6 +3,8 @@ module Language.Reflection.Utils
3import Language.Reflection
3import Language.Reflection
4import Language.Reflection.Errors
4import Language.Reflection.Errors
5
5
6+%default total
7+
6--------------------------------------------------------
8--------------------------------------------------------
7-- Tactic construction conveniences
9-- Tactic construction conveniences
8--------------------------------------------------------
10--------------------------------------------------------
@@ -83,46 +85,65 @@ instance Show Const where
83 show (Fl f) = "(Fl " ++ show f ++ ")"
85 show (Fl f) = "(Fl " ++ show f ++ ")"
84 show (Ch c) = "(Ch " ++ show c ++ ")"
86 show (Ch c) = "(Ch " ++ show c ++ ")"
85 show (Str str) = "(Str " ++ show str ++ ")"
87 show (Str str) = "(Str " ++ show str ++ ")"
86− show IType = "IType"
87− show BIType = "BIType"
88− show FlType = "FlType"
89− show ChType = "ChType"
90− show StrType = "StrType"
91 show (B8 b) = "(B8 ...)"
88 show (B8 b) = "(B8 ...)"
92 show (B16 b) = "(B16 ...)"
89 show (B16 b) = "(B16 ...)"
93 show (B32 b) = "(B32 ...)"
90 show (B32 b) = "(B32 ...)"
94 show (B64 b) = "(B64 ...)"
91 show (B64 b) = "(B64 ...)"
95− show B8Type = "B8Type"
92+ show (B8V xs) = "(B8V ...)"
96− show B16Type = "B16Type"
93+ show (B16V xs) = "(B16V ...)"
97− show B32Type = "B32Type"
94+ show (B32V xs) = "(B32V ...)"
98− show B64Type = "B64Type"
95+ show (B64V xs) = "(B64V ...)"
96+ show (AType x) = "(AType ...)"
97+ show StrType = "StrType"
99− show PtrType = "PtrType"
98+ show PtrType = "PtrType"
99+ show ManagedPtrType = "ManagedPtrType"
100+ show BufferType = "BufferType"
100− show VoidType = "VoidType"
101+ show VoidType = "VoidType"
101− show Forgot = "Forgot"
102+ show Forgot = "Forgot"
103+
104+instance Eq NativeTy where
105+ IT8 == IT8 = True
106+ IT16 == IT16 = True
107+ IT32 == IT32 = True
108+ IT64 == IT64 = True
109+ _ == _ = False
110+
111+instance Eq Reflection.IntTy where
112+ (ITFixed x) == (ITFixed y) = x == y
113+ ITNative == ITNative = True
114+ ITBig == ITBig = True
115+ ITChar == ITChar = True
116+ (ITVec x i) == (ITVec y j) = x == y && i == j
117+ _ == _ = False
118+
119+instance Eq ArithTy where
120+ (ATInt x) == (ATInt y) = x == y
121+ ATFloat == ATFloat = True
122+ _ == _ = False
102
123
103instance Eq Const where
124instance Eq Const where
104− (I i) == (I i') = i == i'
125+ (I x) == (I y) = x == y
105− (BI n) == (BI n') = n == n'
126+ (BI x) == (BI y) = x == y
106− (Fl f) == (Fl f') = f == f'
127+ (Fl x) == (Fl y) = x == y
107− (Ch c) == (Ch c') = c == c'
128+ (Ch x) == (Ch y) = x == y
108− (Str str) == (Str str') = str == str'
129+ (Str x) == (Str y) = x == y
109− IType == IType = True
130+ (B8 x) == (B8 y) = x == y
110− BIType == BIType = True
131+ (B16 x) == (B16 y) = x == y
111− FlType == FlType = True
132+ (B32 x) == (B32 y) = x == y
112− ChType == ChType = True
133+ (B64 x) == (B64 y) = x == y
113− StrType == StrType = True
134+ (B8V xs) == (B8V ys) = False -- TODO
114− (B8 b) == (B8 b') = False -- FIXME: b == b'
135+ (B16V xs) == (B16V ys) = False -- TODO
115− (B16 b) == (B16 b') = False -- FIXME: b == b'
136+ (B32V xs) == (B32V ys) = False -- TODO
116− (B32 b) == (B32 b') = False -- FIXME: b == b'
137+ (B64V xs) == (B64V ys) = False -- TODO
117− (B64 b) == (B64 b') = False -- FIXME: b == b'
138+ (AType x) == (AType y) = x == y
118− B8Type == B8Type = True
139+ StrType == StrType = True
119− B16Type == B16Type = True
140+ PtrType == PtrType = True
120− B32Type == B32Type = True
141+ ManagedPtrType == ManagedPtrType = True
121− B64Type == B64Type = True
142+ BufferType == BufferType = True
122− PtrType == PtrType = True
143+ VoidType == VoidType = True
123− VoidType == VoidType = True
144+ Forgot == Forgot = True
124− Forgot == Forgot = True
125− x == y = False
145+ _ == _ = False
146+
126
147
127instance Show NameType where
148instance Show NameType where
128 show Bound = "Bound"
149 show Bound = "Bound"
libs/effects/Effect/File.idr+9−5
@@ -60,10 +60,10 @@ data FileIO : Effect where
60 ||| Only files that are open for reading can be read.
60 ||| Only files that are open for reading can be read.
61 ReadLine : {OpenFile Read} FileIO String
61 ReadLine : {OpenFile Read} FileIO String
62
62
63− ||| Write a line to a file.
63+ ||| Write a string to a file.
64 |||
64 |||
65 ||| Only file that are open for writing can be written to.
65 ||| Only file that are open for writing can be written to.
66− WriteLine : String -> {OpenFile Write} FileIO ()
66+ WriteString : String -> {OpenFile Write} FileIO ()
67
67
68 ||| End of file?
68 ||| End of file?
69 |||
69 |||
@@ -82,8 +82,8 @@ instance Handler FileIO IO where
82 k () ()
82 k () ()
83 handle (FH h) ReadLine k = do str <- fread h
83 handle (FH h) ReadLine k = do str <- fread h
84 k str (FH h)
84 k str (FH h)
85− handle (FH h) (WriteLine str) k = do fwrite h str
85+ handle (FH h) (WriteString str) k = do fwrite h str
86− k () (FH h)
86+ k () (FH h)
87 handle (FH h) EOF k = do e <- feof h
87 handle (FH h) EOF k = do e <- feof h
88 k e (FH h)
88 k e (FH h)
89
89
@@ -117,9 +117,13 @@ close = call $ Close
117readLine : { [FILE_IO (OpenFile Read)] } Eff String
117readLine : { [FILE_IO (OpenFile Read)] } Eff String
118readLine = call $ ReadLine
118readLine = call $ ReadLine
119
119
120+||| Write a string to a file.
121+writeString : String -> { [FILE_IO (OpenFile Write)] } Eff ()
122+writeString str = call $ WriteString str
123+
120||| Write a line to a file.
124||| Write a line to a file.
121writeLine : String -> { [FILE_IO (OpenFile Write)] } Eff ()
125writeLine : String -> { [FILE_IO (OpenFile Write)] } Eff ()
122−writeLine str = call $ WriteLine str
126+writeLine str = call $ WriteString (str ++ "\n")
123
127
124||| End of file?
128||| End of file?
125eof : { [FILE_IO (OpenFile Read)] } Eff Bool
129eof : { [FILE_IO (OpenFile Read)] } Eff Bool
libs/effects/Effects.idr+1
@@ -152,6 +152,7 @@ data Eff : (x : Type)
152 Eff t [x] xs' -> -- [x] (\v => xs) ->
152 Eff t [x] xs' -> -- [x] (\v => xs) ->
153 Eff t [l ::: x] (\v => map (l :::) (xs' v))
153 Eff t [l ::: x] (\v => map (l :::) (xs' v))
154
154
155+%no_implicit
155(>>=) : Eff a xs xs' ->
156(>>=) : Eff a xs xs' ->
156 ((val : a) -> Eff b (xs' val) xs'') -> Eff b xs xs''
157 ((val : a) -> Eff b (xs' val) xs'') -> Eff b xs xs''
157(>>=) = ebind
158(>>=) = ebind
libs/effects/Makefile+11−4
@@ -1,14 +1,21 @@
1IDRIS := idris
1IDRIS := idris
2+PKG := effects
2
3
3build:
4build:
4− $(IDRIS) --build effects.ipkg
5+ $(IDRIS) --build ${PKG}.ipkg
5
6
6clean:
7clean:
7− $(IDRIS) --clean effects.ipkg
8+ $(IDRIS) --clean ${PKG}.ipkg
8
9
9install:
10install:
10− $(IDRIS) --install effects.ipkg
11+ $(IDRIS) --install ${PKG}.ipkg
11
12
12rebuild: clean build
13rebuild: clean build
13
14
15+doc:
16+ $(IDRIS) --mkdoc ${PKG}.ipkg
17+
18+doc_clean:
19+ rm -rf ${PKG}_doc
20+
14−.PHONY: build clean install rebuild
21+.PHONY: build clean install rebuild doc doc_clean
src/Idris/AbsSyntaxTree.hs+16−2
@@ -35,15 +35,24 @@ import Debug.Trace
35
35
36import Text.PrettyPrint.Annotated.Leijen
36import Text.PrettyPrint.Annotated.Leijen
37
37
38+data ElabWhat = ETypes | EDefns | EAll
39+ deriving (Show, Eq)
40+
38-- Data to pass to recursively called elaborators; e.g. for where blocks,
41-- Data to pass to recursively called elaborators; e.g. for where blocks,
39-- paramaterised declarations, etc.
42-- paramaterised declarations, etc.
40
43
44+-- rec_elabDecl is used to pass the top level elaborator into other elaborators,
45+-- so that we can have mutually recursive elaborators in separate modules without
46+-- having to much about with cyclic modules.
41data ElabInfo = EInfo { params :: [(Name, PTerm)],
47data ElabInfo = EInfo { params :: [(Name, PTerm)],
42 inblock :: Ctxt [Name], -- names in the block, and their params
48 inblock :: Ctxt [Name], -- names in the block, and their params
43 liftname :: Name -> Name,
49 liftname :: Name -> Name,
44− namespace :: Maybe [String] }
50+ namespace :: Maybe [String],
51+ rec_elabDecl :: ElabWhat -> ElabInfo -> PDecl ->
52+ Idris () }
45
53
54+toplevel :: ElabInfo
46−toplevel = EInfo [] emptyContext id Nothing
55+toplevel = EInfo [] emptyContext id Nothing (\_ _ _ -> fail "Not implemented")
47
56
48eInfoNames :: ElabInfo -> [Name]
57eInfoNames :: ElabInfo -> [Name]
49eInfoNames info = map fst (params info) ++ M.keys (inblock info)
58eInfoNames info = map fst (params info) ++ M.keys (inblock info)
@@ -469,6 +478,7 @@ data FnOpt = Inlinable -- always evaluate when simplifying
469 | Dictionary -- type class dictionary, eval only when
478 | Dictionary -- type class dictionary, eval only when
470 -- a function argument, and further evaluation resutls
479 -- a function argument, and further evaluation resutls
471 | Implicit -- implicit coercion
480 | Implicit -- implicit coercion
481+ | NoImplicit -- do not apply implicit coercions
472 | CExport String -- export, with a C name
482 | CExport String -- export, with a C name
473 | ErrorHandler -- ^^ an error handler for use with the ErrorReflection extension
483 | ErrorHandler -- ^^ an error handler for use with the ErrorReflection extension
474 | ErrorReverse -- ^^ attempt to reverse normalise before showing in error
484 | ErrorReverse -- ^^ attempt to reverse normalise before showing in error
@@ -769,6 +779,8 @@ data PTactic' t = Intro [Name] | Intros | Focus Name
769 | TEval t
779 | TEval t
770 | TDocStr (Either Name Const)
780 | TDocStr (Either Name Const)
771 | TSearch t
781 | TSearch t
782+ | Skip
783+ | TFail [ErrorReportPart]
772 | Qed | Abandon
784 | Qed | Abandon
773 deriving (Show, Eq, Functor)
785 deriving (Show, Eq, Functor)
774{-!
786{-!
@@ -798,6 +810,8 @@ instance Sized a => Sized (PTactic' a) where
798 size (Fill t) = 1 + size t
810 size (Fill t) = 1 + size t
799 size Qed = 1
811 size Qed = 1
800 size Abandon = 1
812 size Abandon = 1
813+ size Skip = 1
814+ size (TFail ts) = 1 + size ts
801
815
802type PTactic = PTactic' PTerm
816type PTactic = PTactic' PTerm
803
817
src/Idris/CaseSplit.hs+4−2
@@ -16,6 +16,8 @@ import Idris.Parser
16import Idris.Error
16import Idris.Error
17import Idris.Output
17import Idris.Output
18
18
19+import Idris.Elab.Value
20+
19import Idris.Core.TT
21import Idris.Core.TT
20import Idris.Core.Typecheck
22import Idris.Core.Typecheck
21import Idris.Core.Evaluate
23import Idris.Core.Evaluate
@@ -55,7 +57,7 @@ split n t'
55 = do ist <- getIState
57 = do ist <- getIState
56 -- Make sure all the names in the term are accessible
58 -- Make sure all the names in the term are accessible
57 mapM_ (\n -> setAccessibility n Public) (allNamesIn t')
59 mapM_ (\n -> setAccessibility n Public) (allNamesIn t')
58− (tm, ty, pats) <- elabValBind toplevel ELHS True (addImplPat ist t')
60+ (tm, ty, pats) <- elabValBind recinfo ELHS True (addImplPat ist t')
59 -- ASSUMPTION: tm is in normal form after elabValBind, so we don't
61 -- ASSUMPTION: tm is in normal form after elabValBind, so we don't
60 -- need to do anything special to find out what family each argument
62 -- need to do anything special to find out what family each argument
61 -- is in
63 -- is in
@@ -201,7 +203,7 @@ tidy ist tm ty = return tm
201-- tidyVar t = t
203-- tidyVar t = t
202
204
203elabNewPat :: PTerm -> Idris (Maybe PTerm)
205elabNewPat :: PTerm -> Idris (Maybe PTerm)
204−elabNewPat t = idrisCatch (do (tm, ty) <- elabVal toplevel ELHS t
206+elabNewPat t = idrisCatch (do (tm, ty) <- elabVal recinfo ELHS t
205 i <- getIState
207 i <- getIState
206 return (Just (delab i tm)))
208 return (Just (delab i tm)))
207 (\e -> do i <- getIState
209 (\e -> do i <- getIState
src/Idris/Core/Elaborate.hs+5−16
@@ -12,6 +12,7 @@ module Idris.Core.Elaborate(module Idris.Core.Elaborate,
12 module Idris.Core.ProofState) where
12 module Idris.Core.ProofState) where
13
13
14import Idris.Core.ProofState
14import Idris.Core.ProofState
15+import Idris.Core.ProofTerm(bound_in, getProofTerm, mkProofTerm, bound_in_term)
15import Idris.Core.TT
16import Idris.Core.TT
16import Idris.Core.Evaluate
17import Idris.Core.Evaluate
17import Idris.Core.Typecheck
18import Idris.Core.Typecheck
@@ -128,10 +129,6 @@ elaborate ctxt n ty d elab = do let ps = initElaborator n ctxt ty
128 (a, ES ps' str _) <- runElab d elab ps
129 (a, ES ps' str _) <- runElab d elab ps
129 return $! (a, str)
130 return $! (a, str)
130
131
131−force_term :: Elab' aux ()
132−force_term = do ES (ps, a) l p <- get
133− put (ES (ps { pterm = force (pterm ps) }, a) l p)
134−
135-- | Modify the auxiliary state
132-- | Modify the auxiliary state
136updateAux :: (aux -> aux) -> Elab' aux ()
133updateAux :: (aux -> aux) -> Elab' aux ()
137updateAux f = do ES (ps, a) l p <- get
134updateAux f = do ES (ps, a) l p <- get
@@ -190,12 +187,12 @@ set_context ctxt = do ES (p, a) logs prev <- get
190-- get the proof term
187-- get the proof term
191get_term :: Elab' aux Term
188get_term :: Elab' aux Term
192get_term = do ES p _ _ <- get
189get_term = do ES p _ _ <- get
193− return $! (pterm (fst p))
190+ return $! (getProofTerm (pterm (fst p)))
194
191
195-- get the proof term
192-- get the proof term
196update_term :: (Term -> Term) -> Elab' aux ()
193update_term :: (Term -> Term) -> Elab' aux ()
197update_term f = do ES (p,a) logs prev <- get
194update_term f = do ES (p,a) logs prev <- get
198− let p' = p { pterm = f (pterm p) }
195+ let p' = p { pterm = mkProofTerm (f (getProofTerm (pterm p))) }
199 put (ES (p', a) logs prev)
196 put (ES (p', a) logs prev)
200
197
201-- get the local context at the currently in focus hole
198-- get the local context at the currently in focus hole
@@ -271,7 +268,7 @@ unique_hole' :: Bool -> Name -> Elab' aux Name
271unique_hole' reusable n
268unique_hole' reusable n
272 = do ES p _ _ <- get
269 = do ES p _ _ <- get
273 let bs = bound_in (pterm (fst p)) ++
270 let bs = bound_in (pterm (fst p)) ++
274− bound_in (ptype (fst p))
271+ bound_in_term (ptype (fst p))
275 let nouse = holes (fst p) ++ bs ++ dontunify (fst p) ++ usedns (fst p)
272 let nouse = holes (fst p) ++ bs ++ dontunify (fst p) ++ usedns (fst p)
276 n' <- return $! uniqueNameCtxt (context (fst p)) n nouse
273 n' <- return $! uniqueNameCtxt (context (fst p)) n nouse
277 ES (p, a) s u <- get
274 ES (p, a) s u <- get
@@ -280,14 +277,6 @@ unique_hole' reusable n
280 put (ES (p { nextname = i + 1 }, a) s u)
277 put (ES (p { nextname = i + 1 }, a) s u)
281 _ -> return $! ()
278 _ -> return $! ()
282 return $! n'
279 return $! n'
283− where
284− bound_in (Bind n b sc) = n : bi b ++ bound_in sc
285− where
286− bi (Let t v) = bound_in t ++ bound_in v
287− bi (Guess t v) = bound_in t ++ bound_in v
288− bi b = bound_in (binderTy b)
289− bound_in (App f a) = bound_in f ++ bound_in a
290− bound_in _ = []
291
280
292elog :: String -> Elab' aux ()
281elog :: String -> Elab' aux ()
293elog str = do ES p logs prev <- get
282elog str = do ES p logs prev <- get
@@ -429,7 +418,7 @@ reorder_claims n = processTactic' (Reorder n)
429qed :: Elab' aux Term
418qed :: Elab' aux Term
430qed = do processTactic' QED
419qed = do processTactic' QED
431 ES p _ _ <- get
420 ES p _ _ <- get
432− return $! (pterm (fst p))
421+ return $! (getProofTerm (pterm (fst p)))
433
422
434undo :: Elab' aux ()
423undo :: Elab' aux ()
435undo = processTactic' Undo
424undo = processTactic' Undo
src/Idris/Core/ProofState.hs+25−102
@@ -12,6 +12,7 @@ import Idris.Core.Typecheck
12import Idris.Core.Evaluate
12import Idris.Core.Evaluate
13import Idris.Core.TT
13import Idris.Core.TT
14import Idris.Core.Unify
14import Idris.Core.Unify
15+import Idris.Core.ProofTerm
15
16
16import Control.Monad.State.Strict
17import Control.Monad.State.Strict
17import Control.Applicative hiding (empty)
18import Control.Applicative hiding (empty)
@@ -25,7 +26,7 @@ data ProofState = PS { thname :: Name,
25 holes :: [Name], -- holes still to be solved
26 holes :: [Name], -- holes still to be solved
26 usedns :: [Name], -- used names, don't use again
27 usedns :: [Name], -- used names, don't use again
27 nextname :: Int, -- name supply
28 nextname :: Int, -- name supply
28− pterm :: Term, -- current proof term
29+ pterm :: ProofTerm, -- current proof term
29 ptype :: Type, -- original goal
30 ptype :: Type, -- original goal
30 dontunify :: [Name], -- explicitly given by programmer, leave it
31 dontunify :: [Name], -- explicitly given by programmer, leave it
31 unified :: (Name, [(Name, Term)]),
32 unified :: (Name, [(Name, Term)]),
@@ -43,10 +44,6 @@ data ProofState = PS { thname :: Name,
43 while_elaborating :: [FailContext]
44 while_elaborating :: [FailContext]
44 }
45 }
45
46
46−data Goal = GD { premises :: Env,
47− goalType :: Binder Term
48− }
49−
50data Tactic = Attack
47data Tactic = Attack
51 | Claim Name Raw
48 | Claim Name Raw
52 | Reorder Name
49 | Reorder Name
@@ -141,13 +138,6 @@ instance Pretty ProofState OutputAnnotation where
141 nest nestingSize (pretty n <+> colon <+> prettyEnv env (binderTy b) <+>
138 nest nestingSize (pretty n <+> colon <+> prettyEnv env (binderTy b) <+>
142 nest nestingSize (prettyPs env bs))
139 nest nestingSize (prettyPs env bs))
143
140
144−same Nothing n = True
145−same (Just x) n = x == n
146−
147−hole (Hole _) = True
148−hole (Guess _ _) = True
149−hole _ = False
150−
151holeName i = sMN i "hole"
141holeName i = sMN i "hole"
152
142
153qshow :: Fails -> String
143qshow :: Fails -> String
@@ -165,7 +155,7 @@ match_unify' ctxt env topx topy =
165 " in " ++ show env ++
155 " in " ++ show env ++
166 "\nHoles: " ++ show (holes ps)
156 "\nHoles: " ++ show (holes ps)
167 ++ "\n"
157 ++ "\n"
168− ++ "\n" ++ show (pterm ps) ++ "\n\n"
158+ ++ "\n" ++ show (getProofTerm (pterm ps)) ++ "\n\n"
169 ) $
159 ) $
170 case match_unify ctxt env topx topy inj (holes ps) while of
160 case match_unify ctxt env topx topy inj (holes ps) while of
171 OK u -> traceWhen (unifylog ps)
161 OK u -> traceWhen (unifylog ps)
@@ -290,15 +280,14 @@ addLog str = action (\ps -> ps { plog = plog ps ++ str ++ "\n" })
290newProof :: Name -> Context -> Type -> ProofState
280newProof :: Name -> Context -> Type -> ProofState
291newProof n ctxt ty = let h = holeName 0
281newProof n ctxt ty = let h = holeName 0
292 ty' = vToP ty in
282 ty' = vToP ty in
293− PS n [h] [] 1 (Bind h (Hole ty')
283+ PS n [h] [] 1 (mkProofTerm (Bind h (Hole ty')
294− (P Bound h ty')) ty [] (h, []) []
284+ (P Bound h ty'))) ty [] (h, []) []
295 Nothing [] []
285 Nothing [] []
296 [] []
286 [] []
297 Nothing ctxt "" False False []
287 Nothing ctxt "" False False []
298
288
299type TState = ProofState -- [TacticAction])
289type TState = ProofState -- [TacticAction])
300−type RunTactic = Context -> Env -> Term -> StateT TState TC Term
290+type RunTactic = RunTactic' TState
301−type Hole = Maybe Name -- Nothing = default hole, first in list in proof state
302
291
303envAtFocus :: ProofState -> TC Env
292envAtFocus :: ProofState -> TC Env
304envAtFocus ps
293envAtFocus ps
@@ -310,64 +299,13 @@ goalAtFocus :: ProofState -> TC (Binder Type)
310goalAtFocus ps
299goalAtFocus ps
311 | not $ null (holes ps) = do g <- goal (Just (head (holes ps))) (pterm ps)
300 | not $ null (holes ps) = do g <- goal (Just (head (holes ps))) (pterm ps)
312 return (goalType g)
301 return (goalType g)
313− | otherwise = Error . Msg $ "No goal in " ++ show (holes ps) ++ show (pterm ps)
302+ | otherwise = Error . Msg $ "No goal in " ++ show (holes ps) ++ show (getProofTerm (pterm ps))
314−
315−goal :: Hole -> Term -> TC Goal
316−goal h tm = g [] tm where
317− g env (Bind n b@(Guess _ _) sc)
318− | same h n = return $ GD env b
319− | otherwise
320− = gb env b `mplus` g ((n, b):env) sc
321− g env (Bind n b sc) | hole b && same h n = return $ GD env b
322− | otherwise
323− = g ((n, b):env) sc `mplus` gb env b
324− g env (App f a) = g env f `mplus` g env a
325− g env t = fail "Can't find hole"
326−
327− gb env (Let t v) = g env v `mplus` g env t
328− gb env (Guess t v) = g env v `mplus` g env t
329− gb env t = g env (binderTy t)
330
303
331tactic :: Hole -> RunTactic -> StateT TState TC ()
304tactic :: Hole -> RunTactic -> StateT TState TC ()
332tactic h f = do ps <- get
305tactic h f = do ps <- get
333− (tm', _) <- atH (context ps) [] (pterm ps)
306+ (tm', _) <- atHole h f (context ps) [] (pterm ps)
334 ps <- get -- might have changed while processing
307 ps <- get -- might have changed while processing
335 put (ps { pterm = tm' })
308 put (ps { pterm = tm' })
336− where
337− updated o = do o' <- o
338− return (o', True)
339−
340− ulift2 c env op a b
341− = do (b', u) <- atH c env b
342− if u then return (op a b', True)
343− else do (a', u) <- atH c env a
344− return (op a' b', u)
345−
346− -- Search the things most likely to contain the binding first!
347−
348− atH :: Context -> Env -> Term -> StateT TState TC (Term, Bool)
349− atH c env binder@(Bind n b@(Guess t v) sc)
350− | same h n = updated (f c env binder)
351− | otherwise
352− = do -- binder first
353− (b', u) <- ulift2 c env Guess t v
354− if u then return (Bind n b' sc, True)
355− else do (sc', u) <- atH c ((n, b) : env) sc
356− return (Bind n b' sc', u)
357− atH c env binder@(Bind n b sc)
358− | hole b && same h n = updated (f c env binder)
359− | otherwise -- scope first
360− = do (sc', u) <- atH c ((n, b) : env) sc
361− if u then return (Bind n b sc', True)
362− else do (b', u) <- atHb c env b
363− return (Bind n b' sc', u)
364− atH c env (App f a) = ulift2 c env App f a
365− atH c env t = return (t, False)
366−
367− atHb c env (Let t v) = ulift2 c env Let t v
368− atHb c env (Guess t v) = ulift2 c env Guess t v
369− atHb c env t = do (ty', u) <- atH c env (binderTy t)
370− return (t { binderTy = ty' }, u)
371
309
372computeLet :: Context -> Name -> Term -> Term
310computeLet :: Context -> Name -> Term -> Term
373computeLet ctxt n tm = cl [] tm where
311computeLet ctxt n tm = cl [] tm where
@@ -697,13 +635,13 @@ casetac tm induction ctxt env (Bind x (Hole t) (P _ x' _)) | x == x' = do
697 let indxargs = drop (length restargs - length indicies) $ restargs
635 let indxargs = drop (length restargs - length indicies) $ restargs
698 let scr = last $ tail args'
636 let scr = last $ tail args'
699 let indxnames = makeIndexNames indicies
637 let indxnames = makeIndexNames indicies
700− currentNames <- query $ allTTNames . pterm
638+ currentNames <- query $ allTTNames . getProofTerm . pterm
701 let tmnm = case tm of
639 let tmnm = case tm of
702 Var nm -> uniqueNameCtxt ctxt nm currentNames
640 Var nm -> uniqueNameCtxt ctxt nm currentNames
703 _ -> uniqueNameCtxt ctxt (sMN 0 "iv") currentNames
641 _ -> uniqueNameCtxt ctxt (sMN 0 "iv") currentNames
704 let tmvar = P Bound tmnm tmt'
642 let tmvar = P Bound tmnm tmt'
705 prop <- replaceIndicies indxnames indicies $ Bind tmnm (Lam tmt') (mkP tmvar tmv tmvar t)
643 prop <- replaceIndicies indxnames indicies $ Bind tmnm (Lam tmt') (mkP tmvar tmv tmvar t)
706− consargs' <- query (\ps -> map (flip (uniqueNameCtxt (context ps)) (holes ps ++ allTTNames (pterm ps)) *** uniqueBindersCtxt (context ps) (holes ps ++ allTTNames (pterm ps))) consargs)
644+ consargs' <- query (\ps -> map (flip (uniqueNameCtxt (context ps)) (holes ps ++ allTTNames (getProofTerm (pterm ps))) *** uniqueBindersCtxt (context ps) (holes ps ++ allTTNames (getProofTerm (pterm ps)))) consargs)
707 let res = flip (foldr substV) params $ (substV prop $ bindConsArgs consargs' (mkApp (P Ref (SN (tacn tnm)) (TType (UVal 0)))
645 let res = flip (foldr substV) params $ (substV prop $ bindConsArgs consargs' (mkApp (P Ref (SN (tacn tnm)) (TType (UVal 0)))
708 (params ++ [prop] ++ map makeConsArg consargs' ++ indicies ++ [tmv])))
646 (params ++ [prop] ++ map makeConsArg consargs' ++ indicies ++ [tmv])))
709 action (\ps -> ps {holes = holes ps \\ [x]})
647 action (\ps -> ps {holes = holes ps \\ [x]})
@@ -800,7 +738,7 @@ solve_unified ctxt env tm =
800 action (\ps -> ps { holes = traceWhen (unifylog ps) ("Dropping holes " ++ show (map fst unify)) $
738 action (\ps -> ps { holes = traceWhen (unifylog ps) ("Dropping holes " ++ show (map fst unify)) $
801 holes ps \\ map fst unify })
739 holes ps \\ map fst unify })
802 action (\ps -> ps { pterm = updateSolved unify (pterm ps) })
740 action (\ps -> ps { pterm = updateSolved unify (pterm ps) })
803− return (updateSolved unify tm)
741+ return (updateSolvedTerm unify tm)
804
742
805dropGiven du [] hs = []
743dropGiven du [] hs = []
806dropGiven du ((n, P Bound t ty) : us) hs
744dropGiven du ((n, P Bound t ty) : us) hs
@@ -821,26 +759,9 @@ keepGiven du (u@(n, _) : us) hs
821 | n `elem` du = u : keepGiven du us hs
759 | n `elem` du = u : keepGiven du us hs
822keepGiven du (u : us) hs = keepGiven du us hs
760keepGiven du (u : us) hs = keepGiven du us hs
823
761
824−updateSolved :: [(Name, Term)] -> Term -> Term
825−updateSolved xs x = updateSolved' xs x
826−updateSolved' [] x = x
827−updateSolved' xs (Bind n (Hole ty) t)
828− | Just v <- lookup n xs
829− = case xs of
830− [_] -> substV v $ psubst n v t -- some may be Vs! Can't assume
831− -- explicit names
832− _ -> substV v $ psubst n v (updateSolved' xs t)
833−updateSolved' xs (Bind n b t)
834− | otherwise = Bind n (fmap (updateSolved' xs) b) (updateSolved' xs t)
835−updateSolved' xs (App f a)
836− = App (updateSolved' xs f) (updateSolved' xs a)
837−updateSolved' xs (P _ n@(MN _ _) _)
838− | Just v <- lookup n xs = v
839−updateSolved' xs t = t
840−
841updateEnv [] e = e
762updateEnv [] e = e
842updateEnv ns [] = []
763updateEnv ns [] = []
843−updateEnv ns ((n, b) : env) = (n, fmap (updateSolved ns) b) : updateEnv ns env
764+updateEnv ns ((n, b) : env) = (n, fmap (updateSolvedTerm ns) b) : updateEnv ns env
844
765
845updateError [] err = err
766updateError [] err = err
846updateError ns (At f e) = At f (updateError ns e)
767updateError ns (At f e) = At f (updateError ns e)
@@ -848,7 +769,7 @@ updateError ns (Elaborating s n e) = Elaborating s n (updateError ns e)
848updateError ns (ElaboratingArg f a env e)
769updateError ns (ElaboratingArg f a env e)
849 = ElaboratingArg f a env (updateError ns e)
770 = ElaboratingArg f a env (updateError ns e)
850updateError ns (CantUnify b l r e xs sc)
771updateError ns (CantUnify b l r e xs sc)
851− = CantUnify b (updateSolved ns l) (updateSolved ns r) (updateError ns e) xs sc
772+ = CantUnify b (updateSolvedTerm ns l) (updateSolvedTerm ns r) (updateError ns e) xs sc
852updateError ns e = e
773updateError ns e = e
853
774
854solveInProblems x val [] = []
775solveInProblems x val [] = []
@@ -868,7 +789,7 @@ mergeNotunified env ns = mnu ns [] [] where
868updateNotunified [] nu = nu
789updateNotunified [] nu = nu
869updateNotunified ns nu = up nu where
790updateNotunified ns nu = up nu where
870 up [] = []
791 up [] = []
871− up ((n, t) : nus) = let t' = updateSolved ns t in
792+ up ((n, t) : nus) = let t' = updateSolvedTerm ns t in
872 ((n, t') : up nus)
793 ((n, t') : up nus)
873
794
874-- FIXME: Why not just pass the whole proof state?
795-- FIXME: Why not just pass the whole proof state?
@@ -878,8 +799,8 @@ updateProblems :: Context -> [(Name, TT Name)] -> Fails -> [Name] -> [Name] -> [
878updateProblems ctxt ns ps inj holes usupp = up ns ps where
799updateProblems ctxt ns ps inj holes usupp = up ns ps where
879 up ns [] = (ns, [])
800 up ns [] = (ns, [])
880 up ns ((x, y, env, err, while, um) : ps) =
801 up ns ((x, y, env, err, while, um) : ps) =
881− let x' = updateSolved ns x
802+ let x' = updateSolvedTerm ns x
882− y' = updateSolved ns y
803+ y' = updateSolvedTerm ns y
883 err' = updateError ns err
804 err' = updateError ns err
884 env' = updateEnv ns env in
805 env' = updateEnv ns env in
885-- trace ("Updating " ++ show (x',y')) $
806-- trace ("Updating " ++ show (x',y')) $
@@ -895,8 +816,8 @@ matchProblems all ns ctxt ps inj holes = up ns ps where
895 up ns [] = (ns, [])
816 up ns [] = (ns, [])
896 up ns ((x, y, env, err, while, um) : ps)
817 up ns ((x, y, env, err, while, um) : ps)
897 | all || um == Match =
818 | all || um == Match =
898− let x' = updateSolved ns x
819+ let x' = updateSolvedTerm ns x
899− y' = updateSolved ns y
820+ y' = updateSolvedTerm ns y
900 err' = updateError ns err
821 err' = updateError ns err
901 env' = updateEnv ns env in
822 env' = updateEnv ns env in
902 case match_unify ctxt env' x' y' inj holes while of
823 case match_unify ctxt env' x' y' inj holes while of
@@ -909,19 +830,19 @@ matchProblems all ns ctxt ps inj holes = up ns ps where
909
830
910processTactic :: Tactic -> ProofState -> TC (ProofState, String)
831processTactic :: Tactic -> ProofState -> TC (ProofState, String)
911processTactic QED ps = case holes ps of
832processTactic QED ps = case holes ps of
912− [] -> do let tm = {- normalise (context ps) [] -} (pterm ps)
833+ [] -> do let tm = {- normalise (context ps) [] -} getProofTerm (pterm ps)
913 (tm', ty', _) <- recheck (context ps) [] (forget tm) tm
834 (tm', ty', _) <- recheck (context ps) [] (forget tm) tm
914− return (ps { done = True, pterm = tm' },
835+ return (ps { done = True, pterm = mkProofTerm tm' },
915 "Proof complete: " ++ showEnv [] tm')
836 "Proof complete: " ++ showEnv [] tm')
916 _ -> fail "Still holes to fill."
837 _ -> fail "Still holes to fill."
917−processTactic ProofState ps = return (ps, showEnv [] (pterm ps))
838+processTactic ProofState ps = return (ps, showEnv [] (getProofTerm (pterm ps)))
918processTactic Undo ps = case previous ps of
839processTactic Undo ps = case previous ps of
919 Nothing -> Error . Msg $ "Nothing to undo."
840 Nothing -> Error . Msg $ "Nothing to undo."
920 Just pold -> return (pold, "")
841 Just pold -> return (pold, "")
921processTactic EndUnify ps
842processTactic EndUnify ps
922 = let (h, ns_in) = unified ps
843 = let (h, ns_in) = unified ps
923 ns = dropGiven (dontunify ps) ns_in (holes ps)
844 ns = dropGiven (dontunify ps) ns_in (holes ps)
924− ns' = map (\ (n, t) -> (n, updateSolved ns t)) ns
845+ ns' = map (\ (n, t) -> (n, updateSolvedTerm ns t)) ns
925 (ns'', probs') = updateProblems (context ps) ns' (problems ps)
846 (ns'', probs') = updateProblems (context ps) ns' (problems ps)
926 (injective ps) (holes ps)
847 (injective ps) (holes ps)
927 (map fst (notunified ps))
848 (map fst (notunified ps))
@@ -941,7 +862,9 @@ processTactic (Reorder n) ps
941 = do ps' <- execStateT (tactic (Just n) reorder_claims) ps
862 = do ps' <- execStateT (tactic (Just n) reorder_claims) ps
942 return (ps' { previous = Just ps, plog = "" }, plog ps')
863 return (ps' { previous = Just ps, plog = "" }, plog ps')
943processTactic (ComputeLet n) ps
864processTactic (ComputeLet n) ps
865+ = return (ps { pterm = mkProofTerm $
944− = return (ps { pterm = computeLet (context ps) n (pterm ps) }, "")
866+ computeLet (context ps) n
867+ (getProofTerm (pterm ps)) }, "")
945processTactic UnifyProblems ps
868processTactic UnifyProblems ps
946 = let (ns', probs') = updateProblems (context ps) []
869 = let (ns', probs') = updateProblems (context ps) []
947 (problems ps)
870 (problems ps)
src/Idris/Core/ProofTerm.hsnew file+130
@@ -0,0 +1,130 @@
1+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, PatternGuards #-}
2+
3+{- Implements a proof state, some primitive tactics for manipulating
4+ proofs, and some high level commands for introducing new theorems,
5+ evaluation/checking inside the proof system, etc. --}
6+
7+module Idris.Core.ProofTerm(ProofTerm, Goal(..), mkProofTerm, getProofTerm,
8+ updateSolved, updateSolvedTerm,
9+ bound_in, bound_in_term,
10+ Hole, RunTactic',
11+ goal, atHole) where
12+
13+import Idris.Core.Typecheck
14+import Idris.Core.Evaluate
15+import Idris.Core.TT
16+
17+import Control.Monad.State.Strict
18+import Data.List
19+import Debug.Trace
20+
21+newtype ProofTerm = PT Term
22+
23+type RunTactic' a = Context -> Env -> Term -> StateT a TC Term
24+type Hole = Maybe Name -- Nothing = default hole, first in list in proof state
25+
26+data Goal = GD { premises :: Env,
27+ goalType :: Binder Term
28+ }
29+
30+mkProofTerm :: Term -> ProofTerm
31+mkProofTerm tm = PT tm
32+
33+getProofTerm :: ProofTerm -> Term
34+getProofTerm (PT tm) = tm
35+
36+same Nothing n = True
37+same (Just x) n = x == n
38+
39+hole (Hole _) = True
40+hole (Guess _ _) = True
41+hole _ = False
42+
43+updateSolvedTerm :: [(Name, Term)] -> Term -> Term
44+updateSolvedTerm xs x = updateSolved' xs x where
45+ updateSolved' [] x = x
46+ updateSolved' xs (Bind n (Hole ty) t)
47+ | Just v <- lookup n xs
48+ = case xs of
49+ [_] -> substV v $ psubst n v t -- some may be Vs! Can't assume
50+ -- explicit names
51+ _ -> substV v $ psubst n v (updateSolved' xs t)
52+ updateSolved' xs (Bind n b t)
53+ | otherwise = Bind n (fmap (updateSolved' xs) b) (updateSolved' xs t)
54+ updateSolved' xs (App f a)
55+ = App (updateSolved' xs f) (updateSolved' xs a)
56+ updateSolved' xs (P _ n@(MN _ _) _)
57+ | Just v <- lookup n xs = v
58+ updateSolved' xs t = t
59+
60+updateSolved :: [(Name, Term)] -> ProofTerm -> ProofTerm
61+updateSolved xs (PT x) = PT (updateSolvedTerm xs x)
62+
63+goal :: Hole -> ProofTerm -> TC Goal
64+goal h (PT tm) = g [] tm where
65+ g env (Bind n b@(Guess _ _) sc)
66+ | same h n = return $ GD env b
67+ | otherwise
68+ = gb env b `mplus` g ((n, b):env) sc
69+ g env (Bind n b sc) | hole b && same h n = return $ GD env b
70+ | otherwise
71+ = g ((n, b):env) sc `mplus` gb env b
72+ g env (App f a) = g env f `mplus` g env a
73+ g env t = fail "Can't find hole"
74+
75+ gb env (Let t v) = g env v `mplus` g env t
76+ gb env (Guess t v) = g env v `mplus` g env t
77+ gb env t = g env (binderTy t)
78+
79+atHole :: Hole -> RunTactic' a -> Context -> Env -> ProofTerm ->
80+ StateT a TC (ProofTerm, Bool)
81+atHole h f c e (PT t) = do (tm, u) <- atH f c e t
82+ return (PT tm, u)
83+ where
84+ updated o = do o' <- o
85+ return (o', True)
86+
87+ ulift2 f c env op a b
88+ = do (b', u) <- atH f c env b
89+ if u then return (op a b', True)
90+ else do (a', u) <- atH f c env a
91+ return (op a' b', u)
92+
93+ -- Search the things most likely to contain the binding first!
94+
95+ atH :: RunTactic' a -> Context -> Env -> Term -> StateT a TC (Term, Bool)
96+ atH f c env binder@(Bind n b@(Guess t v) sc)
97+ | same h n = updated (f c env binder)
98+ | otherwise
99+ = do -- binder first
100+ (b', u) <- ulift2 f c env Guess t v
101+ if u then return (Bind n b' sc, True)
102+ else do (sc', u) <- atH f c ((n, b) : env) sc
103+ return (Bind n b' sc', u)
104+ atH f c env binder@(Bind n b sc)
105+ | hole b && same h n = updated (f c env binder)
106+ | otherwise -- scope first
107+ = do (sc', u) <- atH f c ((n, b) : env) sc
108+ if u then return (Bind n b sc', True)
109+ else do (b', u) <- atHb f c env b
110+ return (Bind n b' sc', u)
111+ atH tac c env (App f a) = ulift2 tac c env App f a
112+ atH tac c env t = return (t, False)
113+
114+ atHb f c env (Let t v) = ulift2 f c env Let t v
115+ atHb f c env (Guess t v) = ulift2 f c env Guess t v
116+ atHb f c env t = do (ty', u) <- atH f c env (binderTy t)
117+ return (t { binderTy = ty' }, u)
118+
119+bound_in :: ProofTerm -> [Name]
120+bound_in (PT tm) = bound_in_term tm
121+
122+bound_in_term :: Term -> [Name]
123+bound_in_term (Bind n b sc) = n : bi b ++ bound_in_term sc
124+ where
125+ bi (Let t v) = bound_in_term t ++ bound_in_term v
126+ bi (Guess t v) = bound_in_term t ++ bound_in_term v
127+ bi b = bound_in_term (binderTy b)
128+bound_in_term (App f a) = bound_in_term f ++ bound_in_term a
129+bound_in_term _ = []
130+
src/Idris/Core/TT.hs+6
@@ -158,6 +158,12 @@ type Err = Err' Term
158deriving instance NFData Err
158deriving instance NFData Err
159!-}
159!-}
160
160
161+instance Sized ErrorReportPart where
162+ size (TextPart msg) = 1 + length msg
163+ size (TermPart t) = 1 + size t
164+ size (NamePart n) = 1 + size n
165+ size (SubReport rs) = 1 + size rs
166+
161instance Sized Err where
167instance Sized Err where
162 size (Msg msg) = length msg
168 size (Msg msg) = length msg
163 size (InternalMsg msg) = length msg
169 size (InternalMsg msg) = length msg
src/Idris/DeepSeq.hs+8
@@ -260,6 +260,14 @@ instance (NFData t) => NFData (PTactic' t) where
260 rnf (GoalType x1 x2) = rnf x1 `seq` rnf x2 `seq` ()
260 rnf (GoalType x1 x2) = rnf x1 `seq` rnf x2 `seq` ()
261 rnf Qed = ()
261 rnf Qed = ()
262 rnf Abandon = ()
262 rnf Abandon = ()
263+ rnf Skip = ()
264+ rnf (TFail x1) = rnf x1 `seq` ()
265+
266+instance NFData ErrorReportPart where
267+ rnf (TermPart x1) = rnf x1 `seq` ()
268+ rnf (TextPart x1) = rnf x1 `seq` ()
269+ rnf (NamePart x1) = rnf x1 `seq` ()
270+ rnf (SubReport x1) = rnf x1 `seq` ()
263
271
264instance (NFData t) => NFData (PDo' t) where
272instance (NFData t) => NFData (PDo' t) where
265 rnf (DoExp x1 x2) = rnf x1 `seq` rnf x2 `seq` ()
273 rnf (DoExp x1 x2) = rnf x1 `seq` rnf x2 `seq` ()
src/Idris/Elab/Class.hsnew file+226
@@ -0,0 +1,226 @@
1+{-# LANGUAGE PatternGuards #-}
2+module Idris.Elab.Class(elabClass) where
3+
4+import Idris.AbsSyntax
5+import Idris.ASTUtils
6+import Idris.DSL
7+import Idris.Error
8+import Idris.Delaborate
9+import Idris.Imports
10+import Idris.ElabTerm
11+import Idris.Coverage
12+import Idris.DataOpts
13+import Idris.Providers
14+import Idris.Primitives
15+import Idris.Inliner
16+import Idris.PartialEval
17+import Idris.DeepSeq
18+import Idris.Output (iputStrLn, pshow, iWarn)
19+import IRTS.Lang
20+
21+import Idris.Elab.Type
22+import Idris.Elab.Data
23+import Idris.Elab.Utils
24+
25+import Idris.Core.TT
26+import Idris.Core.Elaborate hiding (Tactic(..))
27+import Idris.Core.Evaluate
28+import Idris.Core.Execute
29+import Idris.Core.Typecheck
30+import Idris.Core.CaseTree
31+
32+import Idris.Docstrings
33+
34+import Prelude hiding (id, (.))
35+import Control.Category
36+
37+import Control.Applicative hiding (Const)
38+import Control.DeepSeq
39+import Control.Monad
40+import Control.Monad.State.Strict as State
41+import Data.List
42+import Data.Maybe
43+import Debug.Trace
44+
45+import qualified Data.Map as Map
46+import qualified Data.Set as S
47+import qualified Data.Text as T
48+import Data.Char(isLetter, toLower)
49+import Data.List.Split (splitOn)
50+
51+import Util.Pretty(pretty, text)
52+
53+data MArgTy = IA | EA | CA deriving Show
54+
55+elabClass :: ElabInfo -> SyntaxInfo -> Docstring ->
56+ FC -> [PTerm] ->
57+ Name -> [(Name, PTerm)] -> [(Name, Docstring)] -> [PDecl] -> Idris ()
58+elabClass info syn_in doc fc constraints tn ps pDocs ds
59+ = do let cn = SN (InstanceCtorN tn) -- sUN ("instance" ++ show tn) -- MN 0 ("instance" ++ show tn)
60+ let tty = pibind ps PType
61+ let constraint = PApp fc (PRef fc tn)
62+ (map (pexp . PRef fc) (map fst ps))
63+
64+ let syn = syn_in { using = addToUsing (using syn_in) ps }
65+
66+ -- build data declaration
67+ let mdecls = filter tydecl ds -- method declarations
68+ let idecls = filter instdecl ds -- default superclass instance declarations
69+ mapM_ checkDefaultSuperclassInstance idecls
70+ let mnames = map getMName mdecls
71+ logLvl 2 $ "Building methods " ++ show mnames
72+ ims <- mapM (tdecl mnames) mdecls
73+ defs <- mapM (defdecl (map (\ (x,y,z) -> z) ims) constraint)
74+ (filter clause ds)
75+ let (methods, imethods)
76+ = unzip (map (\ ( x,y,z) -> (x, y)) ims)
77+ let defaults = map (\ (x, (y, z)) -> (x,y)) defs
78+ addClass tn (CI cn (map nodoc imethods) defaults idecls (map fst ps) [])
79+ -- build instance constructor type
80+ -- decorate names of functions to ensure they can't be referred
81+ -- to elsewhere in the class declaration
82+ let cty = impbind ps $ conbind constraints
83+ $ pibind (map (\ (n, ty) -> (nsroot n, ty)) methods)
84+ constraint
85+ let cons = [(emptyDocstring, [], cn, cty, fc, [])]
86+ let ddecl = PDatadecl tn tty cons
87+ logLvl 5 $ "Class data " ++ show (showDImp verbosePPOption ddecl)
88+ elabData info (syn { no_imp = no_imp syn ++ mnames }) doc pDocs fc [] ddecl
89+ -- for each constraint, build a top level function to chase it
90+ logLvl 5 $ "Building functions"
91+-- let usyn = syn { using = map (\ (x,y) -> UImplicit x y) ps
92+-- ++ using syn }
93+ fns <- mapM (cfun cn constraint syn (map fst imethods)) constraints
94+ mapM_ (rec_elabDecl info EAll info) (concat fns)
95+ -- for each method, build a top level function
96+ fns <- mapM (tfun cn constraint syn (map fst imethods)) imethods
97+ mapM_ (rec_elabDecl info EAll info) (concat fns)
98+ -- add the default definitions
99+ mapM_ (rec_elabDecl info EAll info) (concat (map (snd.snd) defs))
100+ addIBC (IBCClass tn)
101+ where
102+ nodoc (n, (_, o, t)) = (n, (o, t))
103+ pibind [] x = x
104+ pibind ((n, ty): ns) x = PPi expl n ty (pibind ns x)
105+
106+ mdec (UN n) = SN (MethodN (UN n))
107+ mdec (NS x n) = NS (mdec x) n
108+ mdec x = x
109+
110+ -- TODO: probably should normalise
111+ checkDefaultSuperclassInstance (PInstance _ fc cs n ps _ _ _)
112+ = do when (not $ null cs) . tclift
113+ $ tfail (At fc (Msg $ "Default superclass instances can't have constraints."))
114+ i <- getIState
115+ let t = PApp fc (PRef fc n) (map pexp ps)
116+ let isConstrained = any (== t) constraints
117+ when (not isConstrained) . tclift
118+ $ tfail (At fc (Msg $ "Default instances must be for a superclass constraint on the containing class."))
119+ return ()
120+
121+ impbind [] x = x
122+ impbind ((n, ty): ns) x = PPi impl n ty (impbind ns x)
123+ conbind (ty : ns) x = PPi constraint (sMN 0 "class") ty (conbind ns x)
124+ conbind [] x = x
125+
126+ getMName (PTy _ _ _ _ _ n _) = nsroot n
127+ tdecl allmeths (PTy doc _ syn _ o n t)
128+ = do t' <- implicit' info syn allmeths n t
129+ logLvl 5 $ "Method " ++ show n ++ " : " ++ showTmImpls t'
130+ return ( (n, (toExp (map fst ps) Exp t')),
131+ (n, (doc, o, (toExp (map fst ps) Imp t'))),
132+ (n, (syn, o, t) ) )
133+ tdecl _ _ = ifail "Not allowed in a class declaration"
134+
135+ -- Create default definitions
136+ defdecl mtys c d@(PClauses fc opts n cs) =
137+ case lookup n mtys of
138+ Just (syn, o, ty) -> do let ty' = insertConstraint c ty
139+ let ds = map (decorateid defaultdec)
140+ [PTy emptyDocstring [] syn fc [] n ty',
141+ PClauses fc (o ++ opts) n cs]
142+ iLOG (show ds)
143+ return (n, ((defaultdec n, ds!!1), ds))
144+ _ -> ifail $ show n ++ " is not a method"
145+ defdecl _ _ _ = ifail "Can't happen (defdecl)"
146+
147+ defaultdec (UN n) = sUN ("default#" ++ str n)
148+ defaultdec (NS n ns) = NS (defaultdec n) ns
149+
150+ tydecl (PTy _ _ _ _ _ _ _) = True
151+ tydecl _ = False
152+ instdecl (PInstance _ _ _ _ _ _ _ _) = True
153+ instdecl _ = False
154+ clause (PClauses _ _ _ _) = True
155+ clause _ = False
156+
157+ -- Generate a function for chasing a dictionary constraint
158+ cfun cn c syn all con
159+ = do let cfn = sUN ('@':'@':show cn ++ "#" ++ show con)
160+ -- SN (ParentN cn (show con))
161+ let mnames = take (length all) $ map (\x -> sMN x "meth") [0..]
162+ let capp = PApp fc (PRef fc cn) (map (pexp . PRef fc) mnames)
163+ let lhs = PApp fc (PRef fc cfn) [pconst capp]
164+ let rhs = PResolveTC (fileFC "HACK")
165+ let ty = PPi constraint (sMN 0 "pc") c con
166+ iLOG (showTmImpls ty)
167+ iLOG (showTmImpls lhs ++ " = " ++ showTmImpls rhs)
168+ i <- getIState
169+ let conn = case con of
170+ PRef _ n -> n
171+ PApp _ (PRef _ n) _ -> n
172+ let conn' = case lookupCtxtName conn (idris_classes i) of
173+ [(n, _)] -> n
174+ _ -> conn
175+ addInstance False conn' cfn
176+ addIBC (IBCInstance False conn' cfn)
177+-- iputStrLn ("Added " ++ show (conn, cfn, ty))
178+ return [PTy emptyDocstring [] syn fc [] cfn ty,
179+ PClauses fc [Dictionary] cfn [PClause fc cfn lhs [] rhs []]]
180+
181+ -- Generate a top level function which looks up a method in a given
182+ -- dictionary (this is inlinable, always)
183+ tfun cn c syn all (m, (doc, o, ty))
184+ = do let ty' = insertConstraint c ty
185+ let mnames = take (length all) $ map (\x -> sMN x "meth") [0..]
186+ let capp = PApp fc (PRef fc cn) (map (pexp . PRef fc) mnames)
187+ let margs = getMArgs ty
188+ let anames = map (\x -> sMN x "arg") [0..]
189+ let lhs = PApp fc (PRef fc m) (pconst capp : lhsArgs margs anames)
190+ let rhs = PApp fc (getMeth mnames all m) (rhsArgs margs anames)
191+ iLOG (showTmImpls ty)
192+ iLOG (show (m, ty', capp, margs))
193+ iLOG (showTmImpls lhs ++ " = " ++ showTmImpls rhs)
194+ return [PTy doc [] syn fc o m ty',
195+ PClauses fc [Inlinable] m [PClause fc m lhs [] rhs []]]
196+
197+ getMArgs (PPi (Imp _ _ _) n ty sc) = IA : getMArgs sc
198+ getMArgs (PPi (Exp _ _ _) n ty sc) = EA : getMArgs sc
199+ getMArgs (PPi (Constraint _ _) n ty sc) = CA : getMArgs sc
200+ getMArgs _ = []
201+
202+ getMeth (m:ms) (a:as) x | x == a = PRef fc m
203+ | otherwise = getMeth ms as x
204+
205+ lhsArgs (EA : xs) (n : ns) = [] -- pexp (PRef fc n) : lhsArgs xs ns
206+ lhsArgs (IA : xs) ns = lhsArgs xs ns
207+ lhsArgs (CA : xs) ns = lhsArgs xs ns
208+ lhsArgs [] _ = []
209+
210+ rhsArgs (EA : xs) (n : ns) = [] -- pexp (PRef fc n) : rhsArgs xs ns
211+ rhsArgs (IA : xs) ns = pexp Placeholder : rhsArgs xs ns
212+ rhsArgs (CA : xs) ns = pconst (PResolveTC fc) : rhsArgs xs ns
213+ rhsArgs [] _ = []
214+
215+ insertConstraint c (PPi p@(Imp _ _ _) n ty sc)
216+ = PPi p n ty (insertConstraint c sc)
217+ insertConstraint c sc = PPi constraint (sMN 0 "class") c sc
218+
219+ -- make arguments explicit and don't bind class parameters
220+ toExp ns e (PPi (Imp l s p) n ty sc)
221+ | n `elem` ns = toExp ns e sc
222+ | otherwise = PPi (e l s p) n ty (toExp ns e sc)
223+ toExp ns e (PPi p n ty sc) = PPi p n ty (toExp ns e sc)
224+ toExp ns e sc = sc
225+
226+
src/Idris/Elab/Clause.hsnew file+877
@@ -0,0 +1,877 @@
1+{-# LANGUAGE PatternGuards #-}
2+module Idris.Elab.Clause where
3+
4+import Idris.AbsSyntax
5+import Idris.ASTUtils
6+import Idris.DSL
7+import Idris.Error
8+import Idris.Delaborate
9+import Idris.Imports
10+import Idris.ElabTerm
11+import Idris.Coverage
12+import Idris.DataOpts
13+import Idris.Providers
14+import Idris.Primitives
15+import Idris.Inliner
16+import Idris.PartialEval
17+import Idris.DeepSeq
18+import Idris.Output (iputStrLn, pshow, iWarn)
19+import IRTS.Lang
20+
21+import Idris.Elab.Type
22+import Idris.Elab.Utils
23+
24+import Idris.Core.TT
25+import Idris.Core.Elaborate hiding (Tactic(..))
26+import Idris.Core.Evaluate
27+import Idris.Core.Execute
28+import Idris.Core.Typecheck
29+import Idris.Core.CaseTree
30+
31+import Idris.Docstrings
32+
33+import Prelude hiding (id, (.))
34+import Control.Category
35+
36+import Control.Applicative hiding (Const)
37+import Control.DeepSeq
38+import Control.Monad
39+import Control.Monad.State.Strict as State
40+import Data.List
41+import Data.Maybe
42+import Debug.Trace
43+
44+import qualified Data.Map as Map
45+import qualified Data.Set as S
46+import qualified Data.Text as T
47+import Data.Char(isLetter, toLower)
48+import Data.List.Split (splitOn)
49+
50+import Util.Pretty(pretty, text)
51+
52+-- | Elaborate a collection of left-hand and right-hand pairs - that is, a
53+-- top-level definition.
54+elabClauses :: ElabInfo -> FC -> FnOpts -> Name -> [PClause] -> Idris ()
55+elabClauses info fc opts n_in cs = let n = liftname info n_in in
56+ do ctxt <- getContext
57+ ist <- getIState
58+ inacc <- map fst <$> fgetState (opt_inaccessible . ist_optimisation n)
59+
60+ -- Check n actually exists, with no definition yet
61+ let tys = lookupTy n ctxt
62+ let reflect = Reflection `elem` opts
63+ checkUndefined n ctxt
64+ unless (length tys > 1) $ do
65+ fty <- case tys of
66+ [] -> -- TODO: turn into a CAF if there's no arguments
67+ -- question: CAFs in where blocks?
68+ tclift $ tfail $ At fc (NoTypeDecl n)
69+ [ty] -> return ty
70+ let atys = map snd (getArgTys fty)
71+ cs_elab <- mapM (elabClause info opts)
72+ (zip [0..] cs)
73+ let (pats_in, cs_full) = unzip cs_elab
74+
75+ logLvl 3 $ "Elaborated patterns:\n" ++ show pats_in
76+
77+ solveDeferred n
78+
79+ -- just ensure that the structure exists
80+ fmodifyState (ist_optimisation n) id
81+ addIBC (IBCOpt n)
82+
83+ ist <- getIState
84+ let pats = map (simple_lhs (tt_ctxt ist)) $ doTransforms ist pats_in
85+
86+ -- logLvl 3 (showSep "\n" (map (\ (l,r) ->
87+ -- show l ++ " = " ++
88+ -- show r) pats))
89+ let tcase = opt_typecase (idris_options ist)
90+
91+ -- Summary of what's about to happen: Definitions go:
92+ --
93+ -- pats_in -> pats -> pdef -> pdef'
94+
95+ -- addCaseDef builds case trees from <pdef> and <pdef'>
96+
97+ -- pdef is the compile-time pattern definition.
98+ -- This will get further optimised for run-time, and, separately,
99+ -- further inlined to help with totality checking.
100+ let pdef = map debind pats
101+
102+ logLvl 5 $ "Initial typechecked patterns:\n" ++ show pats
103+ logLvl 5 $ "Initial typechecked pattern def:\n" ++ show pdef
104+
105+ -- Look for 'static' names and generate new specialised
106+ -- definitions for them
107+
108+ mapM_ (\ e -> case e of
109+ Left _ -> return ()
110+ Right (l, r) -> elabPE info fc n r) pats
111+
112+ -- NOTE: Need to store original definition so that proofs which
113+ -- rely on its structure aren't affected by any changes to the
114+ -- inliner. Just use the inlined version to generate pdef' and to
115+ -- help with later inlinings.
116+
117+ ist <- getIState
118+ let pdef_inl = inlineDef ist pdef
119+
120+ numArgs <- tclift $ sameLength pdef
121+
122+ case specNames opts of
123+ Just _ -> logLvl 5 $ "Partially evaluated:\n" ++ show pats
124+ _ -> return ()
125+
126+ erInfo <- getErasureInfo <$> getIState
127+ tree@(CaseDef scargs sc _) <- tclift $
128+ simpleCase tcase False reflect CompileTime fc inacc atys pdef erInfo
129+ cov <- coverage
130+ pmissing <-
131+ if cov && not (hasDefault cs)
132+ then do missing <- genClauses fc n (map getLHS pdef) cs_full
133+ -- missing <- genMissing n scargs sc
134+ missing' <- filterM (checkPossible info fc True n) missing
135+ let clhs = map getLHS pdef
136+ logLvl 2 $ "Must be unreachable:\n" ++
137+ showSep "\n" (map showTmImpls missing') ++
138+ "\nAgainst: " ++
139+ showSep "\n" (map (\t -> showTmImpls (delab ist t)) (map getLHS pdef))
140+ -- filter out anything in missing' which is
141+ -- matched by any of clhs. This might happen since
142+ -- unification may force a variable to take a
143+ -- particular form, rather than force a case
144+ -- to be impossible.
145+ return (filter (noMatch ist clhs) missing')
146+ else return []
147+ let pcover = null pmissing
148+
149+ -- pdef' is the version that gets compiled for run-time
150+ pdef_in' <- applyOpts pdef
151+ let pdef' = map (simple_rt (tt_ctxt ist)) pdef_in'
152+
153+ logLvl 5 $ "After data structure transformations:\n" ++ show pdef'
154+
155+ ist <- getIState
156+ -- let wf = wellFounded ist n sc
157+ let tot = if pcover || AssertTotal `elem` opts
158+ then Unchecked -- finish checking later
159+ else Partial NotCovering -- already know it's not total
160+
161+ -- case lookupCtxt (namespace info) n (idris_flags ist) of
162+ -- [fs] -> if TotalFn `elem` fs
163+ -- then case tot of
164+ -- Total _ -> return ()
165+ -- t -> tclift $ tfail (At fc (Msg (show n ++ " is " ++ show t)))
166+ -- else return ()
167+ -- _ -> return ()
168+ case tree of
169+ CaseDef _ _ [] -> return ()
170+ CaseDef _ _ xs -> mapM_ (\x ->
171+ iputStrLn $ show fc ++
172+ ":warning - Unreachable case: " ++
173+ show (delab ist x)) xs
174+ let knowncovering = (pcover && cov) || AssertTotal `elem` opts
175+
176+ tree' <- tclift $ simpleCase tcase knowncovering reflect
177+ RunTime fc inacc atys pdef' erInfo
178+ logLvl 3 $ "Unoptimised " ++ show n ++ ": " ++ show tree
179+ logLvl 3 $ "Optimised: " ++ show tree'
180+ ctxt <- getContext
181+ ist <- getIState
182+ let opt = idris_optimisation ist
183+ putIState (ist { idris_patdefs = addDef n (force pdef', force pmissing)
184+ (idris_patdefs ist) })
185+ let caseInfo = CaseInfo (inlinable opts) (dictionary opts)
186+ case lookupTy n ctxt of
187+ [ty] -> do updateContext (addCasedef n erInfo caseInfo
188+ tcase knowncovering
189+ reflect
190+ (AssertTotal `elem` opts)
191+ atys
192+ inacc
193+ pats
194+ pdef pdef pdef_inl pdef' ty)
195+ addIBC (IBCDef n)
196+ setTotality n tot
197+ when (not reflect) $ do totcheck (fc, n)
198+ defer_totcheck (fc, n)
199+ when (tot /= Unchecked) $ addIBC (IBCTotal n tot)
200+ i <- getIState
201+ case lookupDef n (tt_ctxt i) of
202+ (CaseOp _ _ _ _ _ cd : _) ->
203+ let (scargs, sc) = cases_compiletime cd
204+ (scargs', sc') = cases_runtime cd in
205+ do let calls = findCalls sc' scargs'
206+ let used = findUsedArgs sc' scargs'
207+ -- let scg = buildSCG i sc scargs
208+ -- add SCG later, when checking totality
209+ let cg = CGInfo scargs' calls [] used [] -- TODO: remove this, not needed anymore
210+ logLvl 2 $ "Called names: " ++ show cg
211+ addToCG n cg
212+ addToCalledG n (nub (map fst calls)) -- plus names in type!
213+ addIBC (IBCCG n)
214+ _ -> return ()
215+ return ()
216+ -- addIBC (IBCTotal n tot)
217+ [] -> return ()
218+ -- Check it's covering, if 'covering' option is used. Chase
219+ -- all called functions, and fail if any of them are also
220+ -- 'Partial NotCovering'
221+ when (CoveringFn `elem` opts) $ checkAllCovering fc [] n n
222+ where
223+ noMatch i cs tm = all (\x -> case matchClause i (delab' i x True True) tm of
224+ Right _ -> False
225+ Left miss -> True) cs
226+
227+ checkUndefined n ctxt = case lookupDef n ctxt of
228+ [] -> return ()
229+ [TyDecl _ _] -> return ()
230+ _ -> tclift $ tfail (At fc (AlreadyDefined n))
231+
232+ debind (Right (x, y)) = let (vs, x') = depat [] x
233+ (_, y') = depat [] y in
234+ (vs, x', y')
235+ debind (Left x) = let (vs, x') = depat [] x in
236+ (vs, x', Impossible)
237+
238+ depat acc (Bind n (PVar t) sc) = depat (n : acc) (instantiate (P Bound n t) sc)
239+ depat acc x = (acc, x)
240+
241+ hasDefault cs | (PClause _ _ last _ _ _ :_) <- reverse cs
242+ , (PApp fn s args) <- last = all ((==Placeholder) . getTm) args
243+ hasDefault _ = False
244+
245+ getLHS (_, l, _) = l
246+
247+ simple_lhs ctxt (Right (x, y)) = Right (normalise ctxt [] x,
248+ force (normalisePats ctxt [] y))
249+ simple_lhs ctxt t = t
250+
251+ simple_rt ctxt (p, x, y) = (p, x, force (uniqueBinders p
252+ (rt_simplify ctxt [] y)))
253+
254+ -- this is so pattern types are in the right form for erasure
255+ normalisePats ctxt env (Bind n (PVar t) sc)
256+ = let t' = normalise ctxt env t in
257+ Bind n (PVar t') (normalisePats ctxt ((n, PVar t') : env) sc)
258+ normalisePats ctxt env (Bind n (PVTy t) sc)
259+ = let t' = normalise ctxt env t in
260+ Bind n (PVTy t') (normalisePats ctxt ((n, PVar t') : env) sc)
261+ normalisePats ctxt env t = t
262+
263+ specNames [] = Nothing
264+ specNames (Specialise ns : _) = Just ns
265+ specNames (_ : xs) = specNames xs
266+
267+ sameLength ((_, x, _) : xs)
268+ = do l <- sameLength xs
269+ let (f, as) = unApply x
270+ if (null xs || l == length as) then return (length as)
271+ else tfail (At fc (Msg "Clauses have differing numbers of arguments "))
272+ sameLength [] = return 0
273+
274+ -- apply all transformations (just specialisation for now, add
275+ -- user defined transformation rules later)
276+ doTransforms ist pats =
277+ case specNames opts of
278+ Nothing -> pats
279+ Just ns -> partial_eval (tt_ctxt ist) ns pats
280+
281+-- | Find 'static' applications in a term and partially evaluate them
282+elabPE :: ElabInfo -> FC -> Name -> Term -> Idris ()
283+elabPE info fc caller r =
284+ do ist <- getIState
285+ let sa = getSpecApps ist [] r
286+ mapM_ (mkSpecialised ist) sa
287+ where
288+ -- TODO: Add a PTerm level transformation rule, which is basically the
289+ -- new definition in reverse (before specialising it).
290+ -- RHS => LHS where implicit arguments are left blank in the
291+ -- transformation.
292+
293+ -- Apply that transformation after every PClauses elaboration
294+
295+ mkSpecialised ist specapp_in = do
296+ let (specTy, specapp) = getSpecTy ist specapp_in
297+ let (n, newnm, pats) = getSpecClause ist specapp
298+ let undef = case lookupDef newnm (tt_ctxt ist) of
299+ [] -> True
300+ _ -> False
301+ logLvl 5 $ show (newnm, map (concreteArg ist) (snd specapp))
302+ idrisCatch
303+ (when (undef && all (concreteArg ist) (snd specapp)) $ do
304+ cgns <- getAllNames n
305+ let opts = [Specialise (map (\x -> (x, Nothing)) cgns ++
306+ mapMaybe specName (snd specapp))]
307+ logLvl 3 $ "Specialising application: " ++ show specapp
308+ logLvl 2 $ "New name: " ++ show newnm
309+ iLOG $ "PE definition type : " ++ (show specTy)
310+ ++ "\n" ++ show opts
311+ logLvl 2 $ "PE definition " ++ show newnm ++ ":\n" ++
312+ showSep "\n"
313+ (map (\ (lhs, rhs) ->
314+ (showTmImpls lhs ++ " = " ++
315+ showTmImpls rhs)) pats)
316+ elabType info defaultSyntax emptyDocstring [] fc opts newnm specTy
317+ let def = map (\ (lhs, rhs) -> PClause fc newnm lhs [] rhs []) pats
318+ elabClauses info fc opts newnm def
319+ logLvl 2 $ "Specialised " ++ show newnm)
320+ -- if it doesn't work, just don't specialise. Could happen for lots
321+ -- of valid reasons (e.g. local variables in scope which can't be
322+ -- lifted out).
323+ (\e -> logLvl 4 $ "Couldn't specialise: " ++ (pshow ist e))
324+
325+ specName (ImplicitS, tm)
326+ | (P Ref n _, _) <- unApply tm = Just (n, Just 1)
327+ specName (ExplicitS, tm)
328+ | (P Ref n _, _) <- unApply tm = Just (n, Just 1)
329+ specName _ = Nothing
330+
331+ concreteArg ist (ImplicitS, tm) = concreteTm ist tm
332+ concreteArg ist (ExplicitS, tm) = concreteTm ist tm
333+ concreteArg ist _ = True
334+
335+ concreteTm ist tm | (P _ n _, _) <- unApply tm =
336+ case lookupTy n (tt_ctxt ist) of
337+ [] -> False
338+ _ -> True
339+ concreteTm ist (Constant _) = True
340+ concreteTm ist _ = False
341+
342+ -- get the type of a specialised application
343+ getSpecTy ist (n, args)
344+ = case lookupTy n (tt_ctxt ist) of
345+ [ty] -> let (specty_in, args') = specType args (explicitNames ty)
346+ specty = normalise (tt_ctxt ist) [] (finalise specty_in)
347+ t = mkPE_TyDecl ist args' (explicitNames specty) in
348+ (t, (n, args'))
349+-- (normalise (tt_ctxt ist) [] (specType args ty))
350+ _ -> error "Can't happen (getSpecTy)"
351+
352+ -- get the clause of a specialised application
353+ getSpecClause ist (n, args)
354+ = let newnm = sUN ("__"++show (nsroot n) ++ "_" ++
355+ showSep "_" (map showArg args)) in
356+ -- UN (show n ++ show (map snd args)) in
357+ (n, newnm, mkPE_TermDecl ist newnm n args)
358+ where showArg (ExplicitS, n) = show n
359+ showArg (ImplicitS, n) = show n
360+ showArg _ = ""
361+
362+-- checks if the clause is a possible left hand side. Returns the term if
363+-- possible, otherwise Nothing.
364+
365+checkPossible :: ElabInfo -> FC -> Bool -> Name -> PTerm -> Idris Bool
366+checkPossible info fc tcgen fname lhs_in
367+ = do ctxt <- getContext
368+ i <- getIState
369+ let lhs = addImplPat i lhs_in
370+ -- if the LHS type checks, it is possible
371+ case elaborate ctxt (sMN 0 "patLHS") infP []
372+ (erun fc (buildTC i info ELHS [] fname (infTerm lhs))) of
373+ OK ((lhs', _, _), _) ->
374+ do let lhs_tm = orderPats (getInferTerm lhs')
375+ case recheck ctxt [] (forget lhs_tm) lhs_tm of
376+ OK _ -> return True
377+ err -> return False
378+ -- if it's a recoverable error, the case may become possible
379+ Error err -> if tcgen then return (recoverable ctxt err)
380+ else return (validCase ctxt err ||
381+ recoverable ctxt err)
382+ where validCase ctxt (CantUnify _ topx topy e _ _)
383+ = let topx' = normalise ctxt [] topx
384+ topy' = normalise ctxt [] topy in
385+ not (sameFam topx' topy' || not (validCase ctxt e))
386+ validCase ctxt (CantConvert _ _ _) = False
387+ validCase ctxt (At _ e) = validCase ctxt e
388+ validCase ctxt (Elaborating _ _ e) = validCase ctxt e
389+ validCase ctxt (ElaboratingArg _ _ _ e) = validCase ctxt e
390+ validCase ctxt _ = True
391+
392+ recoverable ctxt (CantUnify r topx topy e _ _)
393+ = let topx' = normalise ctxt [] topx
394+ topy' = normalise ctxt [] topy in
395+ checkRec topx' topy'
396+ recoverable ctxt (At _ e) = recoverable ctxt e
397+ recoverable ctxt (Elaborating _ _ e) = recoverable ctxt e
398+ recoverable ctxt (ElaboratingArg _ _ _ e) = recoverable ctxt e
399+ recoverable _ _ = False
400+
401+ sameFam topx topy
402+ = case (unApply topx, unApply topy) of
403+ ((P _ x _, _), (P _ y _, _)) -> x == y
404+ _ -> False
405+
406+ -- different notion of recoverable than in unification, since we
407+ -- have no metavars -- just looking to see if a constructor is failing
408+ -- to unify with a function that may be reduced later
409+
410+ checkRec (App f a) p@(P _ _ _) = checkRec f p
411+ checkRec p@(P _ _ _) (App f a) = checkRec p f
412+ checkRec fa@(App _ _) fa'@(App _ _)
413+ | (f, as) <- unApply fa,
414+ (f', as') <- unApply fa'
415+ = if (length as /= length as')
416+ then checkRec f f'
417+ else checkRec f f' && and (zipWith checkRec as as')
418+ checkRec (P xt x _) (P yt y _) = x == y || ntRec xt yt
419+ checkRec _ _ = False
420+
421+ ntRec x y | Ref <- x = True
422+ | Ref <- y = True
423+ | otherwise = False -- name is different, unrecoverable
424+
425+getFixedInType i env (PExp _ _ _ _ : is) (Bind n (Pi t) sc)
426+ = nub $ getFixedInType i env [] t ++
427+ getFixedInType i (n : env) is (instantiate (P Bound n t) sc)
428+getFixedInType i env (_ : is) (Bind n (Pi t) sc)
429+ = getFixedInType i (n : env) is (instantiate (P Bound n t) sc)
430+getFixedInType i env is tm@(App f a)
431+ | (P _ tn _, args) <- unApply tm
432+ = case lookupCtxt tn (idris_datatypes i) of
433+ [t] -> nub $ paramNames args env (param_pos t) ++
434+ getFixedInType i env is f ++
435+ getFixedInType i env is a
436+ [] -> nub $ getFixedInType i env is f ++
437+ getFixedInType i env is a
438+ | otherwise = nub $ getFixedInType i env is f ++
439+ getFixedInType i env is a
440+getFixedInType i _ _ _ = []
441+
442+getFlexInType i env ps (Bind n (Pi t) sc)
443+ = nub $ (if (not (n `elem` ps)) then getFlexInType i env ps t else []) ++
444+ getFlexInType i (n : env) ps (instantiate (P Bound n t) sc)
445+getFlexInType i env ps tm@(App f a)
446+ | (P _ tn _, args) <- unApply tm
447+ = case lookupCtxt tn (idris_datatypes i) of
448+ [t] -> nub $ paramNames args env [x | x <- [0..length args],
449+ not (x `elem` param_pos t)]
450+ ++ getFlexInType i env ps f ++
451+ getFlexInType i env ps a
452+ [] -> nub $ getFlexInType i env ps f ++
453+ getFlexInType i env ps a
454+ | otherwise = nub $ getFlexInType i env ps f ++
455+ getFlexInType i env ps a
456+getFlexInType i _ _ _ = []
457+
458+-- Treat a name as a parameter if it appears in parameter positions in
459+-- types, and never in a non-parameter position in a (non-param) argument type.
460+
461+getParamsInType i env ps t = let fix = getFixedInType i env ps t
462+ flex = getFlexInType i env fix t in
463+ [x | x <- fix, not (x `elem` flex)]
464+
465+paramNames args env [] = []
466+paramNames args env (p : ps)
467+ | length args > p = case args!!p of
468+ P _ n _ -> if n `elem` env
469+ then n : paramNames args env ps
470+ else paramNames args env ps
471+ _ -> paramNames args env ps
472+ | otherwise = paramNames args env ps
473+
474+propagateParams :: IState -> [Name] -> Type -> PTerm -> PTerm
475+propagateParams i ps t tm@(PApp _ (PRef fc n) args)
476+ = PApp fc (PRef fc n) (addP t args)
477+ where addP (Bind n _ sc) (t : ts)
478+ | Placeholder <- getTm t,
479+ n `elem` ps,
480+ not (n `elem` allNamesIn tm)
481+ = t { getTm = PRef fc n } : addP sc ts
482+ addP (Bind n _ sc) (t : ts) = t : addP sc ts
483+ addP _ ts = ts
484+propagateParams i ps t (PRef fc n)
485+ = case lookupCtxt n (idris_implicits i) of
486+ [is] -> let ps' = filter (isImplicit is) ps in
487+ PApp fc (PRef fc n) (map (\x -> pimp x (PRef fc x) True) ps')
488+ _ -> PRef fc n
489+ where isImplicit [] n = False
490+ isImplicit (PImp _ _ _ x _ : is) n | x == n = True
491+ isImplicit (_ : is) n = isImplicit is n
492+propagateParams i ps t x = x
493+
494+-- Return the elaborated LHS/RHS, and the original LHS with implicits added
495+elabClause :: ElabInfo -> FnOpts -> (Int, PClause) ->
496+ Idris (Either Term (Term, Term), PTerm)
497+elabClause info opts (_, PClause fc fname lhs_in [] PImpossible [])
498+ = do let tcgen = Dictionary `elem` opts
499+ i <- get
500+ let lhs = addImpl i lhs_in
501+ b <- checkPossible info fc tcgen fname lhs_in
502+ case b of
503+ True -> tclift $ tfail (At fc
504+ (Msg $ show lhs_in ++ " is a valid case"))
505+ False -> do ptm <- mkPatTm lhs_in
506+ return (Left ptm, lhs)
507+elabClause info opts (cnum, PClause fc fname lhs_in withs rhs_in whereblock)
508+ = do let tcgen = Dictionary `elem` opts
509+ ctxt <- getContext
510+
511+ -- Build the LHS as an "Infer", and pull out its type and
512+ -- pattern bindings
513+ i <- getIState
514+ inf <- isTyInferred fname
515+ -- get the parameters first, to pass through to any where block
516+ let fn_ty = case lookupTy fname (tt_ctxt i) of
517+ [t] -> t
518+ _ -> error "Can't happen (elabClause function type)"
519+ let fn_is = case lookupCtxt fname (idris_implicits i) of
520+ [t] -> t
521+ _ -> []
522+ let params = getParamsInType i [] fn_is fn_ty
523+ let lhs = mkLHSapp $ stripUnmatchable i $
524+ propagateParams i params fn_ty (addImplPat i (stripLinear i lhs_in))
525+ logLvl 5 ("LHS: " ++ show fc ++ " " ++ showTmImpls lhs)
526+ logLvl 4 ("Fixed parameters: " ++ show params ++ " from " ++ show lhs_in ++
527+ "\n" ++ show (fn_ty, fn_is))
528+
529+ (((lhs', dlhs, []), probs, inj), _) <-
530+ tclift $ elaborate ctxt (sMN 0 "patLHS") infP []
531+ (do res <- errAt "left hand side of " fname
532+ (erun fc (buildTC i info ELHS opts fname (infTerm lhs)))
533+ probs <- get_probs
534+ inj <- get_inj
535+ return (res, probs, inj))
536+
537+ when inf $ addTyInfConstraints fc (map (\(x,y,_,_,_,_) -> (x,y)) probs)
538+
539+ let lhs_tm = orderPats (getInferTerm lhs')
540+ let lhs_ty = getInferType lhs'
541+ logLvl 3 ("Elaborated: " ++ show lhs_tm)
542+ logLvl 3 ("Elaborated type: " ++ show lhs_ty)
543+ logLvl 5 ("Injective: " ++ show fname ++ " " ++ show inj)
544+
545+ -- If we're inferring metavariables in the type, don't recheck,
546+ -- because we're only doing this to try to work out those metavariables
547+ (clhs_c, clhsty) <- if not inf
548+ then recheckC fc [] lhs_tm
549+ else return (lhs_tm, lhs_ty)
550+ let clhs = normalise ctxt [] clhs_c
551+
552+ logLvl 3 ("Normalised LHS: " ++ showTmImpls (delabMV i clhs))
553+
554+ rep <- useREPL
555+ when rep $ do
556+ addInternalApp (fc_fname fc) (fst . fc_start $ fc) (delabMV i clhs) -- TODO: Should use span instead of line and filename?
557+ addIBC (IBCLineApp (fc_fname fc) (fst . fc_start $ fc) (delabMV i clhs))
558+
559+ logLvl 5 ("Checked " ++ show clhs ++ "\n" ++ show clhsty)
560+ -- Elaborate where block
561+ ist <- getIState
562+ windex <- getName
563+ let decls = nub (concatMap declared whereblock)
564+ let defs = nub (decls ++ concatMap defined whereblock)
565+ let newargs = pvars ist lhs_tm
566+ let winfo = pinfo info newargs defs windex
567+ let wb = map (expandParamsD False ist decorate newargs defs) whereblock
568+
569+ -- Split the where block into declarations with a type, and those
570+ -- without
571+ -- Elaborate those with a type *before* RHS, those without *after*
572+ let (wbefore, wafter) = sepBlocks wb
573+
574+ logLvl 2 $ "Where block:\n " ++ show wbefore ++ "\n" ++ show wafter
575+ mapM_ (rec_elabDecl info EAll winfo) wbefore
576+ -- Now build the RHS, using the type of the LHS as the goal.
577+ i <- getIState -- new implicits from where block
578+ logLvl 5 (showTmImpls (expandParams decorate newargs defs (defs \\ decls) rhs_in))
579+ let rhs = addImplBoundInf i (map fst newargs) (defs \\ decls)
580+ (expandParams decorate newargs defs (defs \\ decls) rhs_in)
581+ logLvl 2 $ "RHS: " ++ showTmImpls rhs
582+ ctxt <- getContext -- new context with where block added
583+ logLvl 5 "STARTING CHECK"
584+ ((rhs', defer, is, probs), _) <-
585+ tclift $ elaborate ctxt (sMN 0 "patRHS") clhsty []
586+ (do pbinds ist lhs_tm
587+ mapM_ setinj (nub (params ++ inj))
588+ setNextName
589+ (_, _, is) <- errAt "right hand side of " fname
590+ (erun fc (build i winfo ERHS opts fname rhs))
591+ errAt "right hand side of " fname
592+ (erun fc $ psolve lhs_tm)
593+ hs <- get_holes
594+ aux <- getAux
595+ mapM_ (elabCaseHole aux) hs
596+ tt <- get_term
597+ let (tm, ds) = runState (collectDeferred (Just fname) tt) []
598+ probs <- get_probs
599+ return (tm, ds, is, probs))
600+
601+ when inf $ addTyInfConstraints fc (map (\(x,y,_,_,_,_) -> (x,y)) probs)
602+
603+ logLvl 5 "DONE CHECK"
604+ logLvl 2 $ "---> " ++ show rhs'
605+ when (not (null defer)) $ iLOG $ "DEFERRED " ++
606+ show (map (\ (n, (_,_,t)) -> (n, t)) defer)
607+ def' <- checkDef fc defer
608+ let def'' = map (\(n, (i, top, t)) -> (n, (i, top, t, False))) def'
609+ addDeferred def''
610+ mapM_ (\(n, _) -> addIBC (IBCDef n)) def''
611+
612+ when (not (null def')) $ do
613+ mapM_ defer_totcheck (map (\x -> (fc, fst x)) def'')
614+
615+ -- Now the remaining deferred (i.e. no type declarations) clauses
616+ -- from the where block
617+
618+ mapM_ (rec_elabDecl info EAll winfo) wafter
619+ mapM_ (elabCaseBlock winfo opts) is
620+
621+ ctxt <- getContext
622+ logLvl 5 $ "Rechecking"
623+ logLvl 6 $ " ==> " ++ show (forget rhs')
624+ (crhs, crhsty) <- if not inf
625+ then recheckC fc [] rhs'
626+ else return (rhs', clhsty)
627+ logLvl 6 $ " ==> " ++ show crhsty ++ " against " ++ show clhsty
628+ case converts ctxt [] clhsty crhsty of
629+ OK _ -> return ()
630+ Error e -> ierror (At fc (CantUnify False clhsty crhsty e [] 0))
631+ i <- getIState
632+ checkInferred fc (delab' i crhs True True) rhs
633+ -- if the function is declared '%error_reverse', or its type,
634+ -- then we'll try running it in reverse to improve error messages
635+ let (ret_fam, _) = unApply (getRetTy crhsty)
636+ rev <- case ret_fam of
637+ P _ rfamn _ ->
638+ case lookupCtxt rfamn (idris_datatypes i) of
639+ [TI _ _ dopts _ _] ->
640+ return (DataErrRev `elem` dopts)
641+ _ -> return False
642+ _ -> return False
643+
644+ when (rev || ErrorReverse `elem` opts) $ do
645+ addIBC (IBCErrRev (crhs, clhs))
646+ addErrRev (crhs, clhs)
647+ return $ (Right (clhs, crhs), lhs)
648+ where
649+ pinfo :: ElabInfo -> [(Name, PTerm)] -> [Name] -> Int -> ElabInfo
650+ pinfo info ns ds i
651+ = let newps = params info ++ ns
652+ dsParams = map (\n -> (n, map fst newps)) ds
653+ newb = addAlist dsParams (inblock info)
654+ l = liftname info in
655+ info { params = newps,
656+ inblock = newb,
657+ liftname = id -- (\n -> case lookupCtxt n newb of
658+ -- Nothing -> n
659+ -- _ -> MN i (show n)) . l
660+ }
661+
662+ mkLHSapp t@(PRef _ _) = trace ("APP " ++ show t) $ PApp fc t []
663+ mkLHSapp t = t
664+
665+ decorate (NS x ns)
666+ = NS (SN (WhereN cnum fname x)) ns -- ++ [show cnum])
667+-- = NS (UN ('#':show x)) (ns ++ [show cnum, show fname])
668+ decorate x
669+ = SN (WhereN cnum fname x)
670+-- = NS (SN (WhereN cnum fname x)) [show cnum]
671+-- = NS (UN ('#':show x)) [show cnum, show fname]
672+
673+ sepBlocks bs = sepBlocks' [] bs where
674+ sepBlocks' ns (d@(PTy _ _ _ _ _ n t) : bs)
675+ = let (bf, af) = sepBlocks' (n : ns) bs in
676+ (d : bf, af)
677+ sepBlocks' ns (d@(PClauses _ _ n _) : bs)
678+ | not (n `elem` ns) = let (bf, af) = sepBlocks' ns bs in
679+ (bf, d : af)
680+ sepBlocks' ns (b : bs) = let (bf, af) = sepBlocks' ns bs in
681+ (b : bf, af)
682+ sepBlocks' ns [] = ([], [])
683+
684+
685+ -- if a hole is just an argument/result of a case block, treat it as
686+ -- the unit type. Hack to help elaborate case in do blocks.
687+ elabCaseHole aux h = do
688+ focus h
689+ g <- goal
690+ case g of
691+ TType _ -> when (any (isArg h) aux) $ do apply (Var unitTy) []; solve
692+ _ -> return ()
693+
694+ -- Is the name a pattern argument in the declaration
695+ isArg :: Name -> PDecl -> Bool
696+ isArg n (PClauses _ _ _ cs) = any isArg' cs
697+ where
698+ isArg' (PClause _ _ (PApp _ _ args) _ _ _)
699+ = any (\x -> case x of
700+ PRef _ n' -> n == n'
701+ _ -> False) (map getTm args)
702+ isArg' _ = False
703+ isArg _ _ = False
704+
705+elabClause info opts (_, PWith fc fname lhs_in withs wval_in withblock)
706+ = do let tcgen = Dictionary `elem` opts
707+ ctxt <- getContext
708+ -- Build the LHS as an "Infer", and pull out its type and
709+ -- pattern bindings
710+ i <- getIState
711+ -- get the parameters first, to pass through to any where block
712+ let fn_ty = case lookupTy fname (tt_ctxt i) of
713+ [t] -> t
714+ _ -> error "Can't happen (elabClause function type)"
715+ let fn_is = case lookupCtxt fname (idris_implicits i) of
716+ [t] -> t
717+ _ -> []
718+ let params = getParamsInType i [] fn_is fn_ty
719+ let lhs = propagateParams i params fn_ty (addImplPat i (stripLinear i lhs_in))
720+ logLvl 2 ("LHS: " ++ show lhs)
721+ ((lhs', dlhs, []), _) <-
722+ tclift $ elaborate ctxt (sMN 0 "patLHS") infP []
723+ (errAt "left hand side of with in " fname
724+ (erun fc (buildTC i info ELHS opts fname (infTerm lhs))) )
725+ let lhs_tm = orderPats (getInferTerm lhs')
726+ let lhs_ty = getInferType lhs'
727+ let ret_ty = getRetTy (explicitNames (normalise ctxt [] lhs_ty))
728+ logLvl 3 (show lhs_tm)
729+ (clhs, clhsty) <- recheckC fc [] lhs_tm
730+ logLvl 5 ("Checked " ++ show clhs)
731+ let bargs = getPBtys (explicitNames (normalise ctxt [] lhs_tm))
732+ let wval = addImplBound i (map fst bargs) wval_in
733+ logLvl 5 ("Checking " ++ showTmImpls wval)
734+ -- Elaborate wval in this context
735+ ((wval', defer, is), _) <-
736+ tclift $ elaborate ctxt (sMN 0 "withRHS")
737+ (bindTyArgs PVTy bargs infP) []
738+ (do pbinds i lhs_tm
739+ setNextName
740+ -- TODO: may want where here - see winfo abpve
741+ (_', d, is) <- errAt "with value in " fname
742+ (erun fc (build i info ERHS opts fname (infTerm wval)))
743+ erun fc $ psolve lhs_tm
744+ tt <- get_term
745+ return (tt, d, is))
746+ def' <- checkDef fc defer
747+ let def'' = map (\(n, (i, top, t)) -> (n, (i, top, t, False))) def'
748+ addDeferred def''
749+ mapM_ (elabCaseBlock info opts) is
750+ logLvl 5 ("Checked wval " ++ show wval')
751+ (cwval, cwvalty) <- recheckC fc [] (getInferTerm wval')
752+ let cwvaltyN = explicitNames (normalise ctxt [] cwvalty)
753+ let cwvalN = explicitNames (normalise ctxt [] cwval)
754+ logLvl 5 ("With type " ++ show cwvalty ++ "\nRet type " ++ show ret_ty)
755+ let pvars = map fst (getPBtys cwvalty)
756+ -- we need the unelaborated term to get the names it depends on
757+ -- rather than a de Bruijn index.
758+ let pdeps = usedNamesIn pvars i (delab i cwvalty)
759+ let (bargs_pre, bargs_post) = split pdeps bargs []
760+ logLvl 10 ("With type " ++ show (getRetTy cwvaltyN) ++
761+ " depends on " ++ show pdeps ++ " from " ++ show pvars)
762+ logLvl 10 ("Pre " ++ show bargs_pre ++ "\nPost " ++ show bargs_post)
763+ windex <- getName
764+ -- build a type declaration for the new function:
765+ -- (ps : Xs) -> (withval : cwvalty) -> (ps' : Xs') -> ret_ty
766+ let wargval = getRetTy cwvalN
767+ let wargtype = getRetTy cwvaltyN
768+ logLvl 5 ("Abstract over " ++ show wargval ++ " in " ++ show wargtype)
769+ let wtype = bindTyArgs Pi (bargs_pre ++
770+ (sMN 0 "warg", wargtype) :
771+ map (abstract (sMN 0 "warg") wargval wargtype) bargs_post)
772+ (substTerm wargval (P Bound (sMN 0 "warg") wargtype) ret_ty)
773+ logLvl 5 ("New function type " ++ show wtype)
774+ let wname = sMN windex (show fname)
775+
776+ let imps = getImps wtype -- add to implicits context
777+ putIState (i { idris_implicits = addDef wname imps (idris_implicits i) })
778+ addIBC (IBCDef wname)
779+ def' <- checkDef fc [(wname, (-1, Nothing, wtype))]
780+ let def'' = map (\(n, (i, top, t)) -> (n, (i, top, t, False))) def'
781+ addDeferred def''
782+
783+ -- in the subdecls, lhs becomes:
784+ -- fname pats | wpat [rest]
785+ -- ==> fname' ps wpat [rest], match pats against toplevel for ps
786+ wb <- mapM (mkAuxC wname lhs (map fst bargs_pre) (map fst bargs_post))
787+ withblock
788+ logLvl 3 ("with block " ++ show wb)
789+ -- propagate totality assertion to the new definitions
790+ when (AssertTotal `elem` opts) $ setFlags wname [AssertTotal]
791+ mapM_ (rec_elabDecl info EAll info) wb
792+
793+ -- rhs becomes: fname' ps wval
794+ let rhs = PApp fc (PRef fc wname)
795+ (map (pexp . (PRef fc) . fst) bargs_pre ++
796+ pexp wval :
797+ (map (pexp . (PRef fc) . fst) bargs_post))
798+ logLvl 5 ("New RHS " ++ showTmImpls rhs)
799+ ctxt <- getContext -- New context with block added
800+ i <- getIState
801+ ((rhs', defer, is), _) <-
802+ tclift $ elaborate ctxt (sMN 0 "wpatRHS") clhsty []
803+ (do pbinds i lhs_tm
804+ setNextName
805+ (_, d, is) <- erun fc (build i info ERHS opts fname rhs)
806+ psolve lhs_tm
807+ tt <- get_term
808+ return (tt, d, is))
809+ def' <- checkDef fc defer
810+ let def'' = map (\(n, (i, top, t)) -> (n, (i, top, t, False))) def'
811+ addDeferred def''
812+ mapM_ (elabCaseBlock info opts) is
813+ logLvl 5 ("Checked RHS " ++ show rhs')
814+ (crhs, crhsty) <- recheckC fc [] rhs'
815+ return $ (Right (clhs, crhs), lhs)
816+ where
817+ getImps (Bind n (Pi _) t) = pexp Placeholder : getImps t
818+ getImps _ = []
819+
820+ mkAuxC wname lhs ns ns' (PClauses fc o n cs)
821+ | True = do cs' <- mapM (mkAux wname lhs ns ns') cs
822+ return $ PClauses fc o wname cs'
823+ | otherwise = ifail $ show fc ++ "with clause uses wrong function name " ++ show n
824+ mkAuxC wname lhs ns ns' d = return $ d
825+
826+ mkAux wname toplhs ns ns' (PClause fc n tm_in (w:ws) rhs wheres)
827+ = do i <- getIState
828+ let tm = addImplPat i tm_in
829+ logLvl 2 ("Matching " ++ showTmImpls tm ++ " against " ++
830+ showTmImpls toplhs)
831+ case matchClause i toplhs tm of
832+ Left (a,b) -> ifail $ show fc ++ ":with clause does not match top level"
833+ Right mvars ->
834+ do logLvl 3 ("Match vars : " ++ show mvars)
835+ lhs <- updateLHS n wname mvars ns ns' (fullApp tm) w
836+ return $ PClause fc wname lhs ws rhs wheres
837+ mkAux wname toplhs ns ns' (PWith fc n tm_in (w:ws) wval withs)
838+ = do i <- getIState
839+ let tm = addImplPat i tm_in
840+ logLvl 2 ("Matching " ++ showTmImpls tm ++ " against " ++
841+ showTmImpls toplhs)
842+ withs' <- mapM (mkAuxC wname toplhs ns ns') withs
843+ case matchClause i toplhs tm of
844+ Left (a,b) -> trace ("matchClause: " ++ show a ++ " =/= " ++ show b) (ifail $ show fc ++ "with clause does not match top level")
845+ Right mvars ->
846+ do lhs <- updateLHS n wname mvars ns ns' (fullApp tm) w
847+ return $ PWith fc wname lhs ws wval withs'
848+ mkAux wname toplhs ns ns' c
849+ = ifail $ show fc ++ ":badly formed with clause"
850+
851+ addArg (PApp fc f args) w = PApp fc f (args ++ [pexp w])
852+ addArg (PRef fc f) w = PApp fc (PRef fc f) [pexp w]
853+
854+ updateLHS n wname mvars ns_in ns_in' (PApp fc (PRef fc' n') args) w
855+ = let ns = map (keepMvar (map fst mvars) fc') ns_in
856+ ns' = map (keepMvar (map fst mvars) fc') ns_in' in
857+ return $ substMatches mvars $
858+ PApp fc (PRef fc' wname)
859+ (map pexp ns ++ pexp w : (map pexp ns'))
860+ updateLHS n wname mvars ns_in ns_in' tm w
861+ = updateLHS n wname mvars ns_in ns_in' (PApp fc tm []) w
862+
863+ keepMvar mvs fc v | v `elem` mvs = PRef fc v
864+ | otherwise = Placeholder
865+
866+ fullApp (PApp _ (PApp fc f args) xs) = fullApp (PApp fc f (args ++ xs))
867+ fullApp x = x
868+
869+ split [] rest pre = (reverse pre, rest)
870+ split deps ((n, ty) : rest) pre
871+ | n `elem` deps = split (deps \\ [n]) rest ((n, ty) : pre)
872+ | otherwise = split deps rest ((n, ty) : pre)
873+ split deps [] pre = (reverse pre, [])
874+
875+ abstract wn wv wty (n, argty) = (n, substTerm wv (P Bound wn wty) argty)
876+
877+
src/Idris/Elab/Data.hsnew file+489
@@ -0,0 +1,489 @@
1+{-# LANGUAGE PatternGuards #-}
2+module Idris.Elab.Data(elabData) where
3+
4+import Idris.AbsSyntax
5+import Idris.ASTUtils
6+import Idris.DSL
7+import Idris.Error
8+import Idris.Delaborate
9+import Idris.Imports
10+import Idris.ElabTerm
11+import Idris.Coverage
12+import Idris.DataOpts
13+import Idris.Providers
14+import Idris.Primitives
15+import Idris.Inliner
16+import Idris.PartialEval
17+import Idris.DeepSeq
18+import Idris.Output (iputStrLn, pshow, iWarn)
19+import IRTS.Lang
20+
21+import Idris.Elab.Type
22+import Idris.Elab.Utils
23+
24+import Idris.Core.TT
25+import Idris.Core.Elaborate hiding (Tactic(..))
26+import Idris.Core.Evaluate
27+import Idris.Core.Execute
28+import Idris.Core.Typecheck
29+import Idris.Core.CaseTree
30+
31+import Idris.Docstrings
32+
33+import Prelude hiding (id, (.))
34+import Control.Category
35+
36+import Control.Applicative hiding (Const)
37+import Control.DeepSeq
38+import Control.Monad
39+import Control.Monad.State.Strict as State
40+import Data.List
41+import Data.Maybe
42+import Debug.Trace
43+
44+import qualified Data.Map as Map
45+import qualified Data.Set as S
46+import qualified Data.Text as T
47+import Data.Char(isLetter, toLower)
48+import Data.List.Split (splitOn)
49+
50+import Util.Pretty(pretty, text)
51+
52+elabData :: ElabInfo -> SyntaxInfo -> Docstring -> [(Name, Docstring)] -> FC -> DataOpts -> PData -> Idris ()
53+elabData info syn doc argDocs fc opts (PLaterdecl n t_in)
54+ = do let codata = Codata `elem` opts
55+ iLOG (show (fc, doc))
56+ checkUndefined fc n
57+ (cty, t, inacc) <- buildType info syn fc [] n t_in
58+
59+ addIBC (IBCDef n)
60+ updateContext (addTyDecl n (TCon 0 0) cty) -- temporary, to check cons
61+
62+elabData info syn doc argDocs fc opts (PDatadecl n t_in dcons)
63+ = do let codata = Codata `elem` opts
64+ iLOG (show fc)
65+ undef <- isUndefined fc n
66+ (cty, t, inacc) <- buildType info syn fc [] n t_in
67+ -- if n is defined already, make sure it is just a type declaration
68+ -- with the same type we've just elaborated
69+ i <- getIState
70+ checkDefinedAs fc n cty (tt_ctxt i)
71+ -- temporary, to check cons
72+ when undef $ updateContext (addTyDecl n (TCon 0 0) cty)
73+ let cnameinfo = cinfo info (map cname dcons)
74+ cons <- mapM (elabCon cnameinfo syn n codata) dcons
75+ ttag <- getName
76+ i <- getIState
77+ let as = map (const Nothing) (getArgTys cty)
78+ let params = findParams (map snd cons)
79+ logLvl 2 $ "Parameters : " ++ show params
80+ -- TI contains information about mutually declared types - this will
81+ -- be updated when the mutual block is complete
82+ putIState (i { idris_datatypes =
83+ addDef n (TI (map fst cons) codata opts params [n])
84+ (idris_datatypes i) })
85+ addIBC (IBCDef n)
86+ addIBC (IBCData n)
87+ checkDocs fc argDocs t
88+ addDocStr n doc argDocs
89+ addIBC (IBCDoc n)
90+ let metainf = DataMI params
91+ addIBC (IBCMetaInformation n metainf)
92+ -- TMP HACK! Make this a data option
93+ updateContext (addDatatype (Data n ttag cty cons))
94+ updateContext (setMetaInformation n metainf)
95+ mapM_ totcheck (zip (repeat fc) (map fst cons))
96+-- mapM_ (checkPositive n) cons
97+
98+ -- if there's exactly one constructor,
99+ -- mark both the type and the constructor as detaggable
100+ case cons of
101+ [(cn,ct)] -> setDetaggable cn >> setDetaggable n
102+ >> addIBC (IBCOpt cn) >> addIBC (IBCOpt n)
103+ _ -> return ()
104+
105+ -- create an eliminator
106+ when (DefaultEliminator `elem` opts) $
107+ evalStateT (elabCaseFun True params n t dcons info) Map.empty
108+ -- create a case function
109+ when (DefaultCaseFun `elem` opts) $
110+ evalStateT (elabCaseFun False params n t dcons info) Map.empty
111+ where
112+ setDetaggable :: Name -> Idris ()
113+ setDetaggable n = do
114+ ist <- getIState
115+ let opt = idris_optimisation ist
116+ case lookupCtxt n opt of
117+ [oi] -> putIState ist{ idris_optimisation = addDef n oi{ detaggable = True } opt }
118+ _ -> putIState ist{ idris_optimisation = addDef n (Optimise [] True) opt }
119+
120+ checkDefinedAs fc n t ctxt
121+ = case lookupDef n ctxt of
122+ [] -> return ()
123+ [TyDecl _ ty] ->
124+ case converts ctxt [] t ty of
125+ OK () -> return ()
126+ _ -> tclift $ tfail (At fc (AlreadyDefined n))
127+ _ -> tclift $ tfail (At fc (AlreadyDefined n))
128+ -- parameters are names which are unchanged across the structure,
129+ -- which appear exactly once in the return type of a constructor
130+
131+ -- First, find all applications of the constructor, then check over
132+ -- them for repeated arguments
133+
134+ findParams :: [Type] -> [Int]
135+ findParams ts = let allapps = concatMap getDataApp ts in
136+ paramPos allapps
137+
138+ paramPos [] = []
139+ paramPos (args : rest)
140+ = dropNothing $ keepSame (zip [0..] args) rest
141+
142+ dropNothing [] = []
143+ dropNothing ((x, Nothing) : ts) = dropNothing ts
144+ dropNothing ((x, _) : ts) = x : dropNothing ts
145+
146+ keepSame :: [(Int, Maybe Name)] -> [[Maybe Name]] ->
147+ [(Int, Maybe Name)]
148+ keepSame as [] = as
149+ keepSame as (args : rest) = keepSame (update as args) rest
150+ where
151+ update [] _ = []
152+ update _ [] = []
153+ update ((n, Just x) : as) (Just x' : args)
154+ | x == x' = (n, Just x) : update as args
155+ update ((n, _) : as) (_ : args) = (n, Nothing) : update as args
156+
157+ getDataApp :: Type -> [[Maybe Name]]
158+ getDataApp f@(App _ _)
159+ | (P _ d _, args) <- unApply f
160+ = if (d == n) then [mParam args args] else []
161+ getDataApp (Bind n (Pi t) sc)
162+ = getDataApp t ++ getDataApp (instantiate (P Bound n t) sc)
163+ getDataApp _ = []
164+
165+ -- keep the arguments which are single names, which don't appear
166+ -- elsewhere
167+
168+ mParam args [] = []
169+ mParam args (P Bound n _ : rest)
170+ | count n args == 1
171+ = Just n : mParam args rest
172+ where count n [] = 0
173+ count n (t : ts)
174+ | n `elem` freeNames t = 1 + count n ts
175+ | otherwise = count n ts
176+ mParam args (_ : rest) = Nothing : mParam args rest
177+
178+ cname (_, _, n, _, _, _) = n
179+
180+ -- Abuse of ElabInfo.
181+ -- TODO Contemplate whether the ElabInfo type needs modification.
182+ cinfo :: ElabInfo -> [Name] -> ElabInfo
183+ cinfo info ds
184+ = let newps = params info
185+ dsParams = map (\n -> (n, [])) ds
186+ newb = addAlist dsParams (inblock info)
187+ l = liftname info in
188+ info { params = newps,
189+ inblock = newb,
190+ liftname = id -- Is this appropriate?
191+ }
192+
193+-- FIXME: 'forcenames' is an almighty hack! Need a better way of
194+-- erasing non-forceable things
195+-- ^^^
196+-- TODO: the above is a comment from the past;
197+-- forcenames is probably no longer needed
198+elabCon :: ElabInfo -> SyntaxInfo -> Name -> Bool ->
199+ (Docstring, [(Name, Docstring)], Name, PTerm, FC, [Name]) -> Idris (Name, Type)
200+elabCon info syn tn codata (doc, argDocs, n, t_in, fc, forcenames)
201+ = do checkUndefined fc n
202+ (cty, t, inacc) <- buildType info syn fc [] n (if codata then mkLazy t_in else t_in)
203+ ctxt <- getContext
204+ let cty' = normalise ctxt [] cty
205+
206+ -- Check that the constructor type is, in fact, a part of the family being defined
207+ tyIs n cty'
208+
209+ logLvl 2 $ show fc ++ ":Constructor " ++ show n ++ " : " ++ show t
210+ logLvl 5 $ "Inaccessible args: " ++ show inacc
211+ logLvl 2 $ "---> " ++ show n ++ " : " ++ show cty'
212+
213+ addIBC (IBCDef n)
214+ checkDocs fc argDocs t
215+ addDocStr n doc argDocs
216+ addIBC (IBCDoc n)
217+ fputState (opt_inaccessible . ist_optimisation n) inacc
218+ addIBC (IBCOpt n)
219+ return (n, cty')
220+ where
221+ tyIs con (Bind n b sc) = tyIs con sc
222+ tyIs con t | (P _ n' _, _) <- unApply t
223+ = if n' /= tn then tclift $ tfail (At fc (Elaborating "constructor " con (Msg (show n' ++ " is not " ++ show tn))))
224+ else return ()
225+ tyIs con t = tclift $ tfail (At fc (Elaborating "constructor " con (Msg (show t ++ " is not " ++ show tn))))
226+
227+ mkLazy (PPi pl n ty sc)
228+ = let ty' = if getTyName ty
229+ then PApp fc (PRef fc (sUN "Lazy'"))
230+ [pexp (PRef fc (sUN "LazyCodata")),
231+ pexp ty]
232+ else ty in
233+ PPi pl n ty' (mkLazy sc)
234+ mkLazy t = t
235+
236+ getTyName (PApp _ (PRef _ n) _) = n == nsroot tn
237+ getTyName (PRef _ n) = n == nsroot tn
238+ getTyName _ = False
239+
240+
241+ getNamePos :: Int -> PTerm -> Name -> Maybe Int
242+ getNamePos i (PPi _ n _ sc) x | n == x = Just i
243+ | otherwise = getNamePos (i + 1) sc x
244+ getNamePos _ _ _ = Nothing
245+
246+type EliminatorState = StateT (Map.Map String Int) Idris
247+
248+-- TODO: Rewrite everything to use idris_implicits instead of manual splitting (or in TT)
249+-- FIXME: Many things have name starting with elim internally since this was the only purpose in the first edition of the function
250+-- rename to caseFun to match updated intend
251+elabCaseFun :: Bool -> [Int] -> Name -> PTerm ->
252+ [(Docstring, [(Name, Docstring)], Name, PTerm, FC, [Name])] ->
253+ ElabInfo -> EliminatorState ()
254+elabCaseFun ind paramPos n ty cons info = do
255+ elimLog $ "Elaborating case function"
256+ put (Map.fromList $ zip (concatMap (\(_, p, _, ty, _, _) -> (map show $ boundNamesIn ty) ++ map (show . fst) p) cons ++ (map show $ boundNamesIn ty)) (repeat 0))
257+ let (cnstrs, _) = splitPi ty
258+ let (splittedTy@(pms, idxs)) = splitPms cnstrs
259+ generalParams <- namePis False pms
260+ motiveIdxs <- namePis False idxs
261+ let motive = mkMotive n paramPos generalParams motiveIdxs
262+ consTerms <- mapM (\(c@(_, _, cnm, _, _, _)) -> do
263+ let casefunt = if ind then "elim_" else "case_"
264+ name <- freshName $ casefunt ++ simpleName cnm
265+ consTerm <- extractConsTerm c generalParams
266+ return (name, expl, consTerm)) cons
267+ scrutineeIdxs <- namePis False idxs
268+ let motiveConstr = [(motiveName, expl, motive)]
269+ let scrutinee = (scrutineeName, expl, applyCons n (interlievePos paramPos generalParams scrutineeIdxs 0))
270+ let eliminatorTy = piConstr (generalParams ++ motiveConstr ++ consTerms ++ scrutineeIdxs ++ [scrutinee]) (applyMotive (map (\(n,_,_) -> PRef elimFC n) scrutineeIdxs) (PRef elimFC scrutineeName))
271+ let eliminatorTyDecl = PTy (parseDocstring . T.pack $ show n) [] defaultSyntax elimFC [TotalFn] elimDeclName eliminatorTy
272+ let clauseConsElimArgs = map getPiName consTerms
273+ let clauseGeneralArgs' = map getPiName generalParams ++ [motiveName] ++ clauseConsElimArgs
274+ let clauseGeneralArgs = map (\arg -> pexp (PRef elimFC arg)) clauseGeneralArgs'
275+ let elimSig = "-- case function signature: " ++ showTmImpls eliminatorTy
276+ elimLog elimSig
277+ eliminatorClauses <- mapM (\(cns, cnsElim) -> generateEliminatorClauses cns cnsElim clauseGeneralArgs generalParams) (zip cons clauseConsElimArgs)
278+ let eliminatorDef = PClauses emptyFC [TotalFn] elimDeclName eliminatorClauses
279+ elimLog $ "-- case function definition: " ++ (show . showDeclImp verbosePPOption) eliminatorDef
280+ State.lift $ idrisCatch (rec_elabDecl info EAll info eliminatorTyDecl) (\err -> return ())
281+ -- Do not elaborate clauses if there aren't any
282+ case eliminatorClauses of
283+ [] -> State.lift $ solveDeferred elimDeclName -- Remove meta-variable for type
284+ _ -> State.lift $ idrisCatch (rec_elabDecl info EAll info eliminatorDef) (\err -> return ())
285+ where elimLog :: String -> EliminatorState ()
286+ elimLog s = State.lift (logLvl 2 s)
287+
288+ elimFC :: FC
289+ elimFC = fileFC "(casefun)"
290+
291+ elimDeclName :: Name
292+ elimDeclName = if ind then SN . ElimN $ n else SN . CaseN $ n
293+
294+ applyNS :: Name -> [String] -> Name
295+ applyNS n [] = n
296+ applyNS n ns = sNS n ns
297+
298+ splitPi :: PTerm -> ([(Name, Plicity, PTerm)], PTerm)
299+ splitPi = splitPi' []
300+ where splitPi' :: [(Name, Plicity, PTerm)] -> PTerm -> ([(Name, Plicity, PTerm)], PTerm)
301+ splitPi' acc (PPi pl n tyl tyr) = splitPi' ((n, pl, tyl):acc) tyr
302+ splitPi' acc t = (reverse acc, t)
303+
304+ splitPms :: [(Name, Plicity, PTerm)] -> ([(Name, Plicity, PTerm)], [(Name, Plicity, PTerm)])
305+ splitPms cnstrs = (map fst pms, map fst idxs)
306+ where (pms, idxs) = partition (\c -> snd c `elem` paramPos) (zip cnstrs [0..])
307+
308+ isMachineGenerated :: Name -> Bool
309+ isMachineGenerated (MN _ _) = True
310+ isMachineGenerated _ = False
311+
312+ namePis :: Bool -> [(Name, Plicity, PTerm)] -> EliminatorState [(Name, Plicity, PTerm)]
313+ namePis keepOld pms = do names <- mapM (mkPiName keepOld) pms
314+ let oldNames = map fst names
315+ let params = map snd names
316+ return $ map (\(n, pl, ty) -> (n, pl, removeParamPis oldNames params ty)) params
317+
318+ mkPiName :: Bool -> (Name, Plicity, PTerm) -> EliminatorState (Name, (Name, Plicity, PTerm))
319+ mkPiName keepOld (n, pl, piarg) | not (isMachineGenerated n) && keepOld = do return (n, (n, pl, piarg))
320+ mkPiName _ (oldName, pl, piarg) = do name <- freshName $ keyOf piarg
321+ return (oldName, (name, pl, piarg))
322+ where keyOf :: PTerm -> String
323+ keyOf (PRef _ name) | isLetter (nameStart name) = (toLower $ nameStart name):"__"
324+ keyOf (PApp _ tyf _) = keyOf tyf
325+ keyOf PType = "ty__"
326+ keyOf _ = "carg__"
327+ nameStart :: Name -> Char
328+ nameStart n = nameStart' (simpleName n)
329+ where nameStart' :: String -> Char
330+ nameStart' "" = ' '
331+ nameStart' ns = head ns
332+
333+ simpleName :: Name -> String
334+ simpleName (NS n _) = simpleName n
335+ simpleName (MN i n) = str n ++ show i
336+ simpleName n = show n
337+
338+ nameSpaces :: Name -> [String]
339+ nameSpaces (NS _ ns) = map str ns
340+ nameSpaces _ = []
341+
342+ freshName :: String -> EliminatorState Name
343+ freshName key = do
344+ nameMap <- get
345+ let i = fromMaybe 0 (Map.lookup key nameMap)
346+ let name = uniqueName (sUN (key ++ show i)) (map (\(nm, nb) -> sUN (nm ++ show nb)) $ Map.toList nameMap)
347+ put $ Map.insert key (i+1) nameMap
348+ return name
349+
350+ scrutineeName :: Name
351+ scrutineeName = sUN "scrutinee"
352+
353+ scrutineeArgName :: Name
354+ scrutineeArgName = sUN "scrutineeArg"
355+
356+ motiveName :: Name
357+ motiveName = sUN "prop"
358+
359+ mkMotive :: Name -> [Int] -> [(Name, Plicity, PTerm)] -> [(Name, Plicity, PTerm)] -> PTerm
360+ mkMotive n paramPos params indicies =
361+ let scrutineeTy = (scrutineeArgName, expl, applyCons n (interlievePos paramPos params indicies 0))
362+ in piConstr (indicies ++ [scrutineeTy]) PType
363+
364+ piConstr :: [(Name, Plicity, PTerm)] -> PTerm -> PTerm
365+ piConstr [] ty = ty
366+ piConstr ((n, pl, tyb):tyr) ty = PPi pl n tyb (piConstr tyr ty)
367+
368+ interlievePos :: [Int] -> [a] -> [a] -> Int -> [a]
369+ interlievePos idxs [] l2 i = l2
370+ interlievePos idxs l1 [] i = l1
371+ interlievePos idxs (x:xs) l2 i | i `elem` idxs = x:(interlievePos idxs xs l2 (i+1))
372+ interlievePos idxs l1 (y:ys) i = y:(interlievePos idxs l1 ys (i+1))
373+
374+ replaceParams :: [Int] -> [(Name, Plicity, PTerm)] -> PTerm -> PTerm
375+ replaceParams paramPos params cns =
376+ let (_, cnsResTy) = splitPi cns
377+ in case cnsResTy of
378+ PApp _ _ args ->
379+ let oldParams = paramNamesOf 0 paramPos args
380+ in removeParamPis oldParams params cns
381+ _ -> cns
382+
383+ removeParamPis :: [Name] -> [(Name, Plicity, PTerm)] -> PTerm -> PTerm
384+ removeParamPis oldParams params (PPi pl n tyb tyr) =
385+ case findIndex (== n) oldParams of
386+ Nothing -> (PPi pl n (removeParamPis oldParams params tyb) (removeParamPis oldParams params tyr))
387+ Just i -> (removeParamPis oldParams params tyr)
388+ removeParamPis oldParams params (PRef _ n) =
389+ case findIndex (== n) oldParams of
390+ Nothing -> (PRef elimFC n)
391+ Just i -> let (newname,_,_) = params !! i in (PRef elimFC (newname))
392+ removeParamPis oldParams params (PApp _ cns args) =
393+ PApp elimFC (removeParamPis oldParams params cns) $ replaceParamArgs args
394+ where replaceParamArgs :: [PArg] -> [PArg]
395+ replaceParamArgs [] = []
396+ replaceParamArgs (arg:args) =
397+ case extractName (getTm arg) of
398+ [] -> arg:replaceParamArgs args
399+ [n] ->
400+ case findIndex (== n) oldParams of
401+ Nothing -> arg:replaceParamArgs args
402+ Just i -> let (newname,_,_) = params !! i in arg {getTm = PRef elimFC newname}:replaceParamArgs args
403+ removeParamPis oldParams params t = t
404+
405+ paramNamesOf :: Int -> [Int] -> [PArg] -> [Name]
406+ paramNamesOf i paramPos [] = []
407+ paramNamesOf i paramPos (arg:args) = (if i `elem` paramPos then extractName (getTm arg) else []) ++ paramNamesOf (i+1) paramPos args
408+
409+ extractName :: PTerm -> [Name]
410+ extractName (PRef _ n) = [n]
411+ extractName _ = []
412+
413+ splitArgPms :: PTerm -> ([PTerm], [PTerm])
414+ splitArgPms (PApp _ f args) = splitArgPms' args
415+ where splitArgPms' :: [PArg] -> ([PTerm], [PTerm])
416+ splitArgPms' cnstrs = (map (getTm . fst) pms, map (getTm . fst) idxs)
417+ where (pms, idxs) = partition (\c -> snd c `elem` paramPos) (zip cnstrs [0..])
418+ splitArgPms _ = ([],[])
419+
420+
421+ implicitIndexes :: (Docstring, Name, PTerm, FC, [Name]) -> EliminatorState [(Name, Plicity, PTerm)]
422+ implicitIndexes (cns@(doc, cnm, ty, fc, fs)) = do
423+ i <- State.lift getIState
424+ implargs' <- case lookupCtxt cnm (idris_implicits i) of
425+ [] -> do fail $ "Error while showing implicits for " ++ show cnm
426+ [args] -> do return args
427+ _ -> do fail $ "Ambigous name for " ++ show cnm
428+ let implargs = mapMaybe convertImplPi implargs'
429+ let (_, cnsResTy) = splitPi ty
430+ case cnsResTy of
431+ PApp _ _ args ->
432+ let oldParams = paramNamesOf 0 paramPos args
433+ in return $ filter (\(n,_,_) -> not (n `elem` oldParams))implargs
434+ _ -> return implargs
435+
436+ extractConsTerm :: (Docstring, [(Name, Docstring)], Name, PTerm, FC, [Name]) -> [(Name, Plicity, PTerm)] -> EliminatorState PTerm
437+ extractConsTerm (doc, argDocs, cnm, ty, fc, fs) generalParameters = do
438+ let cons' = replaceParams paramPos generalParameters ty
439+ let (args, resTy) = splitPi cons'
440+ implidxs <- implicitIndexes (doc, cnm, ty, fc, fs)
441+ consArgs <- namePis False args
442+ let recArgs = findRecArgs consArgs
443+ let recMotives = if ind then map applyRecMotive recArgs else []
444+ let (_, consIdxs) = splitArgPms resTy
445+ return $ piConstr (implidxs ++ consArgs ++ recMotives) (applyMotive consIdxs (applyCons cnm consArgs))
446+ where applyRecMotive :: (Name, Plicity, PTerm) -> (Name, Plicity, PTerm)
447+ applyRecMotive (n,_,ty) = (sUN $ "ih" ++ simpleName n, expl, applyMotive idxs (PRef elimFC n))
448+ where (_, idxs) = splitArgPms ty
449+
450+ findRecArgs :: [(Name, Plicity, PTerm)] -> [(Name, Plicity, PTerm)]
451+ findRecArgs [] = []
452+ findRecArgs (ty@(_,_,PRef _ tn):rs) | simpleName tn == simpleName n = ty:findRecArgs rs
453+ findRecArgs (ty@(_,_,PApp _ (PRef _ tn) _):rs) | simpleName tn == simpleName n = ty:findRecArgs rs
454+ findRecArgs (ty:rs) = findRecArgs rs
455+
456+ applyCons :: Name -> [(Name, Plicity, PTerm)] -> PTerm
457+ applyCons tn targs = PApp elimFC (PRef elimFC tn) (map convertArg targs)
458+
459+ convertArg :: (Name, Plicity, PTerm) -> PArg
460+ convertArg (n, _, _) = pexp (PRef elimFC n)
461+
462+ applyMotive :: [PTerm] -> PTerm -> PTerm
463+ applyMotive idxs t = PApp elimFC (PRef elimFC motiveName) (map pexp idxs ++ [pexp t])
464+
465+ getPiName :: (Name, Plicity, PTerm) -> Name
466+ getPiName (name,_,_) = name
467+
468+ convertImplPi :: PArg -> Maybe (Name, Plicity, PTerm)
469+ convertImplPi (PImp {getTm = t, pname = n}) = Just (n, expl, t)
470+ convertImplPi _ = Nothing
471+
472+ generateEliminatorClauses :: (Docstring, [(Name, Docstring)], Name, PTerm, FC, [Name]) -> Name -> [PArg] -> [(Name, Plicity, PTerm)] -> EliminatorState PClause
473+ generateEliminatorClauses (doc, _, cnm, ty, fc, fs) cnsElim generalArgs generalParameters = do
474+ let cons' = replaceParams paramPos generalParameters ty
475+ let (args, resTy) = splitPi cons'
476+ i <- State.lift getIState
477+ implidxs <- implicitIndexes (doc, cnm, ty, fc, fs)
478+ let (_, generalIdxs') = splitArgPms resTy
479+ let generalIdxs = map pexp generalIdxs'
480+ consArgs <- namePis False args
481+ let lhsPattern = PApp elimFC (PRef elimFC elimDeclName) (generalArgs ++ generalIdxs ++ [pexp $ applyCons cnm consArgs])
482+ let recArgs = findRecArgs consArgs
483+ let recElims = if ind then map applyRecElim recArgs else []
484+ let rhsExpr = PApp elimFC (PRef elimFC cnsElim) (map convertArg implidxs ++ map convertArg consArgs ++ recElims)
485+ return $ PClause elimFC elimDeclName lhsPattern [] rhsExpr []
486+ where applyRecElim :: (Name, Plicity, PTerm) -> PArg
487+ applyRecElim (constr@(recCnm,_,recTy)) = pexp $ PApp elimFC (PRef elimFC elimDeclName) (generalArgs ++ map pexp idxs ++ [pexp $ PRef elimFC recCnm])
488+ where (_, idxs) = splitArgPms recTy
489+
src/Idris/Elab/Instance.hsnew file+260
@@ -0,0 +1,260 @@
1+{-# LANGUAGE PatternGuards #-}
2+module Idris.Elab.Instance(elabInstance) where
3+
4+import Idris.AbsSyntax
5+import Idris.ASTUtils
6+import Idris.DSL
7+import Idris.Error
8+import Idris.Delaborate
9+import Idris.Imports
10+import Idris.ElabTerm
11+import Idris.Coverage
12+import Idris.DataOpts
13+import Idris.Providers
14+import Idris.Primitives
15+import Idris.Inliner
16+import Idris.PartialEval
17+import Idris.DeepSeq
18+import Idris.Output (iputStrLn, pshow, iWarn)
19+import IRTS.Lang
20+
21+import Idris.Elab.Type
22+import Idris.Elab.Data
23+import Idris.Elab.Utils
24+
25+import Idris.Core.TT
26+import Idris.Core.Elaborate hiding (Tactic(..))
27+import Idris.Core.Evaluate
28+import Idris.Core.Execute
29+import Idris.Core.Typecheck
30+import Idris.Core.CaseTree
31+
32+import Idris.Docstrings
33+
34+import Prelude hiding (id, (.))
35+import Control.Category
36+
37+import Control.Applicative hiding (Const)
38+import Control.DeepSeq
39+import Control.Monad
40+import Control.Monad.State.Strict as State
41+import Data.List
42+import Data.Maybe
43+import Debug.Trace
44+
45+import qualified Data.Map as Map
46+import qualified Data.Set as S
47+import qualified Data.Text as T
48+import Data.Char(isLetter, toLower)
49+import Data.List.Split (splitOn)
50+
51+import Util.Pretty(pretty, text)
52+
53+elabInstance :: ElabInfo -> SyntaxInfo ->
54+ ElabWhat -> -- phase
55+ FC -> [PTerm] -> -- constraints
56+ Name -> -- the class
57+ [PTerm] -> -- class parameters (i.e. instance)
58+ PTerm -> -- full instance type
59+ Maybe Name -> -- explicit name
60+ [PDecl] -> Idris ()
61+elabInstance info syn what fc cs n ps t expn ds = do
62+ i <- getIState
63+ (n, ci) <- case lookupCtxtName n (idris_classes i) of
64+ [c] -> return c
65+ [] -> ifail $ show fc ++ ":" ++ show n ++ " is not a type class"
66+ cs -> tclift $ tfail $ At fc
67+ (CantResolveAlts (map fst cs))
68+ let constraint = PApp fc (PRef fc n) (map pexp ps)
69+ let iname = mkiname n ps expn
70+ let emptyclass = null (class_methods ci)
71+ when (what /= EDefns || (null ds && not emptyclass)) $ do
72+ nty <- elabType' True info syn emptyDocstring [] fc [] iname t
73+ -- if the instance type matches any of the instances we have already,
74+ -- and it's not a named instance, then it's overlapping, so report an error
75+ case expn of
76+ Nothing -> do mapM_ (maybe (return ()) overlapping . findOverlapping i (delab i nty))
77+ (class_instances ci)
78+ addInstance intInst n iname
79+ Just _ -> addInstance intInst n iname
80+ when (what /= ETypes && (not (null ds && not emptyclass))) $ do
81+ let ips = zip (class_params ci) ps
82+ let ns = case n of
83+ NS n ns' -> ns'
84+ _ -> []
85+ -- get the implicit parameters that need passing through to the
86+ -- where block
87+ wparams <- mapM (\p -> case p of
88+ PApp _ _ args -> getWParams (map getTm args)
89+ _ -> return []) ps
90+ let pnames = map pname (concat (nub wparams))
91+ let superclassInstances = map (substInstance ips pnames) (class_default_superclasses ci)
92+ undefinedSuperclassInstances <- filterM (fmap not . isOverlapping i) superclassInstances
93+ mapM_ (rec_elabDecl info EAll info) undefinedSuperclassInstances
94+ let all_meths = map (nsroot . fst) (class_methods ci)
95+ let mtys = map (\ (n, (op, t)) ->
96+ let t_in = substMatchesShadow ips pnames t
97+ mnamemap = map (\n -> (n, PRef fc (decorate ns iname n)))
98+ all_meths
99+ t' = substMatchesShadow mnamemap pnames t_in in
100+ (decorate ns iname n,
101+ op, coninsert cs t', t'))
102+ (class_methods ci)
103+ logLvl 3 (show (mtys, ips))
104+ let ds' = insertDefaults i iname (class_defaults ci) ns ds
105+ iLOG ("Defaults inserted: " ++ show ds' ++ "\n" ++ show ci)
106+ mapM_ (warnMissing ds' ns iname) (map fst (class_methods ci))
107+ mapM_ (checkInClass (map fst (class_methods ci))) (concatMap defined ds')
108+ let wbTys = map mkTyDecl mtys
109+ let wbVals = map (decorateid (decorate ns iname)) ds'
110+ let wb = wbTys ++ wbVals
111+ logLvl 3 $ "Method types " ++ showSep "\n" (map (show . showDeclImp verbosePPOption . mkTyDecl) mtys)
112+ logLvl 3 $ "Instance is " ++ show ps ++ " implicits " ++
113+ show (concat (nub wparams))
114+
115+ -- Bring variables in instance head into scope
116+ ist <- getIState
117+ let headVars = nub $ mapMaybe (\p -> case p of
118+ PRef _ n ->
119+ case lookupTy n (tt_ctxt ist) of
120+ [] -> Just n
121+ _ -> Nothing
122+ _ -> Nothing) ps
123+-- let lhs = PRef fc iname
124+ let lhs = PApp fc (PRef fc iname)
125+ (map (\n -> pimp n (PRef fc n) True) headVars)
126+ let rhs = PApp fc (PRef fc (instanceName ci))
127+ (map (pexp . mkMethApp) mtys)
128+
129+ logLvl 5 $ "Instance LHS " ++ show lhs ++ " " ++ show headVars
130+ logLvl 5 $ "Instance RHS " ++ show rhs
131+
132+ let idecls = [PClauses fc [Dictionary] iname
133+ [PClause fc iname lhs [] rhs wb]]
134+ iLOG (show idecls)
135+ mapM_ (rec_elabDecl info EAll info) idecls
136+ addIBC (IBCInstance intInst n iname)
137+
138+ where
139+ intInst = case ps of
140+ [PConstant (AType (ATInt ITNative))] -> True
141+ _ -> False
142+
143+ mkiname n' ps' expn' =
144+ case expn' of
145+ Nothing -> SN (sInstanceN n' (map show ps'))
146+ Just nm -> nm
147+
148+ substInstance ips pnames (PInstance syn _ cs n ps t expn ds)
149+ = PInstance syn fc cs n (map (substMatchesShadow ips pnames) ps) (substMatchesShadow ips pnames t) expn ds
150+
151+ isOverlapping i (PInstance syn _ _ n ps t expn _)
152+ = case lookupCtxtName n (idris_classes i) of
153+ [(n, ci)] -> let iname = (mkiname n ps expn) in
154+ case lookupTy iname (tt_ctxt i) of
155+ [] -> elabFindOverlapping i ci iname syn t
156+ (_:_) -> return True
157+ _ -> return False -- couldn't find class, just let elabInstance fail later
158+
159+ -- TODO: largely based upon elabType' - should try to abstract
160+ elabFindOverlapping i ci iname syn t
161+ = do ty' <- addUsingConstraints syn fc t
162+ -- TODO think: something more in info?
163+ ty' <- implicit info syn iname ty'
164+ let ty = addImpl i ty'
165+ ctxt <- getContext
166+ ((tyT, _, _), _) <-
167+ tclift $ elaborate ctxt iname (TType (UVal 0)) []
168+ (errAt "type of " iname (erun fc (build i info ERHS [] iname ty)))
169+ ctxt <- getContext
170+ (cty, _) <- recheckC fc [] tyT
171+ let nty = normalise ctxt [] cty
172+ return $ any (isJust . findOverlapping i (delab i nty)) (class_instances ci)
173+
174+ findOverlapping i t n
175+ | take 2 (show n) == "@@" = Nothing
176+ | otherwise
177+ = case lookupTy n (tt_ctxt i) of
178+ [t'] -> let tret = getRetType t
179+ tret' = getRetType (delab i t') in
180+ case matchClause i tret' tret of
181+ Right ms -> Just tret'
182+ Left _ -> case matchClause i tret tret' of
183+ Right ms -> Just tret'
184+ Left _ -> Nothing
185+ _ -> Nothing
186+ overlapping t' = tclift $ tfail (At fc (Msg $
187+ "Overlapping instance: " ++ show t' ++ " already defined"))
188+ getRetType (PPi _ _ _ sc) = getRetType sc
189+ getRetType t = t
190+
191+ mkMethApp (n, _, _, ty)
192+ = lamBind 0 ty (papp fc (PRef fc n) (methArgs 0 ty))
193+ lamBind i (PPi (Constraint _ _) _ _ sc) sc'
194+ = PLam (sMN i "meth") Placeholder (lamBind (i+1) sc sc')
195+ lamBind i (PPi _ n ty sc) sc'
196+ = PLam (sMN i "meth") Placeholder (lamBind (i+1) sc sc')
197+ lamBind i _ sc = sc
198+ methArgs i (PPi (Imp _ _ _) n ty sc)
199+ = PImp 0 True [] n (PRef fc (sMN i "meth")) : methArgs (i+1) sc
200+ methArgs i (PPi (Exp _ _ _) n ty sc)
201+ = PExp 0 [] (sMN 0 "marg") (PRef fc (sMN i "meth")) : methArgs (i+1) sc
202+ methArgs i (PPi (Constraint _ _) n ty sc)
203+ = PConstraint 0 [] (sMN 0 "marg") (PResolveTC fc) : methArgs (i+1) sc
204+ methArgs i _ = []
205+
206+ papp fc f [] = f
207+ papp fc f as = PApp fc f as
208+
209+ getWParams [] = return []
210+ getWParams (p : ps)
211+ | PRef _ n <- p
212+ = do ps' <- getWParams ps
213+ ctxt <- getContext
214+ case lookupP n ctxt of
215+ [] -> return (pimp n (PRef fc n) True : ps')
216+ _ -> return ps'
217+ getWParams (_ : ps) = getWParams ps
218+
219+ decorate ns iname (UN n) = NS (SN (MethodN (UN n))) ns
220+ decorate ns iname (NS (UN n) s) = NS (SN (MethodN (UN n))) ns
221+
222+ mkTyDecl (n, op, t, _) = PTy emptyDocstring [] syn fc op n t
223+
224+ conbind (ty : ns) x = PPi constraint (sMN 0 "class") ty (conbind ns x)
225+ conbind [] x = x
226+
227+ coninsert cs (PPi p@(Imp _ _ _) n t sc) = PPi p n t (coninsert cs sc)
228+ coninsert cs sc = conbind cs sc
229+
230+ insertDefaults :: IState -> Name ->
231+ [(Name, (Name, PDecl))] -> [T.Text] ->
232+ [PDecl] -> [PDecl]
233+ insertDefaults i iname [] ns ds = ds
234+ insertDefaults i iname ((n,(dn, clauses)) : defs) ns ds
235+ = insertDefaults i iname defs ns (insertDef i n dn clauses ns iname ds)
236+
237+ insertDef i meth def clauses ns iname decls
238+ | null $ filter (clauseFor meth iname ns) decls
239+ = let newd = expandParamsD False i (\n -> meth) [] [def] clauses in
240+ -- trace (show newd) $
241+ decls ++ [newd]
242+ | otherwise = decls
243+
244+ warnMissing decls ns iname meth
245+ | null $ filter (clauseFor meth iname ns) decls
246+ = iWarn fc . text $ "method " ++ show meth ++ " not defined"
247+ | otherwise = return ()
248+
249+ checkInClass ns meth
250+ | not (null (filter (eqRoot meth) ns)) = return ()
251+ | otherwise = tclift $ tfail (At fc (Msg $
252+ show meth ++ " not a method of class " ++ show n))
253+
254+ eqRoot x y = nsroot x == nsroot y
255+
256+ clauseFor m iname ns (PClauses _ _ m' _)
257+ = decorate ns iname m == decorate ns iname m'
258+ clauseFor m iname ns _ = False
259+
260+
src/Idris/Elab/Provider.hsnew file+117
@@ -0,0 +1,117 @@
1+{-# LANGUAGE PatternGuards #-}
2+module Idris.Elab.Provider(elabProvider) where
3+
4+import Idris.AbsSyntax
5+import Idris.ASTUtils
6+import Idris.DSL
7+import Idris.Error
8+import Idris.Delaborate
9+import Idris.Imports
10+import Idris.ElabTerm
11+import Idris.Coverage
12+import Idris.DataOpts
13+import Idris.Providers
14+import Idris.Primitives
15+import Idris.Inliner
16+import Idris.PartialEval
17+import Idris.DeepSeq
18+import Idris.Output (iputStrLn, pshow, iWarn)
19+import IRTS.Lang
20+
21+import Idris.Elab.Type
22+import Idris.Elab.Clause
23+import Idris.Elab.Value
24+import Idris.Elab.Utils
25+
26+import Idris.Core.TT
27+import Idris.Core.Elaborate hiding (Tactic(..))
28+import Idris.Core.Evaluate
29+import Idris.Core.Execute
30+import Idris.Core.Typecheck
31+import Idris.Core.CaseTree
32+
33+import Idris.Docstrings
34+
35+import Prelude hiding (id, (.))
36+import Control.Category
37+
38+import Control.Applicative hiding (Const)
39+import Control.DeepSeq
40+import Control.Monad
41+import Control.Monad.State.Strict as State
42+import Data.List
43+import Data.Maybe
44+import Debug.Trace
45+
46+import qualified Data.Map as Map
47+import qualified Data.Set as S
48+import qualified Data.Text as T
49+import Data.Char(isLetter, toLower)
50+import Data.List.Split (splitOn)
51+
52+import Util.Pretty(pretty, text)
53+
54+-- | Elaborate a type provider
55+elabProvider :: ElabInfo -> SyntaxInfo -> FC -> ProvideWhat -> Name -> Idris ()
56+elabProvider info syn fc what n
57+ = do i <- getIState
58+ -- Ensure that the experimental extension is enabled
59+ unless (TypeProviders `elem` idris_language_extensions i) $
60+ ifail $ "Failed to define type provider \"" ++ show n ++
61+ "\".\nYou must turn on the TypeProviders extension."
62+
63+ ctxt <- getContext
64+
65+ -- First elaborate the expected type (and check that it's a type)
66+ -- The goal type for a postulate is always Type.
67+ (ty', typ) <- case what of
68+ ProvTerm ty p -> elabVal info ERHS ty
69+ ProvPostulate _ -> elabVal info ERHS PType
70+ unless (isTType typ) $
71+ ifail ("Expected a type, got " ++ show ty' ++ " : " ++ show typ)
72+
73+ -- Elaborate the provider term to TT and check that the type matches
74+ (e, et) <- case what of
75+ ProvTerm _ tm -> elabVal info ERHS tm
76+ ProvPostulate tm -> elabVal info ERHS tm
77+ unless (isProviderOf (normalise ctxt [] ty') et) $
78+ ifail $ "Expected provider type IO (Provider (" ++
79+ show ty' ++ "))" ++ ", got " ++ show et ++ " instead."
80+
81+ -- Execute the type provider and normalise the result
82+ -- use 'run__provider' to convert to a primitive IO action
83+
84+ rhs <- execute (mkApp (P Ref (sUN "run__provider") Erased)
85+ [Erased, e])
86+ let rhs' = normalise ctxt [] rhs
87+ logLvl 3 $ "Normalised " ++ show n ++ "'s RHS to " ++ show rhs
88+
89+ -- Extract the provided term or postulate from the type provider
90+ provided <- getProvided fc rhs'
91+
92+ case provided of
93+ Provide tm
94+ | ProvTerm ty _ <- what ->
95+ do -- Finally add a top-level definition of the provided term
96+ elabType info syn emptyDocstring [] fc [] n ty
97+ elabClauses info fc [] n [PClause fc n (PApp fc (PRef fc n) []) [] (delab i tm) []]
98+ logLvl 3 $ "Elaborated provider " ++ show n ++ " as: " ++ show tm
99+ | ProvPostulate _ <- what ->
100+ do -- Add the postulate
101+ elabPostulate info syn (parseDocstring $ T.pack "Provided postulate") fc [] n (delab i tm)
102+ logLvl 3 $ "Elaborated provided postulate " ++ show n
103+ | otherwise ->
104+ ierror . Msg $ "Attempted to provide a postulate where a term was expected."
105+
106+ where isTType :: TT Name -> Bool
107+ isTType (TType _) = True
108+ isTType _ = False
109+
110+ isProviderOf :: TT Name -> TT Name -> Bool
111+ isProviderOf tp prov
112+ | (P _ (UN io) _, [prov']) <- unApply prov
113+ , (P _ (NS (UN prov) [provs]) _, [tp']) <- unApply prov'
114+ , tp == tp', io == txt "IO"
115+ , prov == txt "Provider" && provs == txt "Providers" = True
116+ isProviderOf _ _ = False
117+
src/Idris/Elab/Record.hsnew file+242
@@ -0,0 +1,242 @@
1+{-# LANGUAGE PatternGuards #-}
2+module Idris.Elab.Record(elabRecord) where
3+
4+import Idris.AbsSyntax
5+import Idris.ASTUtils
6+import Idris.DSL
7+import Idris.Error
8+import Idris.Delaborate
9+import Idris.Imports
10+import Idris.ElabTerm
11+import Idris.Coverage
12+import Idris.DataOpts
13+import Idris.Providers
14+import Idris.Primitives
15+import Idris.Inliner
16+import Idris.PartialEval
17+import Idris.DeepSeq
18+import Idris.Output (iputStrLn, pshow, iWarn)
19+import IRTS.Lang
20+
21+import Idris.Elab.Type
22+import Idris.Elab.Data
23+import Idris.Elab.Utils
24+
25+import Idris.Core.TT
26+import Idris.Core.Elaborate hiding (Tactic(..))
27+import Idris.Core.Evaluate
28+import Idris.Core.Execute
29+import Idris.Core.Typecheck
30+import Idris.Core.CaseTree
31+
32+import Idris.Docstrings
33+
34+import Prelude hiding (id, (.))
35+import Control.Category
36+
37+import Control.Applicative hiding (Const)
38+import Control.DeepSeq
39+import Control.Monad
40+import Control.Monad.State.Strict as State
41+import Data.List
42+import Data.Maybe
43+import Debug.Trace
44+
45+import qualified Data.Map as Map
46+import qualified Data.Set as S
47+import qualified Data.Text as T
48+import Data.Char(isLetter, toLower)
49+import Data.List.Split (splitOn)
50+
51+import Util.Pretty(pretty, text)
52+
53+elabRecord :: ElabInfo -> SyntaxInfo -> Docstring -> FC -> Name ->
54+ PTerm -> DataOpts -> Docstring -> Name -> PTerm -> Idris ()
55+elabRecord info syn doc fc tyn ty opts cdoc cn cty_in
56+ = do elabData info syn doc [] fc opts (PDatadecl tyn ty [(cdoc, [], cn, cty_in, fc, [])])
57+ -- TODO think: something more in info?
58+ cty' <- implicit info syn cn cty_in
59+ i <- getIState
60+
61+ -- get bound implicits and propagate to setters (in case they
62+ -- provide useful information for inference)
63+ let extraImpls = getBoundImpls cty'
64+
65+ cty <- case lookupTy cn (tt_ctxt i) of
66+ [t] -> return (delab i t)
67+ _ -> ifail "Something went inexplicably wrong"
68+ cimp <- case lookupCtxt cn (idris_implicits i) of
69+ [imps] -> return imps
70+ ppos <- case lookupCtxt tyn (idris_datatypes i) of
71+ [ti] -> return $ param_pos ti
72+ let cty_imp = renameBs cimp cty
73+ let ptys = getProjs [] cty_imp
74+ let ptys_u = getProjs [] cty
75+ let recty = getRecTy cty_imp
76+ let recty_u = getRecTy cty
77+
78+ let paramNames = getPNames recty ppos
79+
80+ -- rename indices when we generate the getter/setter types, so
81+ -- that they don't clash with the names of the projections
82+ -- we're generating
83+ let index_names_in = getRecNameMap "_in" ppos recty
84+ let recty_in = substMatches index_names_in recty
85+
86+ logLvl 3 $ show (recty, recty_u, ppos, paramNames, ptys)
87+ -- Substitute indices with projection functions, and parameters with
88+ -- the updated parameter name
89+ let substs = map (\ (n, _) ->
90+ if n `elem` paramNames
91+ then (n, PRef fc (mkp n))
92+ else (n, PApp fc (PRef fc n)
93+ [pexp (PRef fc rec)]))
94+ ptys
95+
96+ -- Generate projection functions
97+ proj_decls <- mapM (mkProj recty_in substs cimp) (zip ptys [0..])
98+ logLvl 3 $ show proj_decls
99+ let nonImp = mapMaybe isNonImp (zip cimp ptys_u)
100+ let implBinds = getImplB id cty'
101+
102+ -- Generate update functions
103+ update_decls <- mapM (mkUpdate recty_u index_names_in extraImpls
104+ (getFieldNames cty')
105+ implBinds (length nonImp)) (zip nonImp [0..])
106+ mapM_ (rec_elabDecl info EAll info) (concat proj_decls)
107+ logLvl 3 $ show update_decls
108+ mapM_ (tryElabDecl info) (update_decls)
109+ where
110+-- syn = syn_in { syn_namespace = show (nsroot tyn) : syn_namespace syn_in }
111+
112+ isNonImp (PExp _ _ _ _, a) = Just a
113+ isNonImp _ = Nothing
114+
115+ getPNames (PApp _ _ as) ppos = getpn as ppos
116+ where
117+ getpn as [] = []
118+ getpn as (i:is) | length as > i,
119+ PRef _ n <- getTm (as!!i) = n : getpn as is
120+ | otherwise = getpn as is
121+ getPNames _ _ = []
122+
123+ tryElabDecl info (fn, ty, val)
124+ = do i <- getIState
125+ idrisCatch (do rec_elabDecl info EAll info ty
126+ rec_elabDecl info EAll info val)
127+ (\v -> do iputStrLn $ show fc ++
128+ ":Warning - can't generate setter for " ++
129+ show fn ++ " (" ++ show ty ++ ")"
130+-- ++ "\n" ++ pshow i v
131+ putIState i)
132+
133+ getBoundImpls (PPi (Imp _ _ _) n ty sc) = (n, ty) : getBoundImpls sc
134+ getBoundImpls _ = []
135+
136+ getImplB k (PPi (Imp l s _) n Placeholder sc)
137+ = getImplB k sc
138+ getImplB k (PPi (Imp l s p) n ty sc)
139+ = getImplB (\x -> k (PPi (Imp l s p) n ty x)) sc
140+ getImplB k (PPi _ n ty sc)
141+ = getImplB k sc
142+ getImplB k _ = k
143+
144+ renameBs (PImp _ _ _ _ _ : ps) (PPi p n ty s)
145+ = PPi p (mkImp n) ty (renameBs ps (substMatch n (PRef fc (mkImp n)) s))
146+ renameBs (_:ps) (PPi p n ty s) = PPi p n ty (renameBs ps s)
147+ renameBs _ t = t
148+
149+ getProjs acc (PPi _ n ty s) = getProjs ((n, ty) : acc) s
150+ getProjs acc r = reverse acc
151+
152+ getFieldNames (PPi (Exp _ _ _) n _ s) = n : getFieldNames s
153+ getFieldNames (PPi _ _ _ s) = getFieldNames s
154+ getFieldNames _ = []
155+
156+ getRecTy (PPi _ n ty s) = getRecTy s
157+ getRecTy t = t
158+
159+ -- make sure we pick a consistent name for parameters; any name will do
160+ -- otherwise
161+ getRecNameMap x ppos (PApp fc t args)
162+ = mapMaybe toMN (zip [0..] (map getTm args))
163+ where
164+ toMN (i, PRef fc n)
165+ | i `elem` ppos = Just (n, PRef fc (mkp n))
166+ | otherwise = Just (n, PRef fc (sMN 0 (show n ++ x)))
167+ toMN _ = Nothing
168+ getRecNameMap x _ _ = []
169+
170+ rec = sMN 0 "rec"
171+
172+ -- only UNs propagate properly as parameters (bit of a hack then...)
173+ mkp (UN n) = sUN ("_p_" ++ str n)
174+ mkp (MN i n) = sMN i ("p_" ++ str n)
175+ mkp (NS n s) = NS (mkp n) s
176+
177+ mkImp (UN n) = sUN ("implicit_" ++ str n)
178+ mkImp (MN i n) = sMN i ("implicit_" ++ str n)
179+ mkImp (NS n s) = NS (mkImp n) s
180+
181+ mkType (UN n) = sUN ("set_" ++ str n)
182+ mkType (MN i n) = sMN i ("set_" ++ str n)
183+ mkType (NS n s) = NS (mkType n) s
184+
185+ mkProj recty substs cimp ((pn_in, pty), pos)
186+ = do let pn = expandNS syn pn_in -- projection name
187+ -- use pn_in in the indices, consistently, to avoid clash
188+ let pfnTy = PTy emptyDocstring [] defaultSyntax fc [] pn
189+ (PPi expl rec recty
190+ (substMatches substs pty))
191+ let pls = repeat Placeholder
192+ let before = pos
193+ let after = length substs - (pos + 1)
194+ let args = take before pls ++ PRef fc (mkp pn_in) : take after pls
195+ let iargs = map implicitise (zip cimp args)
196+ let lhs = PApp fc (PRef fc pn)
197+ [pexp (PApp fc (PRef fc cn) iargs)]
198+ let rhs = PRef fc (mkp pn_in)
199+ let pclause = PClause fc pn lhs [] rhs []
200+ return [pfnTy, PClauses fc [] pn [pclause]]
201+
202+ implicitise (pa, t) = pa { getTm = t }
203+
204+ -- If the 'pty' we're updating includes anything in 'substs', we're
205+ -- updating the type as well, so use recty', otherwise just use
206+ -- recty
207+ mkUpdate recty inames extras fnames k num ((pn, pty), pos)
208+ = do let setname = expandNS syn $ mkType pn
209+ let valname = sMN 0 "updateval"
210+ let pn_out = sMN 0 (show pn ++ "_out")
211+ let pn_in = sMN 0 (show pn ++ "_in")
212+ let recty_in = substMatches [(pn, PRef fc pn_in)] recty
213+ let recty_out = substMatches [(pn, PRef fc pn_out)] recty
214+ let pt = substMatches inames $
215+ k (implBindUp extras inames (PPi expl pn_out pty
216+ (PPi expl rec recty_in recty_out)))
217+ let pfnTy = PTy emptyDocstring [] defaultSyntax fc [] setname pt
218+-- let pls = map (\x -> PRef fc (sMN x ("field" ++ show x))) [0..num-1]
219+ let inames_imp = map (\ (x,_) -> (x, Placeholder)) inames
220+ let pls = map (\x -> substMatches inames_imp (PRef fc x)) fnames
221+ let lhsArgs = pls
222+ let rhsArgs = take pos pls ++ (PRef fc valname) :
223+ drop (pos + 1) pls
224+ let before = pos
225+ let pclause = PClause fc setname (PApp fc (PRef fc setname)
226+ [pexp (PRef fc valname),
227+ pexp (PApp fc (PRef fc cn)
228+ (map pexp lhsArgs))])
229+ []
230+ (PApp fc (PRef fc cn)
231+ (map pexp rhsArgs)) []
232+ return (pn, pfnTy, PClauses fc [] setname [pclause])
233+
234+ implBindUp [] is t = t
235+ implBindUp ((n, ty):ns) is t
236+ = let n' = case lookup n is of
237+ Just (PRef _ x) -> x
238+ _ -> n in
239+ if n `elem` allNamesIn t
240+ then PPi impl n' ty (implBindUp ns is t)
241+ else implBindUp ns is t
242+
src/Idris/Elab/Type.hsnew file+200
@@ -0,0 +1,200 @@
1+{-# LANGUAGE PatternGuards #-}
2+module Idris.Elab.Type(buildType, elabType, elabType', elabPostulate) where
3+
4+import Idris.AbsSyntax
5+import Idris.ASTUtils
6+import Idris.DSL
7+import Idris.Error
8+import Idris.Delaborate
9+import Idris.Imports
10+import Idris.ElabTerm
11+import Idris.Coverage
12+import Idris.DataOpts
13+import Idris.Providers
14+import Idris.Primitives
15+import Idris.Inliner
16+import Idris.PartialEval
17+import Idris.DeepSeq
18+import Idris.Output (iputStrLn, pshow, iWarn)
19+import IRTS.Lang
20+
21+import Idris.Elab.Utils
22+
23+import Idris.Core.TT
24+import Idris.Core.Elaborate hiding (Tactic(..))
25+import Idris.Core.Evaluate
26+import Idris.Core.Execute
27+import Idris.Core.Typecheck
28+import Idris.Core.CaseTree
29+
30+import Idris.Docstrings
31+
32+import Prelude hiding (id, (.))
33+import Control.Category
34+
35+import Control.Applicative hiding (Const)
36+import Control.DeepSeq
37+import Control.Monad
38+import Control.Monad.State.Strict as State
39+import Data.List
40+import Data.Maybe
41+import Debug.Trace
42+
43+import qualified Data.Map as Map
44+import qualified Data.Set as S
45+import qualified Data.Text as T
46+import Data.Char(isLetter, toLower)
47+import Data.List.Split (splitOn)
48+
49+import Util.Pretty(pretty, text)
50+
51+buildType :: ElabInfo -> SyntaxInfo -> FC -> FnOpts -> Name -> PTerm ->
52+ Idris (Type, PTerm, [(Int, Name)])
53+buildType info syn fc opts n ty' = do
54+ ctxt <- getContext
55+ i <- getIState
56+
57+ logLvl 3 $ show n ++ " pre-type " ++ showTmImpls ty'
58+ ty' <- addUsingConstraints syn fc ty'
59+ ty' <- addUsingImpls syn n fc ty'
60+ let ty = addImpl i ty'
61+
62+ logLvl 3 $ show n ++ " type pre-addimpl " ++ showTmImpls ty'
63+ logLvl 3 $ show n ++ " type " ++ show (using syn) ++ "\n" ++ showTmImpls ty
64+
65+ ((tyT', defer, is), log) <-
66+ tclift $ elaborate ctxt n (TType (UVal 0)) []
67+ (errAt "type of " n (erun fc (build i info ETyDecl [] n ty)))
68+
69+ let tyT = patToImp tyT'
70+
71+ logLvl 3 $ show ty ++ "\nElaborated: " ++ show tyT'
72+
73+ ds <- checkAddDef True False fc defer
74+ -- if the type is not complete, note that we'll need to infer
75+ -- things later (for solving metavariables)
76+ when (not (null ds)) $ addTyInferred n
77+
78+ mapM_ (elabCaseBlock info opts) is
79+ ctxt <- getContext
80+ logLvl 5 $ "Rechecking"
81+ logLvl 6 $ show tyT
82+ logLvl 10 $ "Elaborated to " ++ showEnvDbg [] tyT
83+ (cty, _) <- recheckC fc [] tyT
84+
85+ -- record the implicit and inaccessible arguments
86+ i <- getIState
87+ let (inaccData, impls) = unzip $ getUnboundImplicits i cty ty
88+ let inacc = inaccessibleImps 0 cty inaccData
89+ logLvl 3 $ show n ++ ": inaccessible arguments: " ++ show inacc
90+
91+ putIState $ i { idris_implicits = addDef n impls (idris_implicits i) }
92+ logLvl 3 ("Implicit " ++ show n ++ " " ++ show impls)
93+ addIBC (IBCImp n)
94+
95+ return (cty, ty, inacc)
96+ where
97+ patToImp (Bind n (PVar t) sc) = Bind n (Pi t) (patToImp sc)
98+ patToImp (Bind n b sc) = Bind n b (patToImp sc)
99+ patToImp t = t
100+
101+
102+-- | Elaborate a top-level type declaration - for example, "foo : Int -> Int".
103+elabType :: ElabInfo -> SyntaxInfo -> Docstring -> [(Name, Docstring)] ->
104+ FC -> FnOpts -> Name -> PTerm -> Idris Type
105+elabType = elabType' False
106+
107+elabType' :: Bool -> -- normalise it
108+ ElabInfo -> SyntaxInfo -> Docstring -> [(Name, Docstring)] ->
109+ FC -> FnOpts -> Name -> PTerm -> Idris Type
110+elabType' norm info syn doc argDocs fc opts n ty' = {- let ty' = piBind (params info) ty_in
111+ n = liftname info n_in in -}
112+ do checkUndefined fc n
113+ (cty, ty, inacc) <- buildType info syn fc opts n ty'
114+
115+ addStatics n cty ty
116+ let nty = cty -- normalise ctxt [] cty
117+ -- if the return type is something coinductive, freeze the definition
118+ ctxt <- getContext
119+ let nty' = normalise ctxt [] nty
120+ logLvl 2 $ "Rechecked to " ++ show nty'
121+
122+ -- Add normalised type to internals
123+ i <- getIState
124+ rep <- useREPL
125+ when rep $ do
126+ addInternalApp (fc_fname fc) (fst . fc_start $ fc) ty' -- (mergeTy ty' (delab i nty')) -- TODO: Should use span instead of line and filename?
127+ addIBC (IBCLineApp (fc_fname fc) (fst . fc_start $ fc) ty') -- (mergeTy ty' (delab i nty')))
128+
129+ let (t, _) = unApply (getRetTy nty')
130+ let corec = case t of
131+ P _ rcty _ -> case lookupCtxt rcty (idris_datatypes i) of
132+ [TI _ True _ _ _] -> True
133+ _ -> False
134+ _ -> False
135+ -- Productivity checking now via checking for guarded 'Delay'
136+ let opts' = opts -- if corec then (Coinductive : opts) else opts
137+ let usety = if norm then nty' else nty
138+ ds <- checkDef fc [(n, (-1, Nothing, usety))]
139+ addIBC (IBCDef n)
140+ let ds' = map (\(n, (i, top, t)) -> (n, (i, top, t, True))) ds
141+ addDeferred ds'
142+ setFlags n opts'
143+ checkDocs fc argDocs ty
144+ addDocStr n doc argDocs
145+ addIBC (IBCDoc n)
146+ addIBC (IBCFlags n opts')
147+ fputState (opt_inaccessible . ist_optimisation n) inacc
148+ addIBC (IBCOpt n)
149+ when (Implicit `elem` opts') $ do addCoercion n
150+ addIBC (IBCCoercion n)
151+
152+ -- If the function is declared as an error handler and the language
153+ -- extension is enabled, then add it to the list of error handlers.
154+ errorReflection <- fmap (elem ErrorReflection . idris_language_extensions) getIState
155+ when (ErrorHandler `elem` opts) $ do
156+ if errorReflection
157+ then
158+ -- TODO: Check that the declared type is the correct type for an error handler:
159+ -- handler : List (TTName, TT) -> Err -> ErrorReport - for now no ctxt
160+ if tyIsHandler nty'
161+ then do i <- getIState
162+ putIState $ i { idris_errorhandlers = idris_errorhandlers i ++ [n] }
163+ addIBC (IBCErrorHandler n)
164+ else ifail $ "The type " ++ show nty' ++ " is invalid for an error handler"
165+ else ifail "Error handlers can only be defined when the ErrorReflection language extension is enabled."
166+ return usety
167+ where
168+ -- for making an internalapp, we only want the explicit ones, and don't
169+ -- want the parameters, so just take the arguments which correspond to the
170+ -- user declared explicit ones
171+ mergeTy (PPi e n ty sc) (PPi e' n' _ sc')
172+ | e == e' = PPi e n ty (mergeTy sc sc')
173+ | otherwise = mergeTy sc sc'
174+ mergeTy _ sc = sc
175+
176+ err = txt "Err"
177+ maybe = txt "Maybe"
178+ lst = txt "List"
179+ errrep = txt "ErrorReportPart"
180+
181+ tyIsHandler (Bind _ (Pi (P _ (NS (UN e) ns1) _))
182+ (App (P _ (NS (UN m) ns2) _)
183+ (App (P _ (NS (UN l) ns3) _)
184+ (P _ (NS (UN r) ns4) _))))
185+ | e == err && m == maybe && l == lst && r == errrep
186+ , ns1 == map txt ["Errors","Reflection","Language"]
187+ , ns2 == map txt ["Maybe", "Prelude"]
188+ , ns3 == map txt ["List", "Prelude"]
189+ , ns4 == map txt ["Reflection","Language"] = True
190+ tyIsHandler _ = False
191+
192+elabPostulate :: ElabInfo -> SyntaxInfo -> Docstring ->
193+ FC -> FnOpts -> Name -> PTerm -> Idris ()
194+elabPostulate info syn doc fc opts n ty = do
195+ elabType info syn doc [] fc opts n ty
196+ putIState . (\ist -> ist{ idris_postulates = S.insert n (idris_postulates ist) }) =<< getIState
197+ addIBC (IBCPostulate n)
198+
199+ -- remove it from the deferred definitions list
200+ solveDeferred n
src/Idris/Elab/Utils.hsnew file+151
@@ -0,0 +1,151 @@
1+module Idris.Elab.Utils where
2+
3+import Idris.AbsSyntax
4+import Idris.Error
5+import Idris.DeepSeq
6+import Idris.Delaborate
7+import Idris.Docstrings
8+
9+import Idris.Core.TT
10+import Idris.Core.Elaborate hiding (Tactic(..))
11+import Idris.Core.Evaluate
12+import Idris.Core.Typecheck
13+
14+import Control.Applicative hiding (Const)
15+import Control.Monad
16+import Data.List
17+
18+import Debug.Trace
19+
20+import qualified Data.Map as Map
21+
22+recheckC fc env t
23+ = do -- t' <- applyOpts (forget t) (doesn't work, or speed things up...)
24+ ctxt <- getContext
25+ (tm, ty, cs) <- tclift $ case recheck ctxt env (forget t) t of
26+ Error e -> tfail (At fc e)
27+ OK x -> return x
28+ addConstraints fc cs
29+ return (tm, ty)
30+
31+
32+checkDef fc ns = checkAddDef False True fc ns
33+
34+checkAddDef add toplvl fc [] = return []
35+checkAddDef add toplvl fc ((n, (i, top, t)) : ns)
36+ = do ctxt <- getContext
37+ (t', _) <- recheckC fc [] t
38+ when add $ do addDeferred [(n, (i, top, t, toplvl))]
39+ addIBC (IBCDef n)
40+ ns' <- checkAddDef add toplvl fc ns
41+ return ((n, (i, top, t')) : ns')
42+
43+-- Get the list of (index, name) of inaccessible arguments from an elaborated
44+-- type
45+inaccessibleImps :: Int -> Type -> [Bool] -> [(Int, Name)]
46+inaccessibleImps i (Bind n (Pi t) sc) (inacc : ins)
47+ | inacc = (i, n) : inaccessibleImps (i + 1) sc ins
48+ | otherwise = inaccessibleImps (i + 1) sc ins
49+inaccessibleImps _ _ _ = []
50+
51+-- Get the list of (index, name) of inaccessible arguments from the type.
52+inaccessibleArgs :: Int -> PTerm -> [(Int, Name)]
53+inaccessibleArgs i (PPi (Imp _ _ _) n Placeholder t)
54+ = (i,n) : inaccessibleArgs (i+1) t -- unbound implicit
55+inaccessibleArgs i (PPi plicity n ty t)
56+ | InaccessibleArg `elem` pargopts plicity
57+ = (i,n) : inaccessibleArgs (i+1) t -- an .{erased : Implicit}
58+ | otherwise
59+ = inaccessibleArgs (i+1) t -- a {regular : Implicit}
60+inaccessibleArgs _ _ = []
61+
62+elabCaseBlock :: ElabInfo -> FnOpts -> PDecl -> Idris ()
63+elabCaseBlock info opts d@(PClauses f o n ps)
64+ = do addIBC (IBCDef n)
65+ logLvl 5 $ "CASE BLOCK: " ++ show (n, d)
66+ let opts' = nub (o ++ opts)
67+ -- propagate totality assertion to the new definitions
68+ when (AssertTotal `elem` opts) $ setFlags n [AssertTotal]
69+ rec_elabDecl info EAll info (PClauses f opts' n ps )
70+
71+-- Check that the result of type checking matches what the programmer wrote
72+-- (i.e. - if we inferred any arguments that the user provided, make sure
73+-- they are the same!)
74+
75+checkInferred :: FC -> PTerm -> PTerm -> Idris ()
76+checkInferred fc inf user =
77+ do logLvl 6 $ "Checked to\n" ++ showTmImpls inf ++ "\n\nFROM\n\n" ++
78+ showTmImpls user
79+ logLvl 10 $ "Checking match"
80+ i <- getIState
81+ tclift $ case matchClause' True i user inf of
82+ _ -> return ()
83+-- Left (x, y) -> tfail $ At fc
84+-- (Msg $ "The type-checked term and given term do not match: "
85+-- ++ show x ++ " and " ++ show y)
86+ logLvl 10 $ "Checked match"
87+-- ++ "\n" ++ showImp True inf ++ "\n" ++ showImp True user)
88+
89+-- Return whether inferred term is different from given term
90+-- (as above, but return a Bool)
91+
92+inferredDiff :: FC -> PTerm -> PTerm -> Idris Bool
93+inferredDiff fc inf user =
94+ do i <- getIState
95+ logLvl 6 $ "Checked to\n" ++ showTmImpls inf ++ "\n" ++
96+ showTmImpls user
97+ tclift $ case matchClause' True i user inf of
98+ Right vs -> return False
99+ Left (x, y) -> return True
100+
101+-- | Check a PTerm against documentation and ensure that every documented
102+-- argument actually exists. This must be run _after_ implicits have been
103+-- found, or it will give spurious errors.
104+checkDocs :: FC -> [(Name, Docstring)] -> PTerm -> Idris ()
105+checkDocs fc args tm = cd (Map.fromList args) tm
106+ where cd as (PPi _ n _ sc) = cd (Map.delete n as) sc
107+ cd as _ | Map.null as = return ()
108+ | otherwise = ierror . At fc . Msg $
109+ "There is documentation for argument(s) "
110+ ++ (concat . intersperse ", " . map show . Map.keys) as
111+ ++ " but they were not found."
112+
113+decorateid decorate (PTy doc argdocs s f o n t) = PTy doc argdocs s f o (decorate n) t
114+decorateid decorate (PClauses f o n cs)
115+ = PClauses f o (decorate n) (map dc cs)
116+ where dc (PClause fc n t as w ds) = PClause fc (decorate n) (dappname t) as w ds
117+ dc (PWith fc n t as w ds)
118+ = PWith fc (decorate n) (dappname t) as w
119+ (map (decorateid decorate) ds)
120+ dappname (PApp fc (PRef fc' n) as) = PApp fc (PRef fc' (decorate n)) as
121+ dappname t = t
122+
123+
124+-- if 't' is a type class application, assume its arguments are injective
125+pbinds :: IState -> Term -> ElabD ()
126+pbinds i (Bind n (PVar t) sc)
127+ = do attack; patbind n
128+ case unApply t of
129+ (P _ c _, args) -> case lookupCtxt c (idris_classes i) of
130+ [] -> return ()
131+ _ -> -- type class, set as injective
132+ mapM_ setinjArg args
133+ _ -> return ()
134+ pbinds i sc
135+ where setinjArg (P _ n _) = setinj n
136+ setinjArg _ = return ()
137+pbinds i tm = return ()
138+
139+pbty (Bind n (PVar t) sc) tm = Bind n (PVTy t) (pbty sc tm)
140+pbty _ tm = tm
141+
142+getPBtys (Bind n (PVar t) sc) = (n, t) : getPBtys sc
143+getPBtys (Bind n (PVTy t) sc) = (n, t) : getPBtys sc
144+getPBtys _ = []
145+
146+psolve (Bind n (PVar t) sc) = do solve; psolve sc
147+psolve tm = return ()
148+
149+pvars ist (Bind n (PVar t) sc) = (n, delab ist t) : pvars ist sc
150+pvars ist _ = []
151+
src/Idris/Elab/Value.hsnew file+88
@@ -0,0 +1,88 @@
1+{-# LANGUAGE PatternGuards #-}
2+module Idris.Elab.Value(elabVal, elabValBind) where
3+
4+import Idris.AbsSyntax
5+import Idris.ASTUtils
6+import Idris.DSL
7+import Idris.Error
8+import Idris.Delaborate
9+import Idris.Imports
10+import Idris.ElabTerm
11+import Idris.Coverage
12+import Idris.DataOpts
13+import Idris.Providers
14+import Idris.Primitives
15+import Idris.Inliner
16+import Idris.PartialEval
17+import Idris.DeepSeq
18+import Idris.Output (iputStrLn, pshow, iWarn)
19+import IRTS.Lang
20+
21+import Idris.Elab.Utils
22+
23+import Idris.Core.TT
24+import Idris.Core.Elaborate hiding (Tactic(..))
25+import Idris.Core.Evaluate
26+import Idris.Core.Execute
27+import Idris.Core.Typecheck
28+import Idris.Core.CaseTree
29+
30+import Idris.Docstrings
31+
32+import Prelude hiding (id, (.))
33+import Control.Category
34+
35+import Control.Applicative hiding (Const)
36+import Control.DeepSeq
37+import Control.Monad
38+import Control.Monad.State.Strict as State
39+import Data.List
40+import Data.Maybe
41+import Debug.Trace
42+
43+import qualified Data.Map as Map
44+import qualified Data.Set as S
45+import qualified Data.Text as T
46+import Data.Char(isLetter, toLower)
47+import Data.List.Split (splitOn)
48+
49+import Util.Pretty(pretty, text)
50+
51+-- Elaborate a value, returning any new bindings created (this will only
52+-- happen if elaborating as a pattern clause)
53+elabValBind :: ElabInfo -> ElabMode -> Bool -> PTerm -> Idris (Term, Type, [(Name, Type)])
54+elabValBind info aspat norm tm_in
55+ = do ctxt <- getContext
56+ i <- getIState
57+ let tm = addImpl i tm_in
58+ logLvl 10 (showTmImpls tm)
59+ -- try:
60+ -- * ordinary elaboration
61+ -- * elaboration as a Type
62+ -- * elaboration as a function a -> b
63+
64+ ((tm', defer, is), _) <-
65+ tclift (elaborate ctxt (sMN 0 "val") infP []
66+ (build i info aspat [Reflection] (sMN 0 "val") (infTerm tm)))
67+ let vtm = orderPats (getInferTerm tm')
68+
69+ def' <- checkDef (fileFC "(input)") defer
70+ let def'' = map (\(n, (i, top, t)) -> (n, (i, top, t, True))) def'
71+ addDeferred def''
72+ mapM_ (elabCaseBlock info []) is
73+
74+ logLvl 3 ("Value: " ++ show vtm)
75+ (vtm_in, vty) <- recheckC (fileFC "(input)") [] vtm
76+
77+ let vtm = if norm then normalise (tt_ctxt i) [] vtm_in
78+ else vtm_in
79+ let bargs = getPBtys vtm
80+
81+ return (vtm, vty, bargs)
82+
83+elabVal :: ElabInfo -> ElabMode -> PTerm -> Idris (Term, Type)
84+elabVal info aspat tm_in
85+ = do (tm, ty, _) <- elabValBind info aspat False tm_in
86+ return (tm, ty)
87+
88+
src/Idris/ElabDecls.hs+17−2252
@@ -20,6 +20,16 @@ import Idris.DeepSeq
20import Idris.Output (iputStrLn, pshow, iWarn)
20import Idris.Output (iputStrLn, pshow, iWarn)
21import IRTS.Lang
21import IRTS.Lang
22
22
23+import Idris.Elab.Utils
24+import Idris.Elab.Type
25+import Idris.Elab.Clause
26+import Idris.Elab.Data
27+import Idris.Elab.Record
28+import Idris.Elab.Class
29+import Idris.Elab.Instance
30+import Idris.Elab.Provider
31+import Idris.Elab.Value
32+
23import Idris.Core.TT
33import Idris.Core.TT
24import Idris.Core.Elaborate hiding (Tactic(..))
34import Idris.Core.Elaborate hiding (Tactic(..))
25import Idris.Core.Evaluate
35import Idris.Core.Evaluate
@@ -48,638 +58,14 @@ import Data.List.Split (splitOn)
48
58
49import Util.Pretty(pretty, text)
59import Util.Pretty(pretty, text)
50
60
51−recheckC fc env t
52− = do -- t' <- applyOpts (forget t) (doesn't work, or speed things up...)
53− ctxt <- getContext
54− (tm, ty, cs) <- tclift $ case recheck ctxt env (forget t) t of
55− Error e -> tfail (At fc e)
56− OK x -> return x
57− addConstraints fc cs
58− return (tm, ty)
59−
60−
61−checkDef fc ns = checkAddDef False True fc ns
62−
63−checkAddDef add toplvl fc [] = return []
64−checkAddDef add toplvl fc ((n, (i, top, t)) : ns)
65− = do ctxt <- getContext
66− (t', _) <- recheckC fc [] t
67− when add $ do addDeferred [(n, (i, top, t, toplvl))]
68− addIBC (IBCDef n)
69− ns' <- checkAddDef add toplvl fc ns
70− return ((n, (i, top, t')) : ns')
71−-- mapM (\(n, (i, top, t)) -> do (t', _) <- recheckC fc [] t
72−-- return (n, (i, top, t'))) ns
73−
74−buildType :: ElabInfo -> SyntaxInfo -> FC -> FnOpts -> Name -> PTerm ->
75− Idris (Type, PTerm, [(Int, Name)])
76−buildType info syn fc opts n ty' = do
77− ctxt <- getContext
78− i <- getIState
79−
80− logLvl 3 $ show n ++ " pre-type " ++ showTmImpls ty'
81− ty' <- addUsingConstraints syn fc ty'
82− ty' <- addUsingImpls syn n fc ty'
83− let ty = addImpl i ty'
84−
85− logLvl 3 $ show n ++ " type pre-addimpl " ++ showTmImpls ty'
86− logLvl 3 $ show n ++ " type " ++ show (using syn) ++ "\n" ++ showTmImpls ty
87−
88− ((tyT', defer, is), log) <-
89− tclift $ elaborate ctxt n (TType (UVal 0)) []
90− (errAt "type of " n (erun fc (build i info ETyDecl [] n ty)))
91−
92− let tyT = patToImp tyT'
93−
94− logLvl 3 $ show ty ++ "\nElaborated: " ++ show tyT'
95−
96− ds <- checkAddDef True False fc defer
97− -- if the type is not complete, note that we'll need to infer
98− -- things later (for solving metavariables)
99− when (not (null ds)) $ addTyInferred n
100−
101− mapM_ (elabCaseBlock info opts) is
102− ctxt <- getContext
103− logLvl 5 $ "Rechecking"
104− logLvl 6 $ show tyT
105− logLvl 10 $ "Elaborated to " ++ showEnvDbg [] tyT
106− (cty, _) <- recheckC fc [] tyT
107−
108− -- record the implicit and inaccessible arguments
109− i <- getIState
110− let (inaccData, impls) = unzip $ getUnboundImplicits i cty ty
111− let inacc = inaccessibleImps 0 cty inaccData
112− logLvl 3 $ show n ++ ": inaccessible arguments: " ++ show inacc
113−
114− putIState $ i { idris_implicits = addDef n impls (idris_implicits i) }
115− logLvl 3 ("Implicit " ++ show n ++ " " ++ show impls)
116− addIBC (IBCImp n)
117−
118− return (cty, ty, inacc)
119− where
120− patToImp (Bind n (PVar t) sc) = Bind n (Pi t) (patToImp sc)
121− patToImp (Bind n b sc) = Bind n b (patToImp sc)
122− patToImp t = t
123−
124−
125−-- | Elaborate a top-level type declaration - for example, "foo : Int -> Int".
126−elabType :: ElabInfo -> SyntaxInfo -> Docstring -> [(Name, Docstring)] ->
127− FC -> FnOpts -> Name -> PTerm -> Idris Type
128−elabType = elabType' False
129−
130−elabType' :: Bool -> -- normalise it
131− ElabInfo -> SyntaxInfo -> Docstring -> [(Name, Docstring)] ->
132− FC -> FnOpts -> Name -> PTerm -> Idris Type
133−elabType' norm info syn doc argDocs fc opts n ty' = {- let ty' = piBind (params info) ty_in
134− n = liftname info n_in in -}
135− do checkUndefined fc n
136− (cty, ty, inacc) <- buildType info syn fc opts n ty'
137−
138− addStatics n cty ty
139− let nty = cty -- normalise ctxt [] cty
140− -- if the return type is something coinductive, freeze the definition
141− ctxt <- getContext
142− let nty' = normalise ctxt [] nty
143− logLvl 2 $ "Rechecked to " ++ show nty'
144−
145− -- Add normalised type to internals
146− i <- getIState
147− rep <- useREPL
148− when rep $ do
149− addInternalApp (fc_fname fc) (fst . fc_start $ fc) ty' -- (mergeTy ty' (delab i nty')) -- TODO: Should use span instead of line and filename?
150− addIBC (IBCLineApp (fc_fname fc) (fst . fc_start $ fc) ty') -- (mergeTy ty' (delab i nty')))
151−
152− let (t, _) = unApply (getRetTy nty')
153− let corec = case t of
154− P _ rcty _ -> case lookupCtxt rcty (idris_datatypes i) of
155− [TI _ True _ _ _] -> True
156− _ -> False
157− _ -> False
158− -- Productivity checking now via checking for guarded 'Delay'
159− let opts' = opts -- if corec then (Coinductive : opts) else opts
160− let usety = if norm then nty' else nty
161− ds <- checkDef fc [(n, (-1, Nothing, usety))]
162− addIBC (IBCDef n)
163− let ds' = map (\(n, (i, top, t)) -> (n, (i, top, t, True))) ds
164− addDeferred ds'
165− setFlags n opts'
166− checkDocs fc argDocs ty
167− addDocStr n doc argDocs
168− addIBC (IBCDoc n)
169− addIBC (IBCFlags n opts')
170− fputState (opt_inaccessible . ist_optimisation n) inacc
171− addIBC (IBCOpt n)
172− when (Implicit `elem` opts') $ do addCoercion n
173− addIBC (IBCCoercion n)
174−
175− -- If the function is declared as an error handler and the language
176− -- extension is enabled, then add it to the list of error handlers.
177− errorReflection <- fmap (elem ErrorReflection . idris_language_extensions) getIState
178− when (ErrorHandler `elem` opts) $ do
179− if errorReflection
180− then
181− -- TODO: Check that the declared type is the correct type for an error handler:
182− -- handler : List (TTName, TT) -> Err -> ErrorReport - for now no ctxt
183− if tyIsHandler nty'
184− then do i <- getIState
185− putIState $ i { idris_errorhandlers = idris_errorhandlers i ++ [n] }
186− addIBC (IBCErrorHandler n)
187− else ifail $ "The type " ++ show nty' ++ " is invalid for an error handler"
188− else ifail "Error handlers can only be defined when the ErrorReflection language extension is enabled."
189− return usety
190− where
191− -- for making an internalapp, we only want the explicit ones, and don't
192− -- want the parameters, so just take the arguments which correspond to the
193− -- user declared explicit ones
194− mergeTy (PPi e n ty sc) (PPi e' n' _ sc')
195− | e == e' = PPi e n ty (mergeTy sc sc')
196− | otherwise = mergeTy sc sc'
197− mergeTy _ sc = sc
198−
199− err = txt "Err"
200− maybe = txt "Maybe"
201− lst = txt "List"
202− errrep = txt "ErrorReportPart"
203−
204− tyIsHandler (Bind _ (Pi (P _ (NS (UN e) ns1) _))
205− (App (P _ (NS (UN m) ns2) _)
206− (App (P _ (NS (UN l) ns3) _)
207− (P _ (NS (UN r) ns4) _))))
208− | e == err && m == maybe && l == lst && r == errrep
209− , ns1 == map txt ["Errors","Reflection","Language"]
210− , ns2 == map txt ["Maybe", "Prelude"]
211− , ns3 == map txt ["List", "Prelude"]
212− , ns4 == map txt ["Errors","Reflection","Language"] = True
213− tyIsHandler _ = False
214−
215−-- Get the list of (index, name) of inaccessible arguments from an elaborated
216−-- type
217−inaccessibleImps :: Int -> Type -> [Bool] -> [(Int, Name)]
218−inaccessibleImps i (Bind n (Pi t) sc) (inacc : ins)
219− | inacc = (i, n) : inaccessibleImps (i + 1) sc ins
220− | otherwise = inaccessibleImps (i + 1) sc ins
221−inaccessibleImps _ _ _ = []
222−
223−-- Get the list of (index, name) of inaccessible arguments from the type.
224−inaccessibleArgs :: Int -> PTerm -> [(Int, Name)]
225−inaccessibleArgs i (PPi (Imp _ _ _) n Placeholder t)
226− = (i,n) : inaccessibleArgs (i+1) t -- unbound implicit
227−inaccessibleArgs i (PPi plicity n ty t)
228− | InaccessibleArg `elem` pargopts plicity
229− = (i,n) : inaccessibleArgs (i+1) t -- an .{erased : Implicit}
230− | otherwise
231− = inaccessibleArgs (i+1) t -- a {regular : Implicit}
232−inaccessibleArgs _ _ = []
233−
234−elabPostulate :: ElabInfo -> SyntaxInfo -> Docstring ->
235− FC -> FnOpts -> Name -> PTerm -> Idris ()
236−elabPostulate info syn doc fc opts n ty = do
237− elabType info syn doc [] fc opts n ty
238− putIState . (\ist -> ist{ idris_postulates = S.insert n (idris_postulates ist) }) =<< getIState
239− addIBC (IBCPostulate n)
240−
241− -- remove it from the deferred definitions list
242− solveDeferred n
243−
244−elabData :: ElabInfo -> SyntaxInfo -> Docstring -> [(Name, Docstring)] -> FC -> DataOpts -> PData -> Idris ()
245−elabData info syn doc argDocs fc opts (PLaterdecl n t_in)
246− = do let codata = Codata `elem` opts
247− iLOG (show (fc, doc))
248− checkUndefined fc n
249− (cty, t, inacc) <- buildType info syn fc [] n t_in
250−
251− addIBC (IBCDef n)
252− updateContext (addTyDecl n (TCon 0 0) cty) -- temporary, to check cons
253−
254−elabData info syn doc argDocs fc opts (PDatadecl n t_in dcons)
255− = do let codata = Codata `elem` opts
256− iLOG (show fc)
257− undef <- isUndefined fc n
258− (cty, t, inacc) <- buildType info syn fc [] n t_in
259− -- if n is defined already, make sure it is just a type declaration
260− -- with the same type we've just elaborated
261− i <- getIState
262− checkDefinedAs fc n cty (tt_ctxt i)
263− -- temporary, to check cons
264− when undef $ updateContext (addTyDecl n (TCon 0 0) cty)
265− let cnameinfo = cinfo info (map cname dcons)
266− cons <- mapM (elabCon cnameinfo syn n codata) dcons
267− ttag <- getName
268− i <- getIState
269− let as = map (const Nothing) (getArgTys cty)
270− let params = findParams (map snd cons)
271− logLvl 2 $ "Parameters : " ++ show params
272− -- TI contains information about mutually declared types - this will
273− -- be updated when the mutual block is complete
274− putIState (i { idris_datatypes =
275− addDef n (TI (map fst cons) codata opts params [n])
276− (idris_datatypes i) })
277− addIBC (IBCDef n)
278− addIBC (IBCData n)
279− checkDocs fc argDocs t
280− addDocStr n doc argDocs
281− addIBC (IBCDoc n)
282− let metainf = DataMI params
283− addIBC (IBCMetaInformation n metainf)
284− -- TMP HACK! Make this a data option
285− updateContext (addDatatype (Data n ttag cty cons))
286− updateContext (setMetaInformation n metainf)
287− mapM_ totcheck (zip (repeat fc) (map fst cons))
288−-- mapM_ (checkPositive n) cons
289−
290− -- if there's exactly one constructor,
291− -- mark both the type and the constructor as detaggable
292− case cons of
293− [(cn,ct)] -> setDetaggable cn >> setDetaggable n
294− >> addIBC (IBCOpt cn) >> addIBC (IBCOpt n)
295− _ -> return ()
296−
297− -- create an eliminator
298− when (DefaultEliminator `elem` opts) $
299− evalStateT (elabCaseFun True params n t dcons info) Map.empty
300− -- create a case function
301− when (DefaultCaseFun `elem` opts) $
302− evalStateT (elabCaseFun False params n t dcons info) Map.empty
303− where
304− setDetaggable :: Name -> Idris ()
305− setDetaggable n = do
306− ist <- getIState
307− let opt = idris_optimisation ist
308− case lookupCtxt n opt of
309− [oi] -> putIState ist{ idris_optimisation = addDef n oi{ detaggable = True } opt }
310− _ -> putIState ist{ idris_optimisation = addDef n (Optimise [] True) opt }
311−
312− checkDefinedAs fc n t ctxt
313− = case lookupDef n ctxt of
314− [] -> return ()
315− [TyDecl _ ty] ->
316− case converts ctxt [] t ty of
317− OK () -> return ()
318− _ -> tclift $ tfail (At fc (AlreadyDefined n))
319− _ -> tclift $ tfail (At fc (AlreadyDefined n))
320− -- parameters are names which are unchanged across the structure,
321− -- which appear exactly once in the return type of a constructor
322−
323− -- First, find all applications of the constructor, then check over
324− -- them for repeated arguments
325−
326− findParams :: [Type] -> [Int]
327− findParams ts = let allapps = concatMap getDataApp ts in
328− paramPos allapps
329−
330− paramPos [] = []
331− paramPos (args : rest)
332− = dropNothing $ keepSame (zip [0..] args) rest
333−
334− dropNothing [] = []
335− dropNothing ((x, Nothing) : ts) = dropNothing ts
336− dropNothing ((x, _) : ts) = x : dropNothing ts
337−
338− keepSame :: [(Int, Maybe Name)] -> [[Maybe Name]] ->
339− [(Int, Maybe Name)]
340− keepSame as [] = as
341− keepSame as (args : rest) = keepSame (update as args) rest
342− where
343− update [] _ = []
344− update _ [] = []
345− update ((n, Just x) : as) (Just x' : args)
346− | x == x' = (n, Just x) : update as args
347− update ((n, _) : as) (_ : args) = (n, Nothing) : update as args
348−
349− getDataApp :: Type -> [[Maybe Name]]
350− getDataApp f@(App _ _)
351− | (P _ d _, args) <- unApply f
352− = if (d == n) then [mParam args args] else []
353− getDataApp (Bind n (Pi t) sc)
354− = getDataApp t ++ getDataApp (instantiate (P Bound n t) sc)
355− getDataApp _ = []
356−
357− -- keep the arguments which are single names, which don't appear
358− -- elsewhere
359−
360− mParam args [] = []
361− mParam args (P Bound n _ : rest)
362− | count n args == 1
363− = Just n : mParam args rest
364− where count n [] = 0
365− count n (t : ts)
366− | n `elem` freeNames t = 1 + count n ts
367− | otherwise = count n ts
368− mParam args (_ : rest) = Nothing : mParam args rest
369−
370− cname (_, _, n, _, _, _) = n
371−
372− -- Abuse of ElabInfo.
373− -- TODO Contemplate whether the ElabInfo type needs modification.
374− cinfo :: ElabInfo -> [Name] -> ElabInfo
375− cinfo info ds
376− = let newps = params info
377− dsParams = map (\n -> (n, [])) ds
378− newb = addAlist dsParams (inblock info)
379− l = liftname info in
380− info { params = newps,
381− inblock = newb,
382− liftname = id -- Is this appropriate?
383− }
384−
385−-- FIXME: 'forcenames' is an almighty hack! Need a better way of
386−-- erasing non-forceable things
387−-- ^^^
388−-- TODO: the above is a comment from the past;
389−-- forcenames is probably no longer needed
390−elabCon :: ElabInfo -> SyntaxInfo -> Name -> Bool ->
391− (Docstring, [(Name, Docstring)], Name, PTerm, FC, [Name]) -> Idris (Name, Type)
392−elabCon info syn tn codata (doc, argDocs, n, t_in, fc, forcenames)
393− = do checkUndefined fc n
394− (cty, t, inacc) <- buildType info syn fc [] n (if codata then mkLazy t_in else t_in)
395− ctxt <- getContext
396− let cty' = normalise ctxt [] cty
397−
398− logLvl 2 $ show fc ++ ":Constructor " ++ show n ++ " : " ++ show t
399− logLvl 5 $ "Inaccessible args: " ++ show inacc
400− logLvl 2 $ "---> " ++ show n ++ " : " ++ show cty'
401−
402− addIBC (IBCDef n)
403− checkDocs fc argDocs t
404− addDocStr n doc argDocs
405− addIBC (IBCDoc n)
406− fputState (opt_inaccessible . ist_optimisation n) inacc
407− addIBC (IBCOpt n)
408− return (n, cty')
409− where
410− tyIs (Bind n b sc) = tyIs sc
411− tyIs t | (P _ n' _, _) <- unApply t
412− = if n' /= tn then tclift $ tfail (At fc (Msg (show n' ++ " is not " ++ show tn)))
413− else return ()
414− tyIs t = tclift $ tfail (At fc (Msg (show t ++ " is not " ++ show tn)))
415−
416− mkLazy (PPi pl n ty sc)
417− = let ty' = if getTyName ty
418− then PApp fc (PRef fc (sUN "Lazy'"))
419− [pexp (PRef fc (sUN "LazyCodata")),
420− pexp ty]
421− else ty in
422− PPi pl n ty' (mkLazy sc)
423− mkLazy t = t
424−
425− getTyName (PApp _ (PRef _ n) _) = n == nsroot tn
426− getTyName (PRef _ n) = n == nsroot tn
427− getTyName _ = False
428−
429−
430− getNamePos :: Int -> PTerm -> Name -> Maybe Int
431− getNamePos i (PPi _ n _ sc) x | n == x = Just i
432− | otherwise = getNamePos (i + 1) sc x
433− getNamePos _ _ _ = Nothing
434−
435−type EliminatorState = StateT (Map.Map String Int) Idris
436−
437−-- TODO: Rewrite everything to use idris_implicits instead of manual splitting (or in TT)
438−-- FIXME: Many things have name starting with elim internally since this was the only purpose in the first edition of the function
439−-- rename to caseFun to match updated intend
440−elabCaseFun :: Bool -> [Int] -> Name -> PTerm ->
441− [(Docstring, [(Name, Docstring)], Name, PTerm, FC, [Name])] ->
442− ElabInfo -> EliminatorState ()
443−elabCaseFun ind paramPos n ty cons info = do
444− elimLog $ "Elaborating case function"
445− put (Map.fromList $ zip (concatMap (\(_, p, _, ty, _, _) -> (map show $ boundNamesIn ty) ++ map (show . fst) p) cons ++ (map show $ boundNamesIn ty)) (repeat 0))
446− let (cnstrs, _) = splitPi ty
447− let (splittedTy@(pms, idxs)) = splitPms cnstrs
448− generalParams <- namePis False pms
449− motiveIdxs <- namePis False idxs
450− let motive = mkMotive n paramPos generalParams motiveIdxs
451− consTerms <- mapM (\(c@(_, _, cnm, _, _, _)) -> do
452− let casefunt = if ind then "elim_" else "case_"
453− name <- freshName $ casefunt ++ simpleName cnm
454− consTerm <- extractConsTerm c generalParams
455− return (name, expl, consTerm)) cons
456− scrutineeIdxs <- namePis False idxs
457− let motiveConstr = [(motiveName, expl, motive)]
458− let scrutinee = (scrutineeName, expl, applyCons n (interlievePos paramPos generalParams scrutineeIdxs 0))
459− let eliminatorTy = piConstr (generalParams ++ motiveConstr ++ consTerms ++ scrutineeIdxs ++ [scrutinee]) (applyMotive (map (\(n,_,_) -> PRef elimFC n) scrutineeIdxs) (PRef elimFC scrutineeName))
460− let eliminatorTyDecl = PTy (parseDocstring . T.pack $ show n) [] defaultSyntax elimFC [TotalFn] elimDeclName eliminatorTy
461− let clauseConsElimArgs = map getPiName consTerms
462− let clauseGeneralArgs' = map getPiName generalParams ++ [motiveName] ++ clauseConsElimArgs
463− let clauseGeneralArgs = map (\arg -> pexp (PRef elimFC arg)) clauseGeneralArgs'
464− let elimSig = "-- case function signature: " ++ showTmImpls eliminatorTy
465− elimLog elimSig
466− eliminatorClauses <- mapM (\(cns, cnsElim) -> generateEliminatorClauses cns cnsElim clauseGeneralArgs generalParams) (zip cons clauseConsElimArgs)
467− let eliminatorDef = PClauses emptyFC [TotalFn] elimDeclName eliminatorClauses
468− elimLog $ "-- case function definition: " ++ (show . showDeclImp verbosePPOption) eliminatorDef
469− State.lift $ idrisCatch (elabDecl EAll info eliminatorTyDecl) (\err -> return ())
470− -- Do not elaborate clauses if there aren't any
471− case eliminatorClauses of
472− [] -> State.lift $ solveDeferred elimDeclName -- Remove meta-variable for type
473− _ -> State.lift $ idrisCatch (elabDecl EAll info eliminatorDef) (\err -> return ())
474− where elimLog :: String -> EliminatorState ()
475− elimLog s = State.lift (logLvl 2 s)
476−
477− elimFC :: FC
478− elimFC = fileFC "(casefun)"
479−
480− elimDeclName :: Name
481− elimDeclName = if ind then SN . ElimN $ n else SN . CaseN $ n
482−
483− applyNS :: Name -> [String] -> Name
484− applyNS n [] = n
485− applyNS n ns = sNS n ns
486−
487− splitPi :: PTerm -> ([(Name, Plicity, PTerm)], PTerm)
488− splitPi = splitPi' []
489− where splitPi' :: [(Name, Plicity, PTerm)] -> PTerm -> ([(Name, Plicity, PTerm)], PTerm)
490− splitPi' acc (PPi pl n tyl tyr) = splitPi' ((n, pl, tyl):acc) tyr
491− splitPi' acc t = (reverse acc, t)
492−
493− splitPms :: [(Name, Plicity, PTerm)] -> ([(Name, Plicity, PTerm)], [(Name, Plicity, PTerm)])
494− splitPms cnstrs = (map fst pms, map fst idxs)
495− where (pms, idxs) = partition (\c -> snd c `elem` paramPos) (zip cnstrs [0..])
496−
497− isMachineGenerated :: Name -> Bool
498− isMachineGenerated (MN _ _) = True
499− isMachineGenerated _ = False
500−
501− namePis :: Bool -> [(Name, Plicity, PTerm)] -> EliminatorState [(Name, Plicity, PTerm)]
502− namePis keepOld pms = do names <- mapM (mkPiName keepOld) pms
503− let oldNames = map fst names
504− let params = map snd names
505− return $ map (\(n, pl, ty) -> (n, pl, removeParamPis oldNames params ty)) params
506−
507− mkPiName :: Bool -> (Name, Plicity, PTerm) -> EliminatorState (Name, (Name, Plicity, PTerm))
508− mkPiName keepOld (n, pl, piarg) | not (isMachineGenerated n) && keepOld = do return (n, (n, pl, piarg))
509− mkPiName _ (oldName, pl, piarg) = do name <- freshName $ keyOf piarg
510− return (oldName, (name, pl, piarg))
511− where keyOf :: PTerm -> String
512− keyOf (PRef _ name) | isLetter (nameStart name) = (toLower $ nameStart name):"__"
513− keyOf (PApp _ tyf _) = keyOf tyf
514− keyOf PType = "ty__"
515− keyOf _ = "carg__"
516− nameStart :: Name -> Char
517− nameStart n = nameStart' (simpleName n)
518− where nameStart' :: String -> Char
519− nameStart' "" = ' '
520− nameStart' ns = head ns
521−
522− simpleName :: Name -> String
523− simpleName (NS n _) = simpleName n
524− simpleName (MN i n) = str n ++ show i
525− simpleName n = show n
526−
527− nameSpaces :: Name -> [String]
528− nameSpaces (NS _ ns) = map str ns
529− nameSpaces _ = []
530−
531− freshName :: String -> EliminatorState Name
532− freshName key = do
533− nameMap <- get
534− let i = fromMaybe 0 (Map.lookup key nameMap)
535− let name = uniqueName (sUN (key ++ show i)) (map (\(nm, nb) -> sUN (nm ++ show nb)) $ Map.toList nameMap)
536− put $ Map.insert key (i+1) nameMap
537− return name
538−
539− scrutineeName :: Name
540− scrutineeName = sUN "scrutinee"
541
61
542− scrutineeArgName :: Name
62+-- Top level elaborator info, supporting recursive elaboration
543− scrutineeArgName = sUN "scrutineeArg"
63+recinfo :: ElabInfo
544−
64+recinfo = EInfo [] emptyContext id Nothing elabDecl'
545− motiveName :: Name
546− motiveName = sUN "prop"
547−
548− mkMotive :: Name -> [Int] -> [(Name, Plicity, PTerm)] -> [(Name, Plicity, PTerm)] -> PTerm
549− mkMotive n paramPos params indicies =
550− let scrutineeTy = (scrutineeArgName, expl, applyCons n (interlievePos paramPos params indicies 0))
551− in piConstr (indicies ++ [scrutineeTy]) PType
552−
553− piConstr :: [(Name, Plicity, PTerm)] -> PTerm -> PTerm
554− piConstr [] ty = ty
555− piConstr ((n, pl, tyb):tyr) ty = PPi pl n tyb (piConstr tyr ty)
556−
557− interlievePos :: [Int] -> [a] -> [a] -> Int -> [a]
558− interlievePos idxs [] l2 i = l2
559− interlievePos idxs l1 [] i = l1
560− interlievePos idxs (x:xs) l2 i | i `elem` idxs = x:(interlievePos idxs xs l2 (i+1))
561− interlievePos idxs l1 (y:ys) i = y:(interlievePos idxs l1 ys (i+1))
562−
563− replaceParams :: [Int] -> [(Name, Plicity, PTerm)] -> PTerm -> PTerm
564− replaceParams paramPos params cns =
565− let (_, cnsResTy) = splitPi cns
566− in case cnsResTy of
567− PApp _ _ args ->
568− let oldParams = paramNamesOf 0 paramPos args
569− in removeParamPis oldParams params cns
570− _ -> cns
571−
572− removeParamPis :: [Name] -> [(Name, Plicity, PTerm)] -> PTerm -> PTerm
573− removeParamPis oldParams params (PPi pl n tyb tyr) =
574− case findIndex (== n) oldParams of
575− Nothing -> (PPi pl n (removeParamPis oldParams params tyb) (removeParamPis oldParams params tyr))
576− Just i -> (removeParamPis oldParams params tyr)
577− removeParamPis oldParams params (PRef _ n) =
578− case findIndex (== n) oldParams of
579− Nothing -> (PRef elimFC n)
580− Just i -> let (newname,_,_) = params !! i in (PRef elimFC (newname))
581− removeParamPis oldParams params (PApp _ cns args) =
582− PApp elimFC (removeParamPis oldParams params cns) $ replaceParamArgs args
583− where replaceParamArgs :: [PArg] -> [PArg]
584− replaceParamArgs [] = []
585− replaceParamArgs (arg:args) =
586− case extractName (getTm arg) of
587− [] -> arg:replaceParamArgs args
588− [n] ->
589− case findIndex (== n) oldParams of
590− Nothing -> arg:replaceParamArgs args
591− Just i -> let (newname,_,_) = params !! i in arg {getTm = PRef elimFC newname}:replaceParamArgs args
592− removeParamPis oldParams params t = t
593−
594− paramNamesOf :: Int -> [Int] -> [PArg] -> [Name]
595− paramNamesOf i paramPos [] = []
596− paramNamesOf i paramPos (arg:args) = (if i `elem` paramPos then extractName (getTm arg) else []) ++ paramNamesOf (i+1) paramPos args
597−
598− extractName :: PTerm -> [Name]
599− extractName (PRef _ n) = [n]
600− extractName _ = []
601−
602− splitArgPms :: PTerm -> ([PTerm], [PTerm])
603− splitArgPms (PApp _ f args) = splitArgPms' args
604− where splitArgPms' :: [PArg] -> ([PTerm], [PTerm])
605− splitArgPms' cnstrs = (map (getTm . fst) pms, map (getTm . fst) idxs)
606− where (pms, idxs) = partition (\c -> snd c `elem` paramPos) (zip cnstrs [0..])
607− splitArgPms _ = ([],[])
608−
609−
610− implicitIndexes :: (Docstring, Name, PTerm, FC, [Name]) -> EliminatorState [(Name, Plicity, PTerm)]
611− implicitIndexes (cns@(doc, cnm, ty, fc, fs)) = do
612− i <- State.lift getIState
613− implargs' <- case lookupCtxt cnm (idris_implicits i) of
614− [] -> do fail $ "Error while showing implicits for " ++ show cnm
615− [args] -> do return args
616− _ -> do fail $ "Ambigous name for " ++ show cnm
617− let implargs = mapMaybe convertImplPi implargs'
618− let (_, cnsResTy) = splitPi ty
619− case cnsResTy of
620− PApp _ _ args ->
621− let oldParams = paramNamesOf 0 paramPos args
622− in return $ filter (\(n,_,_) -> not (n `elem` oldParams))implargs
623− _ -> return implargs
624−
625− extractConsTerm :: (Docstring, [(Name, Docstring)], Name, PTerm, FC, [Name]) -> [(Name, Plicity, PTerm)] -> EliminatorState PTerm
626− extractConsTerm (doc, argDocs, cnm, ty, fc, fs) generalParameters = do
627− let cons' = replaceParams paramPos generalParameters ty
628− let (args, resTy) = splitPi cons'
629− implidxs <- implicitIndexes (doc, cnm, ty, fc, fs)
630− consArgs <- namePis False args
631− let recArgs = findRecArgs consArgs
632− let recMotives = if ind then map applyRecMotive recArgs else []
633− let (_, consIdxs) = splitArgPms resTy
634− return $ piConstr (implidxs ++ consArgs ++ recMotives) (applyMotive consIdxs (applyCons cnm consArgs))
635− where applyRecMotive :: (Name, Plicity, PTerm) -> (Name, Plicity, PTerm)
636− applyRecMotive (n,_,ty) = (sUN $ "ih" ++ simpleName n, expl, applyMotive idxs (PRef elimFC n))
637− where (_, idxs) = splitArgPms ty
638−
639− findRecArgs :: [(Name, Plicity, PTerm)] -> [(Name, Plicity, PTerm)]
640− findRecArgs [] = []
641− findRecArgs (ty@(_,_,PRef _ tn):rs) | simpleName tn == simpleName n = ty:findRecArgs rs
642− findRecArgs (ty@(_,_,PApp _ (PRef _ tn) _):rs) | simpleName tn == simpleName n = ty:findRecArgs rs
643− findRecArgs (ty:rs) = findRecArgs rs
644−
645− applyCons :: Name -> [(Name, Plicity, PTerm)] -> PTerm
646− applyCons tn targs = PApp elimFC (PRef elimFC tn) (map convertArg targs)
647−
648− convertArg :: (Name, Plicity, PTerm) -> PArg
649− convertArg (n, _, _) = pexp (PRef elimFC n)
650−
651− applyMotive :: [PTerm] -> PTerm -> PTerm
652− applyMotive idxs t = PApp elimFC (PRef elimFC motiveName) (map pexp idxs ++ [pexp t])
653−
654− getPiName :: (Name, Plicity, PTerm) -> Name
655− getPiName (name,_,_) = name
656−
657− convertImplPi :: PArg -> Maybe (Name, Plicity, PTerm)
658− convertImplPi (PImp {getTm = t, pname = n}) = Just (n, expl, t)
659− convertImplPi _ = Nothing
660−
661− generateEliminatorClauses :: (Docstring, [(Name, Docstring)], Name, PTerm, FC, [Name]) -> Name -> [PArg] -> [(Name, Plicity, PTerm)] -> EliminatorState PClause
662− generateEliminatorClauses (doc, _, cnm, ty, fc, fs) cnsElim generalArgs generalParameters = do
663− let cons' = replaceParams paramPos generalParameters ty
664− let (args, resTy) = splitPi cons'
665− i <- State.lift getIState
666− implidxs <- implicitIndexes (doc, cnm, ty, fc, fs)
667− let (_, generalIdxs') = splitArgPms resTy
668− let generalIdxs = map pexp generalIdxs'
669− consArgs <- namePis False args
670− let lhsPattern = PApp elimFC (PRef elimFC elimDeclName) (generalArgs ++ generalIdxs ++ [pexp $ applyCons cnm consArgs])
671− let recArgs = findRecArgs consArgs
672− let recElims = if ind then map applyRecElim recArgs else []
673− let rhsExpr = PApp elimFC (PRef elimFC cnsElim) (map convertArg implidxs ++ map convertArg consArgs ++ recElims)
674− return $ PClause elimFC elimDeclName lhsPattern [] rhsExpr []
675− where applyRecElim :: (Name, Plicity, PTerm) -> PArg
676− applyRecElim (constr@(recCnm,_,recTy)) = pexp $ PApp elimFC (PRef elimFC elimDeclName) (generalArgs ++ map pexp idxs ++ [pexp $ PRef elimFC recCnm])
677− where (_, idxs) = splitArgPms recTy
678
65
679-- | Elaborate primitives
66-- | Elaborate primitives
680−
681elabPrims :: Idris ()
67elabPrims :: Idris ()
682−elabPrims = do mapM_ (elabDecl EAll toplevel)
68+elabPrims = do mapM_ (elabDecl' EAll recinfo)
683 (map (\(opt, decl, docs, argdocs) -> PData docs argdocs defaultSyntax (fileFC "builtin") opt decl)
69 (map (\(opt, decl, docs, argdocs) -> PData docs argdocs defaultSyntax (fileFC "builtin") opt decl)
684 (zip4
70 (zip4
685 [inferOpts, unitOpts, falseOpts, pairOpts, eqOpts]
71 [inferOpts, unitOpts, falseOpts, pairOpts, eqOpts]
@@ -687,7 +73,7 @@ elabPrims = do mapM_ (elabDecl EAll toplevel)
687 [emptyDocstring, unitDoc, falseDoc, pairDoc, eqDoc]
73 [emptyDocstring, unitDoc, falseDoc, pairDoc, eqDoc]
688 [[], [], [], pairParamDoc, eqParamDoc]))
74 [[], [], [], pairParamDoc, eqParamDoc]))
689 addNameHint eqTy (sUN "prf")
75 addNameHint eqTy (sUN "prf")
690− elabDecl EAll toplevel elimDecl
76+ elabDecl' EAll recinfo elimDecl
691 mapM_ elabPrim primitives
77 mapM_ elabPrim primitives
692 -- Special case prim__believe_me because it doesn't work on just constants
78 -- Special case prim__believe_me because it doesn't work on just constants
693 elabBelieveMe
79 elabBelieveMe
@@ -748,71 +134,6 @@ elabPrims = do mapM_ (elabDecl EAll toplevel)
748 idris_scprims = (synEq, (4, LNoOp)) : idris_scprims i
134 idris_scprims = (synEq, (4, LNoOp)) : idris_scprims i
749 }
135 }
750
136
751−
752−-- | Elaborate a type provider
753−elabProvider :: ElabInfo -> SyntaxInfo -> FC -> ProvideWhat -> Name -> Idris ()
754−elabProvider info syn fc what n
755− = do i <- getIState
756− -- Ensure that the experimental extension is enabled
757− unless (TypeProviders `elem` idris_language_extensions i) $
758− ifail $ "Failed to define type provider \"" ++ show n ++
759− "\".\nYou must turn on the TypeProviders extension."
760−
761− ctxt <- getContext
762−
763− -- First elaborate the expected type (and check that it's a type)
764− -- The goal type for a postulate is always Type.
765− (ty', typ) <- case what of
766− ProvTerm ty p -> elabVal toplevel ERHS ty
767− ProvPostulate _ -> elabVal toplevel ERHS PType
768− unless (isTType typ) $
769− ifail ("Expected a type, got " ++ show ty' ++ " : " ++ show typ)
770−
771− -- Elaborate the provider term to TT and check that the type matches
772− (e, et) <- case what of
773− ProvTerm _ tm -> elabVal toplevel ERHS tm
774− ProvPostulate tm -> elabVal toplevel ERHS tm
775− unless (isProviderOf (normalise ctxt [] ty') et) $
776− ifail $ "Expected provider type IO (Provider (" ++
777− show ty' ++ "))" ++ ", got " ++ show et ++ " instead."
778−
779− -- Execute the type provider and normalise the result
780− -- use 'run__provider' to convert to a primitive IO action
781−
782− rhs <- execute (mkApp (P Ref (sUN "run__provider") Erased)
783− [Erased, e])
784− let rhs' = normalise ctxt [] rhs
785− logLvl 3 $ "Normalised " ++ show n ++ "'s RHS to " ++ show rhs
786−
787− -- Extract the provided term or postulate from the type provider
788− provided <- getProvided fc rhs'
789−
790− case provided of
791− Provide tm
792− | ProvTerm ty _ <- what ->
793− do -- Finally add a top-level definition of the provided term
794− elabType info syn emptyDocstring [] fc [] n ty
795− elabClauses info fc [] n [PClause fc n (PApp fc (PRef fc n) []) [] (delab i tm) []]
796− logLvl 3 $ "Elaborated provider " ++ show n ++ " as: " ++ show tm
797− | ProvPostulate _ <- what ->
798− do -- Add the postulate
799− elabPostulate info syn (parseDocstring $ T.pack "Provided postulate") fc [] n (delab i tm)
800− logLvl 3 $ "Elaborated provided postulate " ++ show n
801− | otherwise ->
802− ierror . Msg $ "Attempted to provide a postulate where a term was expected."
803−
804− where isTType :: TT Name -> Bool
805− isTType (TType _) = True
806− isTType _ = False
807−
808− isProviderOf :: TT Name -> TT Name -> Bool
809− isProviderOf tp prov
810− | (P _ (UN io) _, [prov']) <- unApply prov
811− , (P _ (NS (UN prov) [provs]) _, [tp']) <- unApply prov'
812− , tp == tp', io == txt "IO"
813− , prov == txt "Provider" && provs == txt "Providers" = True
814− isProviderOf _ _ = False
815−
816elabTransform :: ElabInfo -> FC -> Bool -> PTerm -> PTerm -> Idris ()
137elabTransform :: ElabInfo -> FC -> Bool -> PTerm -> PTerm -> Idris ()
817elabTransform info fc safe lhs_in rhs_in
138elabTransform info fc safe lhs_in rhs_in
818 = do ctxt <- getContext
139 = do ctxt <- getContext
@@ -845,1518 +166,13 @@ elabTransform info fc safe lhs_in rhs_in
845 addTrans (clhs_tm, crhs_tm)
166 addTrans (clhs_tm, crhs_tm)
846 addIBC (IBCTrans (clhs_tm, crhs_tm))
167 addIBC (IBCTrans (clhs_tm, crhs_tm))
847
168
848−
849−elabRecord :: ElabInfo -> SyntaxInfo -> Docstring -> FC -> Name ->
850− PTerm -> DataOpts -> Docstring -> Name -> PTerm -> Idris ()
851−elabRecord info syn doc fc tyn ty opts cdoc cn cty_in
852− = do elabData info syn doc [] fc opts (PDatadecl tyn ty [(cdoc, [], cn, cty_in, fc, [])])
853− -- TODO think: something more in info?
854− cty' <- implicit info syn cn cty_in
855− i <- getIState
856−
857− -- get bound implicits and propagate to setters (in case they
858− -- provide useful information for inference)
859− let extraImpls = getBoundImpls cty'
860−
861− cty <- case lookupTy cn (tt_ctxt i) of
862− [t] -> return (delab i t)
863− _ -> ifail "Something went inexplicably wrong"
864− cimp <- case lookupCtxt cn (idris_implicits i) of
865− [imps] -> return imps
866− ppos <- case lookupCtxt tyn (idris_datatypes i) of
867− [ti] -> return $ param_pos ti
868− let cty_imp = renameBs cimp cty
869− let ptys = getProjs [] cty_imp
870− let ptys_u = getProjs [] cty
871− let recty = getRecTy cty_imp
872− let recty_u = getRecTy cty
873−
874− let paramNames = getPNames recty ppos
875−
876− -- rename indices when we generate the getter/setter types, so
877− -- that they don't clash with the names of the projections
878− -- we're generating
879− let index_names_in = getRecNameMap "_in" ppos recty
880− let recty_in = substMatches index_names_in recty
881−
882− logLvl 3 $ show (recty, recty_u, ppos, paramNames, ptys)
883− -- Substitute indices with projection functions, and parameters with
884− -- the updated parameter name
885− let substs = map (\ (n, _) ->
886− if n `elem` paramNames
887− then (n, PRef fc (mkp n))
888− else (n, PApp fc (PRef fc n)
889− [pexp (PRef fc rec)]))
890− ptys
891−
892− -- Generate projection functions
893− proj_decls <- mapM (mkProj recty_in substs cimp) (zip ptys [0..])
894− logLvl 3 $ show proj_decls
895− let nonImp = mapMaybe isNonImp (zip cimp ptys_u)
896− let implBinds = getImplB id cty'
897−
898− -- Generate update functions
899− update_decls <- mapM (mkUpdate recty_u index_names_in extraImpls
900− (getFieldNames cty')
901− implBinds (length nonImp)) (zip nonImp [0..])
902− mapM_ (elabDecl EAll info) (concat proj_decls)
903− logLvl 3 $ show update_decls
904− mapM_ (tryElabDecl info) (update_decls)
905− where
906−-- syn = syn_in { syn_namespace = show (nsroot tyn) : syn_namespace syn_in }
907−
908− isNonImp (PExp _ _ _ _, a) = Just a
909− isNonImp _ = Nothing
910−
911− getPNames (PApp _ _ as) ppos = getpn as ppos
912− where
913− getpn as [] = []
914− getpn as (i:is) | length as > i,
915− PRef _ n <- getTm (as!!i) = n : getpn as is
916− | otherwise = getpn as is
917− getPNames _ _ = []
918−
919− tryElabDecl info (fn, ty, val)
920− = do i <- getIState
921− idrisCatch (do elabDecl' EAll info ty
922− elabDecl' EAll info val)
923− (\v -> do iputStrLn $ show fc ++
924− ":Warning - can't generate setter for " ++
925− show fn ++ " (" ++ show ty ++ ")"
926−-- ++ "\n" ++ pshow i v
927− putIState i)
928−
929− getBoundImpls (PPi (Imp _ _ _) n ty sc) = (n, ty) : getBoundImpls sc
930− getBoundImpls _ = []
931−
932− getImplB k (PPi (Imp l s _) n Placeholder sc)
933− = getImplB k sc
934− getImplB k (PPi (Imp l s p) n ty sc)
935− = getImplB (\x -> k (PPi (Imp l s p) n ty x)) sc
936− getImplB k (PPi _ n ty sc)
937− = getImplB k sc
938− getImplB k _ = k
939−
940− renameBs (PImp _ _ _ _ _ : ps) (PPi p n ty s)
941− = PPi p (mkImp n) ty (renameBs ps (substMatch n (PRef fc (mkImp n)) s))
942− renameBs (_:ps) (PPi p n ty s) = PPi p n ty (renameBs ps s)
943− renameBs _ t = t
944−
945− getProjs acc (PPi _ n ty s) = getProjs ((n, ty) : acc) s
946− getProjs acc r = reverse acc
947−
948− getFieldNames (PPi (Exp _ _ _) n _ s) = n : getFieldNames s
949− getFieldNames (PPi _ _ _ s) = getFieldNames s
950− getFieldNames _ = []
951−
952− getRecTy (PPi _ n ty s) = getRecTy s
953− getRecTy t = t
954−
955− -- make sure we pick a consistent name for parameters; any name will do
956− -- otherwise
957− getRecNameMap x ppos (PApp fc t args)
958− = mapMaybe toMN (zip [0..] (map getTm args))
959− where
960− toMN (i, PRef fc n)
961− | i `elem` ppos = Just (n, PRef fc (mkp n))
962− | otherwise = Just (n, PRef fc (sMN 0 (show n ++ x)))
963− toMN _ = Nothing
964− getRecNameMap x _ _ = []
965−
966− rec = sMN 0 "rec"
967−
968− -- only UNs propagate properly as parameters (bit of a hack then...)
969− mkp (UN n) = sUN ("_p_" ++ str n)
970− mkp (MN i n) = sMN i ("p_" ++ str n)
971− mkp (NS n s) = NS (mkp n) s
972−
973− mkImp (UN n) = sUN ("implicit_" ++ str n)
974− mkImp (MN i n) = sMN i ("implicit_" ++ str n)
975− mkImp (NS n s) = NS (mkImp n) s
976−
977− mkType (UN n) = sUN ("set_" ++ str n)
978− mkType (MN i n) = sMN i ("set_" ++ str n)
979− mkType (NS n s) = NS (mkType n) s
980−
981− mkProj recty substs cimp ((pn_in, pty), pos)
982− = do let pn = expandNS syn pn_in -- projection name
983− -- use pn_in in the indices, consistently, to avoid clash
984− let pfnTy = PTy emptyDocstring [] defaultSyntax fc [] pn
985− (PPi expl rec recty
986− (substMatches substs pty))
987− let pls = repeat Placeholder
988− let before = pos
989− let after = length substs - (pos + 1)
990− let args = take before pls ++ PRef fc (mkp pn_in) : take after pls
991− let iargs = map implicitise (zip cimp args)
992− let lhs = PApp fc (PRef fc pn)
993− [pexp (PApp fc (PRef fc cn) iargs)]
994− let rhs = PRef fc (mkp pn_in)
995− let pclause = PClause fc pn lhs [] rhs []
996− return [pfnTy, PClauses fc [] pn [pclause]]
997−
998− implicitise (pa, t) = pa { getTm = t }
999−
1000− -- If the 'pty' we're updating includes anything in 'substs', we're
1001− -- updating the type as well, so use recty', otherwise just use
1002− -- recty
1003− mkUpdate recty inames extras fnames k num ((pn, pty), pos)
1004− = do let setname = expandNS syn $ mkType pn
1005− let valname = sMN 0 "updateval"
1006− let pn_out = sMN 0 (show pn ++ "_out")
1007− let pn_in = sMN 0 (show pn ++ "_in")
1008− let recty_in = substMatches [(pn, PRef fc pn_in)] recty
1009− let recty_out = substMatches [(pn, PRef fc pn_out)] recty
1010− let pt = substMatches inames $
1011− k (implBindUp extras inames (PPi expl pn_out pty
1012− (PPi expl rec recty_in recty_out)))
1013− let pfnTy = PTy emptyDocstring [] defaultSyntax fc [] setname pt
1014−-- let pls = map (\x -> PRef fc (sMN x ("field" ++ show x))) [0..num-1]
1015− let inames_imp = map (\ (x,_) -> (x, Placeholder)) inames
1016− let pls = map (\x -> substMatches inames_imp (PRef fc x)) fnames
1017− let lhsArgs = pls
1018− let rhsArgs = take pos pls ++ (PRef fc valname) :
1019− drop (pos + 1) pls
1020− let before = pos
1021− let pclause = PClause fc setname (PApp fc (PRef fc setname)
1022− [pexp (PRef fc valname),
1023− pexp (PApp fc (PRef fc cn)
1024− (map pexp lhsArgs))])
1025− []
1026− (PApp fc (PRef fc cn)
1027− (map pexp rhsArgs)) []
1028− return (pn, pfnTy, PClauses fc [] setname [pclause])
1029−
1030− implBindUp [] is t = t
1031− implBindUp ((n, ty):ns) is t
1032− = let n' = case lookup n is of
1033− Just (PRef _ x) -> x
1034− _ -> n in
1035− if n `elem` allNamesIn t
1036− then PPi impl n' ty (implBindUp ns is t)
1037− else implBindUp ns is t
1038−
1039−-- | Elaborate a collection of left-hand and right-hand pairs - that is, a
1040−-- top-level definition.
1041−elabClauses :: ElabInfo -> FC -> FnOpts -> Name -> [PClause] -> Idris ()
1042−elabClauses info fc opts n_in cs = let n = liftname info n_in in
1043− do ctxt <- getContext
1044− ist <- getIState
1045− inacc <- map fst <$> fgetState (opt_inaccessible . ist_optimisation n)
1046−
1047− -- Check n actually exists, with no definition yet
1048− let tys = lookupTy n ctxt
1049− let reflect = Reflection `elem` opts
1050− checkUndefined n ctxt
1051− unless (length tys > 1) $ do
1052− fty <- case tys of
1053− [] -> -- TODO: turn into a CAF if there's no arguments
1054− -- question: CAFs in where blocks?
1055− tclift $ tfail $ At fc (NoTypeDecl n)
1056− [ty] -> return ty
1057− let atys = map snd (getArgTys fty)
1058− cs_elab <- mapM (elabClause info opts)
1059− (zip [0..] cs)
1060− let (pats_in, cs_full) = unzip cs_elab
1061−
1062− logLvl 3 $ "Elaborated patterns:\n" ++ show pats_in
1063−
1064− solveDeferred n
1065−
1066− -- just ensure that the structure exists
1067− fmodifyState (ist_optimisation n) id
1068− addIBC (IBCOpt n)
1069−
1070− ist <- getIState
1071− let pats = map (simple_lhs (tt_ctxt ist)) $ doTransforms ist pats_in
1072−
1073− -- logLvl 3 (showSep "\n" (map (\ (l,r) ->
1074− -- show l ++ " = " ++
1075− -- show r) pats))
1076− let tcase = opt_typecase (idris_options ist)
1077−
1078− -- Summary of what's about to happen: Definitions go:
1079− --
1080− -- pats_in -> pats -> pdef -> pdef'
1081−
1082− -- addCaseDef builds case trees from <pdef> and <pdef'>
1083−
1084− -- pdef is the compile-time pattern definition.
1085− -- This will get further optimised for run-time, and, separately,
1086− -- further inlined to help with totality checking.
1087− let pdef = map debind pats
1088−
1089− logLvl 5 $ "Initial typechecked patterns:\n" ++ show pats
1090− logLvl 5 $ "Initial typechecked pattern def:\n" ++ show pdef
1091−
1092− -- Look for 'static' names and generate new specialised
1093− -- definitions for them
1094−
1095− mapM_ (\ e -> case e of
1096− Left _ -> return ()
1097− Right (l, r) -> elabPE info fc n r) pats
1098−
1099− -- NOTE: Need to store original definition so that proofs which
1100− -- rely on its structure aren't affected by any changes to the
1101− -- inliner. Just use the inlined version to generate pdef' and to
1102− -- help with later inlinings.
1103−
1104− ist <- getIState
1105− let pdef_inl = inlineDef ist pdef
1106−
1107− numArgs <- tclift $ sameLength pdef
1108−
1109− case specNames opts of
1110− Just _ -> logLvl 5 $ "Partially evaluated:\n" ++ show pats
1111− _ -> return ()
1112−
1113− erInfo <- getErasureInfo <$> getIState
1114− tree@(CaseDef scargs sc _) <- tclift $
1115− simpleCase tcase False reflect CompileTime fc inacc atys pdef erInfo
1116− cov <- coverage
1117− pmissing <-
1118− if cov && not (hasDefault cs)
1119− then do missing <- genClauses fc n (map getLHS pdef) cs_full
1120− -- missing <- genMissing n scargs sc
1121− missing' <- filterM (checkPossible info fc True n) missing
1122− let clhs = map getLHS pdef
1123− logLvl 2 $ "Must be unreachable:\n" ++
1124− showSep "\n" (map showTmImpls missing') ++
1125− "\nAgainst: " ++
1126− showSep "\n" (map (\t -> showTmImpls (delab ist t)) (map getLHS pdef))
1127− -- filter out anything in missing' which is
1128− -- matched by any of clhs. This might happen since
1129− -- unification may force a variable to take a
1130− -- particular form, rather than force a case
1131− -- to be impossible.
1132− return (filter (noMatch ist clhs) missing')
1133− else return []
1134− let pcover = null pmissing
1135−
1136− -- pdef' is the version that gets compiled for run-time
1137− pdef_in' <- applyOpts pdef
1138− let pdef' = map (simple_rt (tt_ctxt ist)) pdef_in'
1139−
1140− logLvl 5 $ "After data structure transformations:\n" ++ show pdef'
1141−
1142− ist <- getIState
1143− -- let wf = wellFounded ist n sc
1144− let tot = if pcover || AssertTotal `elem` opts
1145− then Unchecked -- finish checking later
1146− else Partial NotCovering -- already know it's not total
1147−
1148− -- case lookupCtxt (namespace info) n (idris_flags ist) of
1149− -- [fs] -> if TotalFn `elem` fs
1150− -- then case tot of
1151− -- Total _ -> return ()
1152− -- t -> tclift $ tfail (At fc (Msg (show n ++ " is " ++ show t)))
1153− -- else return ()
1154− -- _ -> return ()
1155− case tree of
1156− CaseDef _ _ [] -> return ()
1157− CaseDef _ _ xs -> mapM_ (\x ->
1158− iputStrLn $ show fc ++
1159− ":warning - Unreachable case: " ++
1160− show (delab ist x)) xs
1161− let knowncovering = (pcover && cov) || AssertTotal `elem` opts
1162−
1163− tree' <- tclift $ simpleCase tcase knowncovering reflect
1164− RunTime fc inacc atys pdef' erInfo
1165− logLvl 3 $ "Unoptimised " ++ show n ++ ": " ++ show tree
1166− logLvl 3 $ "Optimised: " ++ show tree'
1167− ctxt <- getContext
1168− ist <- getIState
1169− let opt = idris_optimisation ist
1170− putIState (ist { idris_patdefs = addDef n (force pdef', force pmissing)
1171− (idris_patdefs ist) })
1172− let caseInfo = CaseInfo (inlinable opts) (dictionary opts)
1173− case lookupTy n ctxt of
1174− [ty] -> do updateContext (addCasedef n erInfo caseInfo
1175− tcase knowncovering
1176− reflect
1177− (AssertTotal `elem` opts)
1178− atys
1179− inacc
1180− pats
1181− pdef pdef pdef_inl pdef' ty)
1182− addIBC (IBCDef n)
1183− setTotality n tot
1184− when (not reflect) $ do totcheck (fc, n)
1185− defer_totcheck (fc, n)
1186− when (tot /= Unchecked) $ addIBC (IBCTotal n tot)
1187− i <- getIState
1188− case lookupDef n (tt_ctxt i) of
1189− (CaseOp _ _ _ _ _ cd : _) ->
1190− let (scargs, sc) = cases_compiletime cd
1191− (scargs', sc') = cases_runtime cd in
1192− do let calls = findCalls sc' scargs'
1193− let used = findUsedArgs sc' scargs'
1194− -- let scg = buildSCG i sc scargs
1195− -- add SCG later, when checking totality
1196− let cg = CGInfo scargs' calls [] used [] -- TODO: remove this, not needed anymore
1197− logLvl 2 $ "Called names: " ++ show cg
1198− addToCG n cg
1199− addToCalledG n (nub (map fst calls)) -- plus names in type!
1200− addIBC (IBCCG n)
1201− _ -> return ()
1202− return ()
1203− -- addIBC (IBCTotal n tot)
1204− [] -> return ()
1205− -- Check it's covering, if 'covering' option is used. Chase
1206− -- all called functions, and fail if any of them are also
1207− -- 'Partial NotCovering'
1208− when (CoveringFn `elem` opts) $ checkAllCovering fc [] n n
1209− where
1210− noMatch i cs tm = all (\x -> case matchClause i (delab' i x True True) tm of
1211− Right _ -> False
1212− Left miss -> True) cs
1213−
1214− checkUndefined n ctxt = case lookupDef n ctxt of
1215− [] -> return ()
1216− [TyDecl _ _] -> return ()
1217− _ -> tclift $ tfail (At fc (AlreadyDefined n))
1218−
1219− debind (Right (x, y)) = let (vs, x') = depat [] x
1220− (_, y') = depat [] y in
1221− (vs, x', y')
1222− debind (Left x) = let (vs, x') = depat [] x in
1223− (vs, x', Impossible)
1224−
1225− depat acc (Bind n (PVar t) sc) = depat (n : acc) (instantiate (P Bound n t) sc)
1226− depat acc x = (acc, x)
1227−
1228− hasDefault cs | (PClause _ _ last _ _ _ :_) <- reverse cs
1229− , (PApp fn s args) <- last = all ((==Placeholder) . getTm) args
1230− hasDefault _ = False
1231−
1232− getLHS (_, l, _) = l
1233−
1234− simple_lhs ctxt (Right (x, y)) = Right (normalise ctxt [] x,
1235− force (normalisePats ctxt [] y))
1236− simple_lhs ctxt t = t
1237−
1238− simple_rt ctxt (p, x, y) = (p, x, force (uniqueBinders p
1239− (rt_simplify ctxt [] y)))
1240−
1241− -- this is so pattern types are in the right form for erasure
1242− normalisePats ctxt env (Bind n (PVar t) sc)
1243− = let t' = normalise ctxt env t in
1244− Bind n (PVar t') (normalisePats ctxt ((n, PVar t') : env) sc)
1245− normalisePats ctxt env (Bind n (PVTy t) sc)
1246− = let t' = normalise ctxt env t in
1247− Bind n (PVTy t') (normalisePats ctxt ((n, PVar t') : env) sc)
1248− normalisePats ctxt env t = t
1249−
1250− specNames [] = Nothing
1251− specNames (Specialise ns : _) = Just ns
1252− specNames (_ : xs) = specNames xs
1253−
1254− sameLength ((_, x, _) : xs)
1255− = do l <- sameLength xs
1256− let (f, as) = unApply x
1257− if (null xs || l == length as) then return (length as)
1258− else tfail (At fc (Msg "Clauses have differing numbers of arguments "))
1259− sameLength [] = return 0
1260−
1261− -- apply all transformations (just specialisation for now, add
1262− -- user defined transformation rules later)
1263− doTransforms ist pats =
1264− case specNames opts of
1265− Nothing -> pats
1266− Just ns -> partial_eval (tt_ctxt ist) ns pats
1267−
1268−-- | Find 'static' applications in a term and partially evaluate them
1269−elabPE :: ElabInfo -> FC -> Name -> Term -> Idris ()
1270−elabPE info fc caller r =
1271− do ist <- getIState
1272− let sa = getSpecApps ist [] r
1273− mapM_ (mkSpecialised ist) sa
1274− where
1275− -- TODO: Add a PTerm level transformation rule, which is basically the
1276− -- new definition in reverse (before specialising it).
1277− -- RHS => LHS where implicit arguments are left blank in the
1278− -- transformation.
1279−
1280− -- Apply that transformation after every PClauses elaboration
1281−
1282− mkSpecialised ist specapp_in = do
1283− let (specTy, specapp) = getSpecTy ist specapp_in
1284− let (n, newnm, pats) = getSpecClause ist specapp
1285− let undef = case lookupDef newnm (tt_ctxt ist) of
1286− [] -> True
1287− _ -> False
1288− logLvl 5 $ show (newnm, map (concreteArg ist) (snd specapp))
1289− idrisCatch
1290− (when (undef && all (concreteArg ist) (snd specapp)) $ do
1291− cgns <- getAllNames n
1292− let opts = [Specialise (map (\x -> (x, Nothing)) cgns ++
1293− mapMaybe specName (snd specapp))]
1294− logLvl 3 $ "Specialising application: " ++ show specapp
1295− logLvl 2 $ "New name: " ++ show newnm
1296− iLOG $ "PE definition type : " ++ (show specTy)
1297− ++ "\n" ++ show opts
1298− logLvl 2 $ "PE definition " ++ show newnm ++ ":\n" ++
1299− showSep "\n"
1300− (map (\ (lhs, rhs) ->
1301− (showTmImpls lhs ++ " = " ++
1302− showTmImpls rhs)) pats)
1303− elabType info defaultSyntax emptyDocstring [] fc opts newnm specTy
1304− let def = map (\ (lhs, rhs) -> PClause fc newnm lhs [] rhs []) pats
1305− elabClauses info fc opts newnm def
1306− logLvl 2 $ "Specialised " ++ show newnm)
1307− -- if it doesn't work, just don't specialise. Could happen for lots
1308− -- of valid reasons (e.g. local variables in scope which can't be
1309− -- lifted out).
1310− (\e -> logLvl 4 $ "Couldn't specialise: " ++ (pshow ist e))
1311−
1312− specName (ImplicitS, tm)
1313− | (P Ref n _, _) <- unApply tm = Just (n, Just 1)
1314− specName (ExplicitS, tm)
1315− | (P Ref n _, _) <- unApply tm = Just (n, Just 1)
1316− specName _ = Nothing
1317−
1318− concreteArg ist (ImplicitS, tm) = concreteTm ist tm
1319− concreteArg ist (ExplicitS, tm) = concreteTm ist tm
1320− concreteArg ist _ = True
1321−
1322− concreteTm ist tm | (P _ n _, _) <- unApply tm =
1323− case lookupTy n (tt_ctxt ist) of
1324− [] -> False
1325− _ -> True
1326− concreteTm ist (Constant _) = True
1327− concreteTm ist _ = False
1328−
1329− -- get the type of a specialised application
1330− getSpecTy ist (n, args)
1331− = case lookupTy n (tt_ctxt ist) of
1332− [ty] -> let (specty_in, args') = specType args (explicitNames ty)
1333− specty = normalise (tt_ctxt ist) [] (finalise specty_in)
1334− t = mkPE_TyDecl ist args' (explicitNames specty) in
1335− (t, (n, args'))
1336−-- (normalise (tt_ctxt ist) [] (specType args ty))
1337− _ -> error "Can't happen (getSpecTy)"
1338−
1339− -- get the clause of a specialised application
1340− getSpecClause ist (n, args)
1341− = let newnm = sUN ("__"++show (nsroot n) ++ "_" ++
1342− showSep "_" (map showArg args)) in
1343− -- UN (show n ++ show (map snd args)) in
1344− (n, newnm, mkPE_TermDecl ist newnm n args)
1345− where showArg (ExplicitS, n) = show n
1346− showArg (ImplicitS, n) = show n
1347− showArg _ = ""
1348−
1349−
1350−-- Elaborate a value, returning any new bindings created (this will only
1351−-- happen if elaborating as a pattern clause)
1352−elabValBind :: ElabInfo -> ElabMode -> Bool -> PTerm -> Idris (Term, Type, [(Name, Type)])
1353−elabValBind info aspat norm tm_in
1354− = do ctxt <- getContext
1355− i <- getIState
1356− let tm = addImpl i tm_in
1357− logLvl 10 (showTmImpls tm)
1358− -- try:
1359− -- * ordinary elaboration
1360− -- * elaboration as a Type
1361− -- * elaboration as a function a -> b
1362−
1363− ((tm', defer, is), _) <-
1364−-- tctry (elaborate ctxt (MN 0 "val") (TType (UVal 0)) []
1365−-- (build i info aspat (MN 0 "val") tm))
1366− tclift (elaborate ctxt (sMN 0 "val") infP []
1367− (build i info aspat [Reflection] (sMN 0 "val") (infTerm tm)))
1368− let vtm = orderPats (getInferTerm tm')
1369−
1370− def' <- checkDef (fileFC "(input)") defer
1371− let def'' = map (\(n, (i, top, t)) -> (n, (i, top, t, True))) def'
1372− addDeferred def''
1373− mapM_ (elabCaseBlock info []) is
1374−
1375− logLvl 3 ("Value: " ++ show vtm)
1376−-- recheckC (fileFC "(input)") [] tm'
1377−-- logLvl 2 (show vtm)
1378− (vtm_in, vty) <- recheckC (fileFC "(input)") [] vtm
1379−
1380− let vtm = if norm then normalise (tt_ctxt i) [] vtm_in
1381− else vtm_in
1382− let bargs = getPBtys vtm
1383−
1384− return (vtm, vty, bargs)
1385−
1386−elabVal :: ElabInfo -> ElabMode -> PTerm -> Idris (Term, Type)
1387−elabVal info aspat tm_in
1388− = do (tm, ty, _) <- elabValBind info aspat False tm_in
1389− return (tm, ty)
1390−
1391−-- checks if the clause is a possible left hand side. Returns the term if
1392−-- possible, otherwise Nothing.
1393−
1394−checkPossible :: ElabInfo -> FC -> Bool -> Name -> PTerm -> Idris Bool
1395−checkPossible info fc tcgen fname lhs_in
1396− = do ctxt <- getContext
1397− i <- getIState
1398− let lhs = addImplPat i lhs_in
1399− -- if the LHS type checks, it is possible
1400− case elaborate ctxt (sMN 0 "patLHS") infP []
1401− (erun fc (buildTC i info ELHS [] fname (infTerm lhs))) of
1402− OK ((lhs', _, _), _) ->
1403− do let lhs_tm = orderPats (getInferTerm lhs')
1404− case recheck ctxt [] (forget lhs_tm) lhs_tm of
1405− OK _ -> return True
1406− err -> return False
1407− -- if it's a recoverable error, the case may become possible
1408− Error err -> if tcgen then return (recoverable ctxt err)
1409− else return (validCase ctxt err ||
1410− recoverable ctxt err)
1411− where validCase ctxt (CantUnify _ topx topy e _ _)
1412− = let topx' = normalise ctxt [] topx
1413− topy' = normalise ctxt [] topy in
1414− not (sameFam topx' topy' || not (validCase ctxt e))
1415− validCase ctxt (CantConvert _ _ _) = False
1416− validCase ctxt (At _ e) = validCase ctxt e
1417− validCase ctxt (Elaborating _ _ e) = validCase ctxt e
1418− validCase ctxt (ElaboratingArg _ _ _ e) = validCase ctxt e
1419− validCase ctxt _ = True
1420−
1421− recoverable ctxt (CantUnify r topx topy e _ _)
1422− = let topx' = normalise ctxt [] topx
1423− topy' = normalise ctxt [] topy in
1424− checkRec topx' topy'
1425− recoverable ctxt (At _ e) = recoverable ctxt e
1426− recoverable ctxt (Elaborating _ _ e) = recoverable ctxt e
1427− recoverable ctxt (ElaboratingArg _ _ _ e) = recoverable ctxt e
1428− recoverable _ _ = False
1429−
1430− sameFam topx topy
1431− = case (unApply topx, unApply topy) of
1432− ((P _ x _, _), (P _ y _, _)) -> x == y
1433− _ -> False
1434−
1435− -- different notion of recoverable than in unification, since we
1436− -- have no metavars -- just looking to see if a constructor is failing
1437− -- to unify with a function that may be reduced later
1438−
1439− checkRec (App f a) p@(P _ _ _) = checkRec f p
1440− checkRec p@(P _ _ _) (App f a) = checkRec p f
1441− checkRec fa@(App _ _) fa'@(App _ _)
1442− | (f, as) <- unApply fa,
1443− (f', as') <- unApply fa'
1444− = if (length as /= length as')
1445− then checkRec f f'
1446− else checkRec f f' && and (zipWith checkRec as as')
1447− checkRec (P xt x _) (P yt y _) = x == y || ntRec xt yt
1448− checkRec _ _ = False
1449−
1450− ntRec x y | Ref <- x = True
1451− | Ref <- y = True
1452− | otherwise = False -- name is different, unrecoverable
1453−
1454−getFixedInType i env (PExp _ _ _ _ : is) (Bind n (Pi t) sc)
1455− = nub $ getFixedInType i env [] t ++
1456− getFixedInType i (n : env) is (instantiate (P Bound n t) sc)
1457−getFixedInType i env (_ : is) (Bind n (Pi t) sc)
1458− = getFixedInType i (n : env) is (instantiate (P Bound n t) sc)
1459−getFixedInType i env is tm@(App f a)
1460− | (P _ tn _, args) <- unApply tm
1461− = case lookupCtxt tn (idris_datatypes i) of
1462− [t] -> nub $ paramNames args env (param_pos t) ++
1463− getFixedInType i env is f ++
1464− getFixedInType i env is a
1465− [] -> nub $ getFixedInType i env is f ++
1466− getFixedInType i env is a
1467− | otherwise = nub $ getFixedInType i env is f ++
1468− getFixedInType i env is a
1469−getFixedInType i _ _ _ = []
1470−
1471−getFlexInType i env ps (Bind n (Pi t) sc)
1472− = nub $ (if (not (n `elem` ps)) then getFlexInType i env ps t else []) ++
1473− getFlexInType i (n : env) ps (instantiate (P Bound n t) sc)
1474−getFlexInType i env ps tm@(App f a)
1475− | (P _ tn _, args) <- unApply tm
1476− = case lookupCtxt tn (idris_datatypes i) of
1477− [t] -> nub $ paramNames args env [x | x <- [0..length args],
1478− not (x `elem` param_pos t)]
1479− ++ getFlexInType i env ps f ++
1480− getFlexInType i env ps a
1481− [] -> nub $ getFlexInType i env ps f ++
1482− getFlexInType i env ps a
1483− | otherwise = nub $ getFlexInType i env ps f ++
1484− getFlexInType i env ps a
1485−getFlexInType i _ _ _ = []
1486−
1487−-- Treat a name as a parameter if it appears in parameter positions in
1488−-- types, and never in a non-parameter position in a (non-param) argument type.
1489−
1490−getParamsInType i env ps t = let fix = getFixedInType i env ps t
1491− flex = getFlexInType i env fix t in
1492− [x | x <- fix, not (x `elem` flex)]
1493−
1494−paramNames args env [] = []
1495−paramNames args env (p : ps)
1496− | length args > p = case args!!p of
1497− P _ n _ -> if n `elem` env
1498− then n : paramNames args env ps
1499− else paramNames args env ps
1500− _ -> paramNames args env ps
1501− | otherwise = paramNames args env ps
1502−
1503−propagateParams :: IState -> [Name] -> Type -> PTerm -> PTerm
1504−propagateParams i ps t tm@(PApp _ (PRef fc n) args)
1505− = PApp fc (PRef fc n) (addP t args)
1506− where addP (Bind n _ sc) (t : ts)
1507− | Placeholder <- getTm t,
1508− n `elem` ps,
1509− not (n `elem` allNamesIn tm)
1510− = t { getTm = PRef fc n } : addP sc ts
1511− addP (Bind n _ sc) (t : ts) = t : addP sc ts
1512− addP _ ts = ts
1513−propagateParams i ps t (PRef fc n)
1514− = case lookupCtxt n (idris_implicits i) of
1515− [is] -> let ps' = filter (isImplicit is) ps in
1516− PApp fc (PRef fc n) (map (\x -> pimp x (PRef fc x) True) ps')
1517− _ -> PRef fc n
1518− where isImplicit [] n = False
1519− isImplicit (PImp _ _ _ x _ : is) n | x == n = True
1520− isImplicit (_ : is) n = isImplicit is n
1521−propagateParams i ps t x = x
1522−
1523−-- Return the elaborated LHS/RHS, and the original LHS with implicits added
1524−elabClause :: ElabInfo -> FnOpts -> (Int, PClause) ->
1525− Idris (Either Term (Term, Term), PTerm)
1526−elabClause info opts (_, PClause fc fname lhs_in [] PImpossible [])
1527− = do let tcgen = Dictionary `elem` opts
1528− i <- get
1529− let lhs = addImpl i lhs_in
1530− b <- checkPossible info fc tcgen fname lhs_in
1531− case b of
1532− True -> tclift $ tfail (At fc
1533− (Msg $ show lhs_in ++ " is a valid case"))
1534− False -> do ptm <- mkPatTm lhs_in
1535− return (Left ptm, lhs)
1536−elabClause info opts (cnum, PClause fc fname lhs_in withs rhs_in whereblock)
1537− = do let tcgen = Dictionary `elem` opts
1538− ctxt <- getContext
1539−
1540− -- Build the LHS as an "Infer", and pull out its type and
1541− -- pattern bindings
1542− i <- getIState
1543− inf <- isTyInferred fname
1544− -- get the parameters first, to pass through to any where block
1545− let fn_ty = case lookupTy fname (tt_ctxt i) of
1546− [t] -> t
1547− _ -> error "Can't happen (elabClause function type)"
1548− let fn_is = case lookupCtxt fname (idris_implicits i) of
1549− [t] -> t
1550− _ -> []
1551− let params = getParamsInType i [] fn_is fn_ty
1552− let lhs = mkLHSapp $ stripUnmatchable i $
1553− propagateParams i params fn_ty (addImplPat i (stripLinear i lhs_in))
1554− logLvl 5 ("LHS: " ++ show fc ++ " " ++ showTmImpls lhs)
1555− logLvl 4 ("Fixed parameters: " ++ show params ++ " from " ++ show lhs_in ++
1556− "\n" ++ show (fn_ty, fn_is))
1557−
1558− (((lhs', dlhs, []), probs, inj), _) <-
1559− tclift $ elaborate ctxt (sMN 0 "patLHS") infP []
1560− (do res <- errAt "left hand side of " fname
1561− (erun fc (buildTC i info ELHS opts fname (infTerm lhs)))
1562− probs <- get_probs
1563− inj <- get_inj
1564− return (res, probs, inj))
1565−
1566− when inf $ addTyInfConstraints fc (map (\(x,y,_,_,_,_) -> (x,y)) probs)
1567−
1568− let lhs_tm = orderPats (getInferTerm lhs')
1569− let lhs_ty = getInferType lhs'
1570− logLvl 3 ("Elaborated: " ++ show lhs_tm)
1571− logLvl 3 ("Elaborated type: " ++ show lhs_ty)
1572− logLvl 5 ("Injective: " ++ show fname ++ " " ++ show inj)
1573−
1574− -- If we're inferring metavariables in the type, don't recheck,
1575− -- because we're only doing this to try to work out those metavariables
1576− (clhs_c, clhsty) <- if not inf
1577− then recheckC fc [] lhs_tm
1578− else return (lhs_tm, lhs_ty)
1579− let clhs = normalise ctxt [] clhs_c
1580−
1581− logLvl 3 ("Normalised LHS: " ++ showTmImpls (delabMV i clhs))
1582−
1583− rep <- useREPL
1584− when rep $ do
1585− addInternalApp (fc_fname fc) (fst . fc_start $ fc) (delabMV i clhs) -- TODO: Should use span instead of line and filename?
1586− addIBC (IBCLineApp (fc_fname fc) (fst . fc_start $ fc) (delabMV i clhs))
1587−
1588− logLvl 5 ("Checked " ++ show clhs ++ "\n" ++ show clhsty)
1589− -- Elaborate where block
1590− ist <- getIState
1591− windex <- getName
1592− let decls = nub (concatMap declared whereblock)
1593− let defs = nub (decls ++ concatMap defined whereblock)
1594− let newargs = pvars ist lhs_tm
1595− let winfo = pinfo info newargs defs windex
1596− let wb = map (expandParamsD False ist decorate newargs defs) whereblock
1597−
1598− -- Split the where block into declarations with a type, and those
1599− -- without
1600− -- Elaborate those with a type *before* RHS, those without *after*
1601− let (wbefore, wafter) = sepBlocks wb
1602−
1603− logLvl 2 $ "Where block:\n " ++ show wbefore ++ "\n" ++ show wafter
1604− mapM_ (elabDecl' EAll winfo) wbefore
1605− -- Now build the RHS, using the type of the LHS as the goal.
1606− i <- getIState -- new implicits from where block
1607− logLvl 5 (showTmImpls (expandParams decorate newargs defs (defs \\ decls) rhs_in))
1608− let rhs = addImplBoundInf i (map fst newargs) (defs \\ decls)
1609− (expandParams decorate newargs defs (defs \\ decls) rhs_in)
1610− logLvl 2 $ "RHS: " ++ showTmImpls rhs
1611− ctxt <- getContext -- new context with where block added
1612− logLvl 5 "STARTING CHECK"
1613− ((rhs', defer, is, probs), _) <-
1614− tclift $ elaborate ctxt (sMN 0 "patRHS") clhsty []
1615− (do pbinds ist lhs_tm
1616− mapM_ setinj (nub (params ++ inj))
1617− setNextName
1618− (_, _, is) <- errAt "right hand side of " fname
1619− (erun fc (build i winfo ERHS opts fname rhs))
1620− errAt "right hand side of " fname
1621− (erun fc $ psolve lhs_tm)
1622− hs <- get_holes
1623− aux <- getAux
1624− mapM_ (elabCaseHole aux) hs
1625− tt <- get_term
1626− let (tm, ds) = runState (collectDeferred (Just fname) tt) []
1627− probs <- get_probs
1628− return (tm, ds, is, probs))
1629−
1630− when inf $ addTyInfConstraints fc (map (\(x,y,_,_,_,_) -> (x,y)) probs)
1631−
1632− logLvl 5 "DONE CHECK"
1633− logLvl 2 $ "---> " ++ show rhs'
1634− when (not (null defer)) $ iLOG $ "DEFERRED " ++
1635− show (map (\ (n, (_,_,t)) -> (n, t)) defer)
1636− def' <- checkDef fc defer
1637− let def'' = map (\(n, (i, top, t)) -> (n, (i, top, t, False))) def'
1638− addDeferred def''
1639− mapM_ (\(n, _) -> addIBC (IBCDef n)) def''
1640−
1641− when (not (null def')) $ do
1642− mapM_ defer_totcheck (map (\x -> (fc, fst x)) def'')
1643−
1644− -- Now the remaining deferred (i.e. no type declarations) clauses
1645− -- from the where block
1646−
1647− mapM_ (elabDecl' EAll winfo) wafter
1648− mapM_ (elabCaseBlock winfo opts) is
1649−
1650− ctxt <- getContext
1651− logLvl 5 $ "Rechecking"
1652− logLvl 6 $ " ==> " ++ show (forget rhs')
1653− (crhs, crhsty) <- if not inf
1654− then recheckC fc [] rhs'
1655− else return (rhs', clhsty)
1656− logLvl 6 $ " ==> " ++ show crhsty ++ " against " ++ show clhsty
1657− case converts ctxt [] clhsty crhsty of
1658− OK _ -> return ()
1659− Error e -> ierror (At fc (CantUnify False clhsty crhsty e [] 0))
1660− i <- getIState
1661− checkInferred fc (delab' i crhs True True) rhs
1662− -- if the function is declared '%error_reverse', or its type,
1663− -- then we'll try running it in reverse to improve error messages
1664− let (ret_fam, _) = unApply (getRetTy crhsty)
1665− rev <- case ret_fam of
1666− P _ rfamn _ ->
1667− case lookupCtxt rfamn (idris_datatypes i) of
1668− [TI _ _ dopts _ _] ->
1669− return (DataErrRev `elem` dopts)
1670− _ -> return False
1671− _ -> return False
1672−
1673− when (rev || ErrorReverse `elem` opts) $ do
1674− addIBC (IBCErrRev (crhs, clhs))
1675− addErrRev (crhs, clhs)
1676− return $ (Right (clhs, crhs), lhs)
1677− where
1678− pinfo :: ElabInfo -> [(Name, PTerm)] -> [Name] -> Int -> ElabInfo
1679− pinfo info ns ds i
1680− = let newps = params info ++ ns
1681− dsParams = map (\n -> (n, map fst newps)) ds
1682− newb = addAlist dsParams (inblock info)
1683− l = liftname info in
1684− info { params = newps,
1685− inblock = newb,
1686− liftname = id -- (\n -> case lookupCtxt n newb of
1687− -- Nothing -> n
1688− -- _ -> MN i (show n)) . l
1689− }
1690−
1691− mkLHSapp t@(PRef _ _) = trace ("APP " ++ show t) $ PApp fc t []
1692− mkLHSapp t = t
1693−
1694− decorate (NS x ns)
1695− = NS (SN (WhereN cnum fname x)) ns -- ++ [show cnum])
1696−-- = NS (UN ('#':show x)) (ns ++ [show cnum, show fname])
1697− decorate x
1698− = SN (WhereN cnum fname x)
1699−-- = NS (SN (WhereN cnum fname x)) [show cnum]
1700−-- = NS (UN ('#':show x)) [show cnum, show fname]
1701−
1702− sepBlocks bs = sepBlocks' [] bs where
1703− sepBlocks' ns (d@(PTy _ _ _ _ _ n t) : bs)
1704− = let (bf, af) = sepBlocks' (n : ns) bs in
1705− (d : bf, af)
1706− sepBlocks' ns (d@(PClauses _ _ n _) : bs)
1707− | not (n `elem` ns) = let (bf, af) = sepBlocks' ns bs in
1708− (bf, d : af)
1709− sepBlocks' ns (b : bs) = let (bf, af) = sepBlocks' ns bs in
1710− (b : bf, af)
1711− sepBlocks' ns [] = ([], [])
1712−
1713−
1714− -- if a hole is just an argument/result of a case block, treat it as
1715− -- the unit type. Hack to help elaborate case in do blocks.
1716− elabCaseHole aux h = do
1717− focus h
1718− g <- goal
1719− case g of
1720− TType _ -> when (any (isArg h) aux) $ do apply (Var unitTy) []; solve
1721− _ -> return ()
1722−
1723− -- Is the name a pattern argument in the declaration
1724− isArg :: Name -> PDecl -> Bool
1725− isArg n (PClauses _ _ _ cs) = any isArg' cs
1726− where
1727− isArg' (PClause _ _ (PApp _ _ args) _ _ _)
1728− = any (\x -> case x of
1729− PRef _ n' -> n == n'
1730− _ -> False) (map getTm args)
1731− isArg' _ = False
1732− isArg _ _ = False
1733−
1734−elabClause info opts (_, PWith fc fname lhs_in withs wval_in withblock)
1735− = do let tcgen = Dictionary `elem` opts
1736− ctxt <- getContext
1737− -- Build the LHS as an "Infer", and pull out its type and
1738− -- pattern bindings
1739− i <- getIState
1740− -- get the parameters first, to pass through to any where block
1741− let fn_ty = case lookupTy fname (tt_ctxt i) of
1742− [t] -> t
1743− _ -> error "Can't happen (elabClause function type)"
1744− let fn_is = case lookupCtxt fname (idris_implicits i) of
1745− [t] -> t
1746− _ -> []
1747− let params = getParamsInType i [] fn_is fn_ty
1748− let lhs = propagateParams i params fn_ty (addImplPat i (stripLinear i lhs_in))
1749− logLvl 2 ("LHS: " ++ show lhs)
1750− ((lhs', dlhs, []), _) <-
1751− tclift $ elaborate ctxt (sMN 0 "patLHS") infP []
1752− (errAt "left hand side of with in " fname
1753− (erun fc (buildTC i info ELHS opts fname (infTerm lhs))) )
1754− let lhs_tm = orderPats (getInferTerm lhs')
1755− let lhs_ty = getInferType lhs'
1756− let ret_ty = getRetTy (explicitNames (normalise ctxt [] lhs_ty))
1757− logLvl 3 (show lhs_tm)
1758− (clhs, clhsty) <- recheckC fc [] lhs_tm
1759− logLvl 5 ("Checked " ++ show clhs)
1760− let bargs = getPBtys (explicitNames (normalise ctxt [] lhs_tm))
1761− let wval = addImplBound i (map fst bargs) wval_in
1762− logLvl 5 ("Checking " ++ showTmImpls wval)
1763− -- Elaborate wval in this context
1764− ((wval', defer, is), _) <-
1765− tclift $ elaborate ctxt (sMN 0 "withRHS")
1766− (bindTyArgs PVTy bargs infP) []
1767− (do pbinds i lhs_tm
1768− setNextName
1769− -- TODO: may want where here - see winfo abpve
1770− (_', d, is) <- errAt "with value in " fname
1771− (erun fc (build i info ERHS opts fname (infTerm wval)))
1772− erun fc $ psolve lhs_tm
1773− tt <- get_term
1774− return (tt, d, is))
1775− def' <- checkDef fc defer
1776− let def'' = map (\(n, (i, top, t)) -> (n, (i, top, t, False))) def'
1777− addDeferred def''
1778− mapM_ (elabCaseBlock info opts) is
1779− logLvl 5 ("Checked wval " ++ show wval')
1780− (cwval, cwvalty) <- recheckC fc [] (getInferTerm wval')
1781− let cwvaltyN = explicitNames (normalise ctxt [] cwvalty)
1782− let cwvalN = explicitNames (normalise ctxt [] cwval)
1783− logLvl 5 ("With type " ++ show cwvalty ++ "\nRet type " ++ show ret_ty)
1784− let pvars = map fst (getPBtys cwvalty)
1785− -- we need the unelaborated term to get the names it depends on
1786− -- rather than a de Bruijn index.
1787− let pdeps = usedNamesIn pvars i (delab i cwvalty)
1788− let (bargs_pre, bargs_post) = split pdeps bargs []
1789− logLvl 10 ("With type " ++ show (getRetTy cwvaltyN) ++
1790− " depends on " ++ show pdeps ++ " from " ++ show pvars)
1791− logLvl 10 ("Pre " ++ show bargs_pre ++ "\nPost " ++ show bargs_post)
1792− windex <- getName
1793− -- build a type declaration for the new function:
1794− -- (ps : Xs) -> (withval : cwvalty) -> (ps' : Xs') -> ret_ty
1795− let wargval = getRetTy cwvalN
1796− let wargtype = getRetTy cwvaltyN
1797− logLvl 5 ("Abstract over " ++ show wargval ++ " in " ++ show wargtype)
1798− let wtype = bindTyArgs Pi (bargs_pre ++
1799− (sMN 0 "warg", wargtype) :
1800− map (abstract (sMN 0 "warg") wargval wargtype) bargs_post)
1801− (substTerm wargval (P Bound (sMN 0 "warg") wargtype) ret_ty)
1802− logLvl 5 ("New function type " ++ show wtype)
1803− let wname = sMN windex (show fname)
1804−
1805− let imps = getImps wtype -- add to implicits context
1806− putIState (i { idris_implicits = addDef wname imps (idris_implicits i) })
1807− addIBC (IBCDef wname)
1808− def' <- checkDef fc [(wname, (-1, Nothing, wtype))]
1809− let def'' = map (\(n, (i, top, t)) -> (n, (i, top, t, False))) def'
1810− addDeferred def''
1811−
1812− -- in the subdecls, lhs becomes:
1813− -- fname pats | wpat [rest]
1814− -- ==> fname' ps wpat [rest], match pats against toplevel for ps
1815− wb <- mapM (mkAuxC wname lhs (map fst bargs_pre) (map fst bargs_post))
1816− withblock
1817− logLvl 3 ("with block " ++ show wb)
1818− -- propagate totality assertion to the new definitions
1819− when (AssertTotal `elem` opts) $ setFlags wname [AssertTotal]
1820− mapM_ (elabDecl EAll info) wb
1821−
1822− -- rhs becomes: fname' ps wval
1823− let rhs = PApp fc (PRef fc wname)
1824− (map (pexp . (PRef fc) . fst) bargs_pre ++
1825− pexp wval :
1826− (map (pexp . (PRef fc) . fst) bargs_post))
1827− logLvl 5 ("New RHS " ++ showTmImpls rhs)
1828− ctxt <- getContext -- New context with block added
1829− i <- getIState
1830− ((rhs', defer, is), _) <-
1831− tclift $ elaborate ctxt (sMN 0 "wpatRHS") clhsty []
1832− (do pbinds i lhs_tm
1833− setNextName
1834− (_, d, is) <- erun fc (build i info ERHS opts fname rhs)
1835− psolve lhs_tm
1836− tt <- get_term
1837− return (tt, d, is))
1838− def' <- checkDef fc defer
1839− let def'' = map (\(n, (i, top, t)) -> (n, (i, top, t, False))) def'
1840− addDeferred def''
1841− mapM_ (elabCaseBlock info opts) is
1842− logLvl 5 ("Checked RHS " ++ show rhs')
1843− (crhs, crhsty) <- recheckC fc [] rhs'
1844− return $ (Right (clhs, crhs), lhs)
1845− where
1846− getImps (Bind n (Pi _) t) = pexp Placeholder : getImps t
1847− getImps _ = []
1848−
1849− mkAuxC wname lhs ns ns' (PClauses fc o n cs)
1850− | True = do cs' <- mapM (mkAux wname lhs ns ns') cs
1851− return $ PClauses fc o wname cs'
1852− | otherwise = ifail $ show fc ++ "with clause uses wrong function name " ++ show n
1853− mkAuxC wname lhs ns ns' d = return $ d
1854−
1855− mkAux wname toplhs ns ns' (PClause fc n tm_in (w:ws) rhs wheres)
1856− = do i <- getIState
1857− let tm = addImplPat i tm_in
1858− logLvl 2 ("Matching " ++ showTmImpls tm ++ " against " ++
1859− showTmImpls toplhs)
1860− case matchClause i toplhs tm of
1861− Left (a,b) -> ifail $ show fc ++ ":with clause does not match top level"
1862− Right mvars ->
1863− do logLvl 3 ("Match vars : " ++ show mvars)
1864− lhs <- updateLHS n wname mvars ns ns' (fullApp tm) w
1865− return $ PClause fc wname lhs ws rhs wheres
1866− mkAux wname toplhs ns ns' (PWith fc n tm_in (w:ws) wval withs)
1867− = do i <- getIState
1868− let tm = addImplPat i tm_in
1869− logLvl 2 ("Matching " ++ showTmImpls tm ++ " against " ++
1870− showTmImpls toplhs)
1871− withs' <- mapM (mkAuxC wname toplhs ns ns') withs
1872− case matchClause i toplhs tm of
1873− Left (a,b) -> trace ("matchClause: " ++ show a ++ " =/= " ++ show b) (ifail $ show fc ++ "with clause does not match top level")
1874− Right mvars ->
1875− do lhs <- updateLHS n wname mvars ns ns' (fullApp tm) w
1876− return $ PWith fc wname lhs ws wval withs'
1877− mkAux wname toplhs ns ns' c
1878− = ifail $ show fc ++ ":badly formed with clause"
1879−
1880− addArg (PApp fc f args) w = PApp fc f (args ++ [pexp w])
1881− addArg (PRef fc f) w = PApp fc (PRef fc f) [pexp w]
1882−
1883− updateLHS n wname mvars ns_in ns_in' (PApp fc (PRef fc' n') args) w
1884− = let ns = map (keepMvar (map fst mvars) fc') ns_in
1885− ns' = map (keepMvar (map fst mvars) fc') ns_in' in
1886− return $ substMatches mvars $
1887− PApp fc (PRef fc' wname)
1888− (map pexp ns ++ pexp w : (map pexp ns'))
1889− updateLHS n wname mvars ns_in ns_in' tm w
1890− = updateLHS n wname mvars ns_in ns_in' (PApp fc tm []) w
1891−
1892− keepMvar mvs fc v | v `elem` mvs = PRef fc v
1893− | otherwise = Placeholder
1894−
1895− fullApp (PApp _ (PApp fc f args) xs) = fullApp (PApp fc f (args ++ xs))
1896− fullApp x = x
1897−
1898− split [] rest pre = (reverse pre, rest)
1899− split deps ((n, ty) : rest) pre
1900− | n `elem` deps = split (deps \\ [n]) rest ((n, ty) : pre)
1901− | otherwise = split deps rest ((n, ty) : pre)
1902− split deps [] pre = (reverse pre, [])
1903−
1904− abstract wn wv wty (n, argty) = (n, substTerm wv (P Bound wn wty) argty)
1905−
1906−data MArgTy = IA | EA | CA deriving Show
1907−
1908−elabClass :: ElabInfo -> SyntaxInfo -> Docstring ->
1909− FC -> [PTerm] ->
1910− Name -> [(Name, PTerm)] -> [(Name, Docstring)] -> [PDecl] -> Idris ()
1911−elabClass info syn_in doc fc constraints tn ps pDocs ds
1912− = do let cn = SN (InstanceCtorN tn) -- sUN ("instance" ++ show tn) -- MN 0 ("instance" ++ show tn)
1913− let tty = pibind ps PType
1914− let constraint = PApp fc (PRef fc tn)
1915− (map (pexp . PRef fc) (map fst ps))
1916−
1917− let syn = syn_in { using = addToUsing (using syn_in) ps }
1918−
1919− -- build data declaration
1920− let mdecls = filter tydecl ds -- method declarations
1921− let idecls = filter instdecl ds -- default superclass instance declarations
1922− mapM_ checkDefaultSuperclassInstance idecls
1923− let mnames = map getMName mdecls
1924− logLvl 2 $ "Building methods " ++ show mnames
1925− ims <- mapM (tdecl mnames) mdecls
1926− defs <- mapM (defdecl (map (\ (x,y,z) -> z) ims) constraint)
1927− (filter clause ds)
1928− let (methods, imethods)
1929− = unzip (map (\ ( x,y,z) -> (x, y)) ims)
1930− let defaults = map (\ (x, (y, z)) -> (x,y)) defs
1931− addClass tn (CI cn (map nodoc imethods) defaults idecls (map fst ps) [])
1932− -- build instance constructor type
1933− -- decorate names of functions to ensure they can't be referred
1934− -- to elsewhere in the class declaration
1935− let cty = impbind ps $ conbind constraints
1936− $ pibind (map (\ (n, ty) -> (nsroot n, ty)) methods)
1937− constraint
1938− let cons = [(emptyDocstring, [], cn, cty, fc, [])]
1939− let ddecl = PDatadecl tn tty cons
1940− logLvl 5 $ "Class data " ++ show (showDImp verbosePPOption ddecl)
1941− elabData info (syn { no_imp = no_imp syn ++ mnames }) doc pDocs fc [] ddecl
1942− -- for each constraint, build a top level function to chase it
1943− logLvl 5 $ "Building functions"
1944−-- let usyn = syn { using = map (\ (x,y) -> UImplicit x y) ps
1945−-- ++ using syn }
1946− fns <- mapM (cfun cn constraint syn (map fst imethods)) constraints
1947− mapM_ (elabDecl EAll info) (concat fns)
1948− -- for each method, build a top level function
1949− fns <- mapM (tfun cn constraint syn (map fst imethods)) imethods
1950− mapM_ (elabDecl EAll info) (concat fns)
1951− -- add the default definitions
1952− mapM_ (elabDecl EAll info) (concat (map (snd.snd) defs))
1953− addIBC (IBCClass tn)
1954− where
1955− nodoc (n, (_, o, t)) = (n, (o, t))
1956− pibind [] x = x
1957− pibind ((n, ty): ns) x = PPi expl n ty (pibind ns x)
1958−
1959− mdec (UN n) = SN (MethodN (UN n))
1960− mdec (NS x n) = NS (mdec x) n
1961− mdec x = x
1962−
1963− -- TODO: probably should normalise
1964− checkDefaultSuperclassInstance (PInstance _ fc cs n ps _ _ _)
1965− = do when (not $ null cs) . tclift
1966− $ tfail (At fc (Msg $ "Default superclass instances can't have constraints."))
1967− i <- getIState
1968− let t = PApp fc (PRef fc n) (map pexp ps)
1969− let isConstrained = any (== t) constraints
1970− when (not isConstrained) . tclift
1971− $ tfail (At fc (Msg $ "Default instances must be for a superclass constraint on the containing class."))
1972− return ()
1973−
1974− impbind [] x = x
1975− impbind ((n, ty): ns) x = PPi impl n ty (impbind ns x)
1976− conbind (ty : ns) x = PPi constraint (sMN 0 "class") ty (conbind ns x)
1977− conbind [] x = x
1978−
1979− getMName (PTy _ _ _ _ _ n _) = nsroot n
1980− tdecl allmeths (PTy doc _ syn _ o n t)
1981− = do t' <- implicit' info syn allmeths n t
1982− logLvl 5 $ "Method " ++ show n ++ " : " ++ showTmImpls t'
1983− return ( (n, (toExp (map fst ps) Exp t')),
1984− (n, (doc, o, (toExp (map fst ps) Imp t'))),
1985− (n, (syn, o, t) ) )
1986− tdecl _ _ = ifail "Not allowed in a class declaration"
1987−
1988− -- Create default definitions
1989− defdecl mtys c d@(PClauses fc opts n cs) =
1990− case lookup n mtys of
1991− Just (syn, o, ty) -> do let ty' = insertConstraint c ty
1992− let ds = map (decorateid defaultdec)
1993− [PTy emptyDocstring [] syn fc [] n ty',
1994− PClauses fc (o ++ opts) n cs]
1995− iLOG (show ds)
1996− return (n, ((defaultdec n, ds!!1), ds))
1997− _ -> ifail $ show n ++ " is not a method"
1998− defdecl _ _ _ = ifail "Can't happen (defdecl)"
1999−
2000− defaultdec (UN n) = sUN ("default#" ++ str n)
2001− defaultdec (NS n ns) = NS (defaultdec n) ns
2002−
2003− tydecl (PTy _ _ _ _ _ _ _) = True
2004− tydecl _ = False
2005− instdecl (PInstance _ _ _ _ _ _ _ _) = True
2006− instdecl _ = False
2007− clause (PClauses _ _ _ _) = True
2008− clause _ = False
2009−
2010− -- Generate a function for chasing a dictionary constraint
2011− cfun cn c syn all con
2012− = do let cfn = sUN ('@':'@':show cn ++ "#" ++ show con)
2013− -- SN (ParentN cn (show con))
2014− let mnames = take (length all) $ map (\x -> sMN x "meth") [0..]
2015− let capp = PApp fc (PRef fc cn) (map (pexp . PRef fc) mnames)
2016− let lhs = PApp fc (PRef fc cfn) [pconst capp]
2017− let rhs = PResolveTC (fileFC "HACK")
2018− let ty = PPi constraint (sMN 0 "pc") c con
2019− iLOG (showTmImpls ty)
2020− iLOG (showTmImpls lhs ++ " = " ++ showTmImpls rhs)
2021− i <- getIState
2022− let conn = case con of
2023− PRef _ n -> n
2024− PApp _ (PRef _ n) _ -> n
2025− let conn' = case lookupCtxtName conn (idris_classes i) of
2026− [(n, _)] -> n
2027− _ -> conn
2028− addInstance False conn' cfn
2029− addIBC (IBCInstance False conn' cfn)
2030−-- iputStrLn ("Added " ++ show (conn, cfn, ty))
2031− return [PTy emptyDocstring [] syn fc [] cfn ty,
2032− PClauses fc [Dictionary] cfn [PClause fc cfn lhs [] rhs []]]
2033−
2034− -- Generate a top level function which looks up a method in a given
2035− -- dictionary (this is inlinable, always)
2036− tfun cn c syn all (m, (doc, o, ty))
2037− = do let ty' = insertConstraint c ty
2038− let mnames = take (length all) $ map (\x -> sMN x "meth") [0..]
2039− let capp = PApp fc (PRef fc cn) (map (pexp . PRef fc) mnames)
2040− let margs = getMArgs ty
2041− let anames = map (\x -> sMN x "arg") [0..]
2042− let lhs = PApp fc (PRef fc m) (pconst capp : lhsArgs margs anames)
2043− let rhs = PApp fc (getMeth mnames all m) (rhsArgs margs anames)
2044− iLOG (showTmImpls ty)
2045− iLOG (show (m, ty', capp, margs))
2046− iLOG (showTmImpls lhs ++ " = " ++ showTmImpls rhs)
2047− return [PTy doc [] syn fc o m ty',
2048− PClauses fc [Inlinable] m [PClause fc m lhs [] rhs []]]
2049−
2050− getMArgs (PPi (Imp _ _ _) n ty sc) = IA : getMArgs sc
2051− getMArgs (PPi (Exp _ _ _) n ty sc) = EA : getMArgs sc
2052− getMArgs (PPi (Constraint _ _) n ty sc) = CA : getMArgs sc
2053− getMArgs _ = []
2054−
2055− getMeth (m:ms) (a:as) x | x == a = PRef fc m
2056− | otherwise = getMeth ms as x
2057−
2058− lhsArgs (EA : xs) (n : ns) = [] -- pexp (PRef fc n) : lhsArgs xs ns
2059− lhsArgs (IA : xs) ns = lhsArgs xs ns
2060− lhsArgs (CA : xs) ns = lhsArgs xs ns
2061− lhsArgs [] _ = []
2062−
2063− rhsArgs (EA : xs) (n : ns) = [] -- pexp (PRef fc n) : rhsArgs xs ns
2064− rhsArgs (IA : xs) ns = pexp Placeholder : rhsArgs xs ns
2065− rhsArgs (CA : xs) ns = pconst (PResolveTC fc) : rhsArgs xs ns
2066− rhsArgs [] _ = []
2067−
2068− insertConstraint c (PPi p@(Imp _ _ _) n ty sc)
2069− = PPi p n ty (insertConstraint c sc)
2070− insertConstraint c sc = PPi constraint (sMN 0 "class") c sc
2071−
2072− -- make arguments explicit and don't bind class parameters
2073− toExp ns e (PPi (Imp l s p) n ty sc)
2074− | n `elem` ns = toExp ns e sc
2075− | otherwise = PPi (e l s p) n ty (toExp ns e sc)
2076− toExp ns e (PPi p n ty sc) = PPi p n ty (toExp ns e sc)
2077− toExp ns e sc = sc
2078−
2079−elabInstance :: ElabInfo -> SyntaxInfo ->
2080− ElabWhat -> -- phase
2081− FC -> [PTerm] -> -- constraints
2082− Name -> -- the class
2083− [PTerm] -> -- class parameters (i.e. instance)
2084− PTerm -> -- full instance type
2085− Maybe Name -> -- explicit name
2086− [PDecl] -> Idris ()
2087−elabInstance info syn what fc cs n ps t expn ds = do
2088− i <- getIState
2089− (n, ci) <- case lookupCtxtName n (idris_classes i) of
2090− [c] -> return c
2091− [] -> ifail $ show fc ++ ":" ++ show n ++ " is not a type class"
2092− cs -> tclift $ tfail $ At fc
2093− (CantResolveAlts (map fst cs))
2094− let constraint = PApp fc (PRef fc n) (map pexp ps)
2095− let iname = mkiname n ps expn
2096− let emptyclass = null (class_methods ci)
2097− when (what /= EDefns || (null ds && not emptyclass)) $ do
2098− nty <- elabType' True info syn emptyDocstring [] fc [] iname t
2099− -- if the instance type matches any of the instances we have already,
2100− -- and it's not a named instance, then it's overlapping, so report an error
2101− case expn of
2102− Nothing -> do mapM_ (maybe (return ()) overlapping . findOverlapping i (delab i nty))
2103− (class_instances ci)
2104− addInstance intInst n iname
2105− Just _ -> addInstance intInst n iname
2106− when (what /= ETypes && (not (null ds && not emptyclass))) $ do
2107− let ips = zip (class_params ci) ps
2108− let ns = case n of
2109− NS n ns' -> ns'
2110− _ -> []
2111− -- get the implicit parameters that need passing through to the
2112− -- where block
2113− wparams <- mapM (\p -> case p of
2114− PApp _ _ args -> getWParams (map getTm args)
2115− _ -> return []) ps
2116− let pnames = map pname (concat (nub wparams))
2117− let superclassInstances = map (substInstance ips pnames) (class_default_superclasses ci)
2118− undefinedSuperclassInstances <- filterM (fmap not . isOverlapping i) superclassInstances
2119− mapM_ (elabDecl EAll info) undefinedSuperclassInstances
2120− let all_meths = map (nsroot . fst) (class_methods ci)
2121− let mtys = map (\ (n, (op, t)) ->
2122− let t_in = substMatchesShadow ips pnames t
2123− mnamemap = map (\n -> (n, PRef fc (decorate ns iname n)))
2124− all_meths
2125− t' = substMatchesShadow mnamemap pnames t_in in
2126− (decorate ns iname n,
2127− op, coninsert cs t', t'))
2128− (class_methods ci)
2129− logLvl 3 (show (mtys, ips))
2130− let ds' = insertDefaults i iname (class_defaults ci) ns ds
2131− iLOG ("Defaults inserted: " ++ show ds' ++ "\n" ++ show ci)
2132− mapM_ (warnMissing ds' ns iname) (map fst (class_methods ci))
2133− mapM_ (checkInClass (map fst (class_methods ci))) (concatMap defined ds')
2134− let wbTys = map mkTyDecl mtys
2135− let wbVals = map (decorateid (decorate ns iname)) ds'
2136− let wb = wbTys ++ wbVals
2137− logLvl 3 $ "Method types " ++ showSep "\n" (map (show . showDeclImp verbosePPOption . mkTyDecl) mtys)
2138− logLvl 3 $ "Instance is " ++ show ps ++ " implicits " ++
2139− show (concat (nub wparams))
2140−
2141− -- Bring variables in instance head into scope
2142− ist <- getIState
2143− let headVars = nub $ mapMaybe (\p -> case p of
2144− PRef _ n ->
2145− case lookupTy n (tt_ctxt ist) of
2146− [] -> Just n
2147− _ -> Nothing
2148− _ -> Nothing) ps
2149−-- let lhs = PRef fc iname
2150− let lhs = PApp fc (PRef fc iname)
2151− (map (\n -> pimp n (PRef fc n) True) headVars)
2152− let rhs = PApp fc (PRef fc (instanceName ci))
2153− (map (pexp . mkMethApp) mtys)
2154−
2155− logLvl 5 $ "Instance LHS " ++ show lhs ++ " " ++ show headVars
2156− logLvl 5 $ "Instance RHS " ++ show rhs
2157−
2158− let idecls = [PClauses fc [Dictionary] iname
2159− [PClause fc iname lhs [] rhs wb]]
2160− iLOG (show idecls)
2161− mapM_ (elabDecl EAll info) idecls
2162− addIBC (IBCInstance intInst n iname)
2163−
2164− where
2165− intInst = case ps of
2166− [PConstant (AType (ATInt ITNative))] -> True
2167− _ -> False
2168−
2169− mkiname n' ps' expn' =
2170− case expn' of
2171− Nothing -> SN (sInstanceN n' (map show ps'))
2172− Just nm -> nm
2173−
2174− substInstance ips pnames (PInstance syn _ cs n ps t expn ds)
2175− = PInstance syn fc cs n (map (substMatchesShadow ips pnames) ps) (substMatchesShadow ips pnames t) expn ds
2176−
2177− isOverlapping i (PInstance syn _ _ n ps t expn _)
2178− = case lookupCtxtName n (idris_classes i) of
2179− [(n, ci)] -> let iname = (mkiname n ps expn) in
2180− case lookupTy iname (tt_ctxt i) of
2181− [] -> elabFindOverlapping i ci iname syn t
2182− (_:_) -> return True
2183− _ -> return False -- couldn't find class, just let elabInstance fail later
2184−
2185− -- TODO: largely based upon elabType' - should try to abstract
2186− elabFindOverlapping i ci iname syn t
2187− = do ty' <- addUsingConstraints syn fc t
2188− -- TODO think: something more in info?
2189− ty' <- implicit info syn iname ty'
2190− let ty = addImpl i ty'
2191− ctxt <- getContext
2192− ((tyT, _, _), _) <-
2193− tclift $ elaborate ctxt iname (TType (UVal 0)) []
2194− (errAt "type of " iname (erun fc (build i info ERHS [] iname ty)))
2195− ctxt <- getContext
2196− (cty, _) <- recheckC fc [] tyT
2197− let nty = normalise ctxt [] cty
2198− return $ any (isJust . findOverlapping i (delab i nty)) (class_instances ci)
2199−
2200− findOverlapping i t n
2201− | take 2 (show n) == "@@" = Nothing
2202− | otherwise
2203− = case lookupTy n (tt_ctxt i) of
2204− [t'] -> let tret = getRetType t
2205− tret' = getRetType (delab i t') in
2206− case matchClause i tret' tret of
2207− Right ms -> Just tret'
2208− Left _ -> case matchClause i tret tret' of
2209− Right ms -> Just tret'
2210− Left _ -> Nothing
2211− _ -> Nothing
2212− overlapping t' = tclift $ tfail (At fc (Msg $
2213− "Overlapping instance: " ++ show t' ++ " already defined"))
2214− getRetType (PPi _ _ _ sc) = getRetType sc
2215− getRetType t = t
2216−
2217− mkMethApp (n, _, _, ty)
2218− = lamBind 0 ty (papp fc (PRef fc n) (methArgs 0 ty))
2219− lamBind i (PPi (Constraint _ _) _ _ sc) sc'
2220− = PLam (sMN i "meth") Placeholder (lamBind (i+1) sc sc')
2221− lamBind i (PPi _ n ty sc) sc'
2222− = PLam (sMN i "meth") Placeholder (lamBind (i+1) sc sc')
2223− lamBind i _ sc = sc
2224− methArgs i (PPi (Imp _ _ _) n ty sc)
2225− = PImp 0 True [] n (PRef fc (sMN i "meth")) : methArgs (i+1) sc
2226− methArgs i (PPi (Exp _ _ _) n ty sc)
2227− = PExp 0 [] (sMN 0 "marg") (PRef fc (sMN i "meth")) : methArgs (i+1) sc
2228− methArgs i (PPi (Constraint _ _) n ty sc)
2229− = PConstraint 0 [] (sMN 0 "marg") (PResolveTC fc) : methArgs (i+1) sc
2230− methArgs i _ = []
2231−
2232− papp fc f [] = f
2233− papp fc f as = PApp fc f as
2234−
2235− getWParams [] = return []
2236− getWParams (p : ps)
2237− | PRef _ n <- p
2238− = do ps' <- getWParams ps
2239− ctxt <- getContext
2240− case lookupP n ctxt of
2241− [] -> return (pimp n (PRef fc n) True : ps')
2242− _ -> return ps'
2243− getWParams (_ : ps) = getWParams ps
2244−
2245− decorate ns iname (UN n) = NS (SN (MethodN (UN n))) ns
2246− decorate ns iname (NS (UN n) s) = NS (SN (MethodN (UN n))) ns
2247−
2248− mkTyDecl (n, op, t, _) = PTy emptyDocstring [] syn fc op n t
2249−
2250− conbind (ty : ns) x = PPi constraint (sMN 0 "class") ty (conbind ns x)
2251− conbind [] x = x
2252−
2253− coninsert cs (PPi p@(Imp _ _ _) n t sc) = PPi p n t (coninsert cs sc)
2254− coninsert cs sc = conbind cs sc
2255−
2256− insertDefaults :: IState -> Name ->
2257− [(Name, (Name, PDecl))] -> [T.Text] ->
2258− [PDecl] -> [PDecl]
2259− insertDefaults i iname [] ns ds = ds
2260− insertDefaults i iname ((n,(dn, clauses)) : defs) ns ds
2261− = insertDefaults i iname defs ns (insertDef i n dn clauses ns iname ds)
2262−
2263− insertDef i meth def clauses ns iname decls
2264− | null $ filter (clauseFor meth iname ns) decls
2265− = let newd = expandParamsD False i (\n -> meth) [] [def] clauses in
2266− -- trace (show newd) $
2267− decls ++ [newd]
2268− | otherwise = decls
2269−
2270− warnMissing decls ns iname meth
2271− | null $ filter (clauseFor meth iname ns) decls
2272− = iWarn fc . text $ "method " ++ show meth ++ " not defined"
2273− | otherwise = return ()
2274−
2275− checkInClass ns meth
2276− | not (null (filter (eqRoot meth) ns)) = return ()
2277− | otherwise = tclift $ tfail (At fc (Msg $
2278− show meth ++ " not a method of class " ++ show n))
2279−
2280− eqRoot x y = nsroot x == nsroot y
2281−
2282− clauseFor m iname ns (PClauses _ _ m' _)
2283− = decorate ns iname m == decorate ns iname m'
2284− clauseFor m iname ns _ = False
2285−
2286−{- This won't work yet. Can it ever, in this form?
2287−
2288− cfun cn c syn all con
2289− = do let cfn = UN ('@':'@':show cn ++ "#" ++ show con)
2290− let mnames = take (length all) $ map (\x -> MN x "meth") [0..]
2291− let capp = PApp fc (PRef fc cn) (map (pexp . PRef fc) mnames)
2292− let lhs = PApp fc (PRef fc cfn) [pconst capp]
2293− let rhs = PResolveTC (FC "HACK" 0)
2294− let ty = PPi constraint (MN 0 "pc") c con
2295− iLOG (showImp True ty)
2296− iLOG (showImp True lhs ++ " = " ++ showImp True rhs)
2297− i <- getIState
2298− let conn = case con of
2299− PRef _ n -> n
2300− PApp _ (PRef _ n) _ -> n
2301− let conn' = case lookupCtxtName Nothing conn (idris_classes i) of
2302− [(n, _)] -> n
2303− _ -> conn
2304− addInstance False conn' cfn
2305− addIBC (IBCInstance False conn' cfn)
2306− iputStrLn ("Added " ++ show (conn, cfn, ty) ++ "\n" ++ show (lhs, rhs))
2307− return [PTy "" syn fc [] cfn ty,
2308− PClauses fc [Dictionary] cfn [PClause fc cfn lhs [] rhs []]]
2309−-}
2310−
2311−decorateid decorate (PTy doc argdocs s f o n t) = PTy doc argdocs s f o (decorate n) t
2312−decorateid decorate (PClauses f o n cs)
2313− = PClauses f o (decorate n) (map dc cs)
2314− where dc (PClause fc n t as w ds) = PClause fc (decorate n) (dappname t) as w ds
2315− dc (PWith fc n t as w ds)
2316− = PWith fc (decorate n) (dappname t) as w
2317− (map (decorateid decorate) ds)
2318− dappname (PApp fc (PRef fc' n) as) = PApp fc (PRef fc' (decorate n)) as
2319− dappname t = t
2320−
2321−
2322−-- if 't' is a type class application, assume its arguments are injective
2323−pbinds :: IState -> Term -> ElabD ()
2324−pbinds i (Bind n (PVar t) sc)
2325− = do attack; patbind n
2326− case unApply t of
2327− (P _ c _, args) -> case lookupCtxt c (idris_classes i) of
2328− [] -> return ()
2329− _ -> -- type class, set as injective
2330− mapM_ setinjArg args
2331− _ -> return ()
2332− pbinds i sc
2333− where setinjArg (P _ n _) = setinj n
2334− setinjArg _ = return ()
2335−pbinds i tm = return ()
2336−
2337−pbty (Bind n (PVar t) sc) tm = Bind n (PVTy t) (pbty sc tm)
2338−pbty _ tm = tm
2339−
2340−getPBtys (Bind n (PVar t) sc) = (n, t) : getPBtys sc
2341−getPBtys (Bind n (PVTy t) sc) = (n, t) : getPBtys sc
2342−getPBtys _ = []
2343−
2344−psolve (Bind n (PVar t) sc) = do solve; psolve sc
2345−psolve tm = return ()
2346−
2347−pvars ist (Bind n (PVar t) sc) = (n, delab ist t) : pvars ist sc
2348−pvars ist _ = []
2349−
2350−data ElabWhat = ETypes | EDefns | EAll
2351− deriving (Show, Eq)
2352−
2353elabDecls :: ElabInfo -> [PDecl] -> Idris ()
169elabDecls :: ElabInfo -> [PDecl] -> Idris ()
2354elabDecls info ds = do mapM_ (elabDecl EAll info) ds
170elabDecls info ds = do mapM_ (elabDecl EAll info) ds
2355−-- mapM_ (elabDecl EDefns info) ds
2356
171
2357elabDecl :: ElabWhat -> ElabInfo -> PDecl -> Idris ()
172elabDecl :: ElabWhat -> ElabInfo -> PDecl -> Idris ()
2358elabDecl what info d
173elabDecl what info d
174+ = let info' = info { rec_elabDecl = elabDecl' } in
2359− = idrisCatch (withErrorReflection $ elabDecl' what info d) (setAndReport)
175+ idrisCatch (withErrorReflection $ elabDecl' what info' d) (setAndReport)
2360
176
2361elabDecl' _ info (PFix _ _ _)
177elabDecl' _ info (PFix _ _ _)
2362 = return () -- nothing to elaborate
178 = return () -- nothing to elaborate
@@ -2464,54 +280,3 @@ elabDecl' what info (PTransform fc safety old new)
2464 = elabTransform info fc safety old new
280 = elabTransform info fc safety old new
2465elabDecl' _ _ _ = return () -- skipped this time
281elabDecl' _ _ _ = return () -- skipped this time
2466
282
2467−elabCaseBlock info opts d@(PClauses f o n ps)
2468− = do addIBC (IBCDef n)
2469− logLvl 5 $ "CASE BLOCK: " ++ show (n, d)
2470− let opts' = nub (o ++ opts)
2471− -- propagate totality assertion to the new definitions
2472− when (AssertTotal `elem` opts) $ setFlags n [AssertTotal]
2473− elabDecl' EAll info (PClauses f opts' n ps )
2474−
2475−-- elabDecl' info (PImport i) = loadModule i
2476−
2477−-- Check that the result of type checking matches what the programmer wrote
2478−-- (i.e. - if we inferred any arguments that the user provided, make sure
2479−-- they are the same!)
2480−
2481−checkInferred :: FC -> PTerm -> PTerm -> Idris ()
2482−checkInferred fc inf user =
2483− do logLvl 6 $ "Checked to\n" ++ showTmImpls inf ++ "\n\nFROM\n\n" ++
2484− showTmImpls user
2485− logLvl 10 $ "Checking match"
2486− i <- getIState
2487− tclift $ case matchClause' True i user inf of
2488− _ -> return ()
2489−-- Left (x, y) -> tfail $ At fc
2490−-- (Msg $ "The type-checked term and given term do not match: "
2491−-- ++ show x ++ " and " ++ show y)
2492− logLvl 10 $ "Checked match"
2493−-- ++ "\n" ++ showImp True inf ++ "\n" ++ showImp True user)
2494−
2495−-- Return whether inferred term is different from given term
2496−-- (as above, but return a Bool)
2497−
2498−inferredDiff :: FC -> PTerm -> PTerm -> Idris Bool
2499−inferredDiff fc inf user =
2500− do i <- getIState
2501− logLvl 6 $ "Checked to\n" ++ showTmImpls inf ++ "\n" ++
2502− showTmImpls user
2503− tclift $ case matchClause' True i user inf of
2504− Right vs -> return False
2505− Left (x, y) -> return True
2506−
2507−-- | Check a PTerm against documentation and ensure that every documented
2508−-- argument actually exists. This must be run _after_ implicits have been
2509−-- found, or it will give spurious errors.
2510−checkDocs :: FC -> [(Name, Docstring)] -> PTerm -> Idris ()
2511−checkDocs fc args tm = cd (Map.fromList args) tm
2512− where cd as (PPi _ n _ sc) = cd (Map.delete n as) sc
2513− cd as _ | Map.null as = return ()
2514− | otherwise = ierror . At fc . Msg $
2515− "There is documentation for argument(s) "
2516− ++ (concat . intersperse ", " . map show . Map.keys) as
2517− ++ " but they were not found."
src/Idris/ElabTerm.hs+92−26
@@ -26,6 +26,8 @@ import qualified Data.Map as M
26import Data.Maybe (mapMaybe, fromMaybe)
26import Data.Maybe (mapMaybe, fromMaybe)
27import qualified Data.Set as S
27import qualified Data.Set as S
28import qualified Data.Text as T
28import qualified Data.Text as T
29+import Data.Vector.Unboxed (Vector)
30+import qualified Data.Vector.Unboxed as V
29
31
30import Debug.Trace
32import Debug.Trace
31
33
@@ -853,9 +855,23 @@ elab ist info emode opts fn tm
853 addImplBound ist (map fst env) (PApp fc (PRef fc (sUN "Delay"))
855 addImplBound ist (map fst env) (PApp fc (PRef fc (sUN "Delay"))
854 [pexp t])
856 [pexp t])
855
857
858+
859+ -- Don't put implicit coercions around applications which are marked
860+ -- as '%noImplicit', or around case blocks, otherwise we get exponential
861+ -- blowup especially where there are errors deep in large expressions.
862+ notImplicitable (PApp _ f _) = notImplicitable f
863+ -- TMP HACK no coercing on bind (make this configurable)
864+ notImplicitable (PRef _ n)
865+ | [opts] <- lookupCtxt n (idris_flags ist)
866+ = NoImplicit `elem` opts
867+ notImplicitable (PAlternative True as) = any notImplicitable as
856 -- case is tricky enough without implicit coercions! If they are needed,
868 -- case is tricky enough without implicit coercions! If they are needed,
857 -- they can go in the branches separately.
869 -- they can go in the branches separately.
870+ notImplicitable (PCase _ _ _) = True
871+ notImplicitable _ = False
872+
858 insertCoerce ina t@(PCase _ _ _) = return t
873 insertCoerce ina t@(PCase _ _ _) = return t
874+ insertCoerce ina t | notImplicitable t = return t
859 insertCoerce ina t =
875 insertCoerce ina t =
860 do ty <- goal
876 do ty <- goal
861 -- Check for possible coercions to get to the goal
877 -- Check for possible coercions to get to the goal
@@ -1359,6 +1375,8 @@ runTac autoSolve ist fn tac
1359 _ -> fail "Wrong goal type"
1375 _ -> fail "Wrong goal type"
1360 runT ProofState = do g <- goal
1376 runT ProofState = do g <- goal
1361 return ()
1377 return ()
1378+ runT Skip = return ()
1379+ runT (TFail err) = lift . tfail $ ReflectionError [err] (Msg "")
1362 runT x = fail $ "Not implemented " ++ show x
1380 runT x = fail $ "Not implemented " ++ show x
1363
1381
1364 runReflected t = do t' <- reify ist t
1382 runReflected t = do t' <- reify ist t
@@ -1376,6 +1394,7 @@ reify _ (P _ n _) | n == reflm "Trivial" = return Trivial
1376reify _ (P _ n _) | n == reflm "Instance" = return TCInstance
1394reify _ (P _ n _) | n == reflm "Instance" = return TCInstance
1377reify _ (P _ n _) | n == reflm "Solve" = return Solve
1395reify _ (P _ n _) | n == reflm "Solve" = return Solve
1378reify _ (P _ n _) | n == reflm "Compute" = return Compute
1396reify _ (P _ n _) | n == reflm "Compute" = return Compute
1397+reify _ (P _ n _) | n == reflm "Skip" = return Skip
1379reify ist t@(App _ _)
1398reify ist t@(App _ _)
1380 | (P _ f _, args) <- unApply t = reifyApp ist f args
1399 | (P _ f _, args) <- unApply t = reifyApp ist f args
1381reify _ t = fail ("Unknown tactic " ++ show t)
1400reify _ t = fail ("Unknown tactic " ++ show t)
@@ -1416,6 +1435,15 @@ reifyApp ist t [n, tt', t']
1416 tt'' <- reifyTT tt'
1435 tt'' <- reifyTT tt'
1417 t'' <- reifyTT t'
1436 t'' <- reifyTT t'
1418 return $ LetTacTy n' (delab ist tt'') (delab ist t'')
1437 return $ LetTacTy n' (delab ist tt'') (delab ist t'')
1438+reifyApp ist t [errs]
1439+ | t == reflm "Fail" = case unList errs of
1440+ Nothing -> fail "Failed to reify errors"
1441+ Just errs' ->
1442+ let parts = mapM reifyReportPart errs' in
1443+ case parts of
1444+ Left err -> fail $ "Couldn't reify \"Fail\" tactic - " ++ show err
1445+ Right errs'' ->
1446+ return $ TFail errs''
1419reifyApp _ f args = fail ("Unknown tactic " ++ show (f, args)) -- shouldn't happen
1447reifyApp _ f args = fail ("Unknown tactic " ++ show (f, args)) -- shouldn't happen
1420
1448
1421-- | Reify terms from their reflected representation
1449-- | Reify terms from their reflected representation
@@ -1547,15 +1575,7 @@ reifyTTBinderApp reif f [t]
1547reifyTTBinderApp _ f args = fail ("Unknown reflection binder: " ++ show (f, args))
1575reifyTTBinderApp _ f args = fail ("Unknown reflection binder: " ++ show (f, args))
1548
1576
1549reifyTTConst :: Term -> ElabD Const
1577reifyTTConst :: Term -> ElabD Const
1550−reifyTTConst (P _ n _) | n == reflm "IType" = return (AType (ATInt ITNative))
1551−reifyTTConst (P _ n _) | n == reflm "BIType" = return (AType (ATInt ITBig))
1552−reifyTTConst (P _ n _) | n == reflm "FlType" = return (AType ATFloat)
1553−reifyTTConst (P _ n _) | n == reflm "ChType" = return (AType (ATInt ITChar))
1554reifyTTConst (P _ n _) | n == reflm "StrType" = return $ StrType
1578reifyTTConst (P _ n _) | n == reflm "StrType" = return $ StrType
1555−reifyTTConst (P _ n _) | n == reflm "B8Type" = return (AType (ATInt (ITFixed IT8)))
1556−reifyTTConst (P _ n _) | n == reflm "B16Type" = return (AType (ATInt (ITFixed IT16)))
1557−reifyTTConst (P _ n _) | n == reflm "B32Type" = return (AType (ATInt (ITFixed IT32)))
1558−reifyTTConst (P _ n _) | n == reflm "B64Type" = return (AType (ATInt (ITFixed IT64)))
1559reifyTTConst (P _ n _) | n == reflm "PtrType" = return $ PtrType
1579reifyTTConst (P _ n _) | n == reflm "PtrType" = return $ PtrType
1560reifyTTConst (P _ n _) | n == reflm "VoidType" = return $ VoidType
1580reifyTTConst (P _ n _) | n == reflm "VoidType" = return $ VoidType
1561reifyTTConst (P _ n _) | n == reflm "Forgot" = return $ Forgot
1581reifyTTConst (P _ n _) | n == reflm "Forgot" = return $ Forgot
@@ -1564,6 +1584,8 @@ reifyTTConst t@(App _ _)
1564reifyTTConst t = fail ("Unknown reflection constant: " ++ show t)
1584reifyTTConst t = fail ("Unknown reflection constant: " ++ show t)
1565
1585
1566reifyTTConstApp :: Name -> Term -> ElabD Const
1586reifyTTConstApp :: Name -> Term -> ElabD Const
1587+reifyTTConstApp f aty
1588+ | f == reflm "AType" = fmap AType (reifyArithTy aty)
1567reifyTTConstApp f (Constant c@(I _))
1589reifyTTConstApp f (Constant c@(I _))
1568 | f == reflm "I" = return $ c
1590 | f == reflm "I" = return $ c
1569reifyTTConstApp f (Constant c@(BI _))
1591reifyTTConstApp f (Constant c@(BI _))
@@ -1584,6 +1606,26 @@ reifyTTConstApp f (Constant c@(B64 _))
1584 | f == reflm "B64" = return $ c
1606 | f == reflm "B64" = return $ c
1585reifyTTConstApp f arg = fail ("Unknown reflection constant: " ++ show (f, arg))
1607reifyTTConstApp f arg = fail ("Unknown reflection constant: " ++ show (f, arg))
1586
1608
1609+reifyArithTy :: Term -> ElabD ArithTy
1610+reifyArithTy (App (P _ n _) intTy) | n == reflm "ATInt" = fmap ATInt (reifyIntTy intTy)
1611+reifyArithTy (P _ n _) | n == reflm "ATFloat" = return ATFloat
1612+reifyArithTy x = fail ("Couldn't reify reflected ArithTy: " ++ show x)
1613+
1614+reifyNativeTy :: Term -> ElabD NativeTy
1615+reifyNativeTy (P _ n _) | n == reflm "IT8" = return IT8
1616+reifyNativeTy (P _ n _) | n == reflm "IT8" = return IT8
1617+reifyNativeTy (P _ n _) | n == reflm "IT8" = return IT8
1618+reifyNativeTy (P _ n _) | n == reflm "IT8" = return IT8
1619+reifyNativeTy x = fail $ "Couldn't reify reflected NativeTy " ++ show x
1620+
1621+reifyIntTy :: Term -> ElabD IntTy
1622+reifyIntTy (App (P _ n _) nt) | n == reflm "ITFixed" = fmap ITFixed (reifyNativeTy nt)
1623+reifyIntTy (P _ n _) | n == reflm "ITNative" = return ITNative
1624+reifyIntTy (P _ n _) | n == reflm "ITBig" = return ITBig
1625+reifyIntTy (P _ n _) | n == reflm "ITChar" = return ITChar
1626+reifyIntTy (App (App (P _ n _) nt) (Constant (I i))) | n == reflm "ITVec" = fmap (flip ITVec i)
1627+ (reifyNativeTy nt)
1628+
1587reifyTTUExp :: Term -> ElabD UExp
1629reifyTTUExp :: Term -> ElabD UExp
1588reifyTTUExp t@(App _ _)
1630reifyTTUExp t@(App _ _)
1589 = case unApply t of
1631 = case unApply t of
@@ -1778,8 +1820,9 @@ reflectName (MN i n)
1778reflectName (NErased) = Var (reflm "NErased")
1820reflectName (NErased) = Var (reflm "NErased")
1779reflectName n = Var (reflm "NErased") -- special name, not yet implemented
1821reflectName n = Var (reflm "NErased") -- special name, not yet implemented
1780
1822
1781−-- | Elaborate a name to a pattern. This means that NS and UN will be intact,
1823+-- | Elaborate a name to a pattern. This means that NS and UN will be intact.
1824+-- MNs corresponding to will care about the string but not the number. All
1782−-- while all others become _
1825+-- others become _.
1783reflectNameQuotePattern :: Name -> ElabD ()
1826reflectNameQuotePattern :: Name -> ElabD ()
1784reflectNameQuotePattern n@(UN s)
1827reflectNameQuotePattern n@(UN s)
1785 = do fill $ reflectName n
1828 = do fill $ reflectName n
@@ -1787,6 +1830,12 @@ reflectNameQuotePattern n@(UN s)
1787reflectNameQuotePattern n@(NS _ _)
1830reflectNameQuotePattern n@(NS _ _)
1788 = do fill $ reflectName n
1831 = do fill $ reflectName n
1789 solve
1832 solve
1833+reflectNameQuotePattern (MN _ n)
1834+ = do i <- getNameFrom (sMN 0 "mnCounter")
1835+ claim i (RConstant (AType (ATInt ITNative)))
1836+ movelast i
1837+ fill $ reflCall "MN" [Var i, RConstant (Str $ T.unpack n)]
1838+ solve
1790reflectNameQuotePattern _ -- for all other names, match any
1839reflectNameQuotePattern _ -- for all other names, match any
1791 = do nameHole <- getNameFrom (sMN 0 "name")
1840 = do nameHole <- getNameFrom (sMN 0 "name")
1792 claim nameHole (Var (reflm "TTName"))
1841 claim nameHole (Var (reflm "TTName"))
@@ -1817,28 +1866,45 @@ reflectBinderQuote unq (PVar t)
1817reflectBinderQuote unq (PVTy t)
1866reflectBinderQuote unq (PVTy t)
1818 = reflCall "PVTy" [Var (reflm "TT"), reflectQuote unq t]
1867 = reflCall "PVTy" [Var (reflm "TT"), reflectQuote unq t]
1819
1868
1869+mkList :: Raw -> [Raw] -> Raw
1870+mkList ty [] = RApp (Var (sNS (sUN "Nil") ["List", "Prelude"])) ty
1871+mkList ty (x:xs) = RApp (RApp (RApp (Var (sNS (sUN "::") ["List", "Prelude"])) ty)
1872+ x)
1873+ (mkList ty xs)
1874+
1820reflectConstant :: Const -> Raw
1875reflectConstant :: Const -> Raw
1821reflectConstant c@(I _) = reflCall "I" [RConstant c]
1876reflectConstant c@(I _) = reflCall "I" [RConstant c]
1822reflectConstant c@(BI _) = reflCall "BI" [RConstant c]
1877reflectConstant c@(BI _) = reflCall "BI" [RConstant c]
1823reflectConstant c@(Fl _) = reflCall "Fl" [RConstant c]
1878reflectConstant c@(Fl _) = reflCall "Fl" [RConstant c]
1824reflectConstant c@(Ch _) = reflCall "Ch" [RConstant c]
1879reflectConstant c@(Ch _) = reflCall "Ch" [RConstant c]
1825reflectConstant c@(Str _) = reflCall "Str" [RConstant c]
1880reflectConstant c@(Str _) = reflCall "Str" [RConstant c]
1826−reflectConstant (AType (ATInt ITNative)) = Var (reflm "IType")
1827−reflectConstant (AType (ATInt ITBig)) = Var (reflm "BIType")
1828−reflectConstant (AType ATFloat) = Var (reflm "FlType")
1829−reflectConstant (AType (ATInt ITChar)) = Var (reflm "ChType")
1830−reflectConstant (StrType) = Var (reflm "StrType")
1831reflectConstant c@(B8 _) = reflCall "B8" [RConstant c]
1881reflectConstant c@(B8 _) = reflCall "B8" [RConstant c]
1832reflectConstant c@(B16 _) = reflCall "B16" [RConstant c]
1882reflectConstant c@(B16 _) = reflCall "B16" [RConstant c]
1833reflectConstant c@(B32 _) = reflCall "B32" [RConstant c]
1883reflectConstant c@(B32 _) = reflCall "B32" [RConstant c]
1834reflectConstant c@(B64 _) = reflCall "B64" [RConstant c]
1884reflectConstant c@(B64 _) = reflCall "B64" [RConstant c]
1885+reflectConstant (B8V ws) = reflCall "B8V" [mkList (Var (sUN "Bits8")) . map (RConstant . B8) . V.toList $ ws]
1886+reflectConstant (B16V ws) = reflCall "B8V" [mkList (Var (sUN "Bits16")) . map (RConstant . B16) . V.toList $ ws]
1887+reflectConstant (B32V ws) = reflCall "B8V" [mkList (Var (sUN "Bits32")) . map (RConstant . B32) . V.toList $ ws]
1888+reflectConstant (B64V ws) = reflCall "B8V" [mkList (Var (sUN "Bits64")) . map (RConstant . B64) . V.toList $ ws]
1889+reflectConstant (AType (ATInt ITNative)) = reflCall "AType" [reflCall "ATInt" [Var (reflm "ITNative")]]
1890+reflectConstant (AType (ATInt ITBig)) = reflCall "AType" [reflCall "ATInt" [Var (reflm "ITBig")]]
1891+reflectConstant (AType ATFloat) = reflCall "AType" [Var (reflm "ATFloat")]
1892+reflectConstant (AType (ATInt ITChar)) = reflCall "AType" [reflCall "ATInt" [Var (reflm "ITChar")]]
1893+reflectConstant StrType = Var (reflm "StrType")
1835−reflectConstant (AType (ATInt (ITFixed IT8))) = Var (reflm "B8Type")
1894+reflectConstant (AType (ATInt (ITFixed IT8))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITFixed" [Var (reflm "IT8")]]]
1836−reflectConstant (AType (ATInt (ITFixed IT16))) = Var (reflm "B16Type")
1895+reflectConstant (AType (ATInt (ITFixed IT16))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITFixed" [Var (reflm "IT16")]]]
1837−reflectConstant (AType (ATInt (ITFixed IT32))) = Var (reflm "B32Type")
1896+reflectConstant (AType (ATInt (ITFixed IT32))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITFixed" [Var (reflm "IT32")]]]
1838−reflectConstant (AType (ATInt (ITFixed IT64))) = Var (reflm "B64Type")
1897+reflectConstant (AType (ATInt (ITFixed IT64))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITFixed" [Var (reflm "IT64")]]]
1839−reflectConstant (PtrType) = Var (reflm "PtrType")
1898+reflectConstant (AType (ATInt (ITVec IT8 c))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITVec" [Var (reflm "IT8"), RConstant (I c)]]]
1899+reflectConstant (AType (ATInt (ITVec IT16 c))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITVec" [Var (reflm "IT16"), RConstant (I c)]]]
1900+reflectConstant (AType (ATInt (ITVec IT32 c))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITVec" [Var (reflm "IT32"), RConstant (I c)]]]
1901+reflectConstant (AType (ATInt (ITVec IT64 c))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITVec" [Var (reflm "IT64"), RConstant (I c)]]]
1902+reflectConstant PtrType = Var (reflm "PtrType")
1903+reflectConstant ManagedPtrType = Var (reflm "ManagedPtrType")
1904+reflectConstant BufferType = Var (reflm "BufferType")
1840−reflectConstant (VoidType) = Var (reflm "VoidType")
1905+reflectConstant VoidType = Var (reflm "VoidType")
1841−reflectConstant (Forgot) = Var (reflm "Forgot")
1906+reflectConstant Forgot = Var (reflm "Forgot")
1907+
1842
1908
1843reflectUExp :: UExp -> Raw
1909reflectUExp :: UExp -> Raw
1844reflectUExp (UVar i) = reflCall "UVar" [RConstant (I i)]
1910reflectUExp (UVar i) = reflCall "UVar" [RConstant (I i)]
@@ -2042,10 +2108,10 @@ reflErrName n = sNS (sUN n) ["Errors", "Reflection", "Language"]
2042-- representation. Not in Idris or ElabD monads because it should be usable
2108-- representation. Not in Idris or ElabD monads because it should be usable
2043-- from either.
2109-- from either.
2044reifyReportPart :: Term -> Either Err ErrorReportPart
2110reifyReportPart :: Term -> Either Err ErrorReportPart
2045−reifyReportPart (App (P (DCon _ _) n _) (Constant (Str msg))) | n == reflErrName "TextPart" =
2111+reifyReportPart (App (P (DCon _ _) n _) (Constant (Str msg))) | n == reflm "TextPart" =
2046 Right (TextPart msg)
2112 Right (TextPart msg)
2047reifyReportPart (App (P (DCon _ _) n _) ttn)
2113reifyReportPart (App (P (DCon _ _) n _) ttn)
2048− | n == reflErrName "NamePart" =
2114+ | n == reflm "NamePart" =
2049 case runElab [] (reifyTTName ttn) (initElaborator NErased initContext Erased) of
2115 case runElab [] (reifyTTName ttn) (initElaborator NErased initContext Erased) of
2050 Error e -> Left . InternalMsg $
2116 Error e -> Left . InternalMsg $
2051 "could not reify name term " ++
2117 "could not reify name term " ++
@@ -2053,7 +2119,7 @@ reifyReportPart (App (P (DCon _ _) n _) ttn)
2053 " when reflecting an error:" ++ show e
2119 " when reflecting an error:" ++ show e
2054 OK (n', _)-> Right $ NamePart n'
2120 OK (n', _)-> Right $ NamePart n'
2055reifyReportPart (App (P (DCon _ _) n _) tm)
2121reifyReportPart (App (P (DCon _ _) n _) tm)
2056− | n == reflErrName "TermPart" =
2122+ | n == reflm "TermPart" =
2057 case runElab [] (reifyTT tm) (initElaborator NErased initContext Erased) of
2123 case runElab [] (reifyTT tm) (initElaborator NErased initContext Erased) of
2058 Error e -> Left . InternalMsg $
2124 Error e -> Left . InternalMsg $
2059 "could not reify reflected term " ++
2125 "could not reify reflected term " ++
@@ -2061,7 +2127,7 @@ reifyReportPart (App (P (DCon _ _) n _) tm)
2061 " when reflecting an error:" ++ show e
2127 " when reflecting an error:" ++ show e
2062 OK (tm', _) -> Right $ TermPart tm'
2128 OK (tm', _) -> Right $ TermPart tm'
2063reifyReportPart (App (P (DCon _ _) n _) tm)
2129reifyReportPart (App (P (DCon _ _) n _) tm)
2064− | n == reflErrName "SubReport" =
2130+ | n == reflm "SubReport" =
2065 case unList tm of
2131 case unList tm of
2066 Just xs -> do subParts <- mapM reifyReportPart xs
2132 Just xs -> do subParts <- mapM reifyReportPart xs
2067 Right (SubReport subParts)
2133 Right (SubReport subParts)
src/Idris/IBC.hs+3
@@ -274,6 +274,7 @@ process i fn
274 pDefs (symbols i) (ibc_defs i)
274 pDefs (symbols i) (ibc_defs i)
275 pPatdefs (ibc_patdefs i)
275 pPatdefs (ibc_patdefs i)
276 pAccess (ibc_access i)
276 pAccess (ibc_access i)
277+ pFlags (ibc_flags i)
277 pTotal (ibc_total i)
278 pTotal (ibc_total i)
278 pTotCheckErr (ibc_totcheckfail i)
279 pTotCheckErr (ibc_totcheckfail i)
279 pCG (ibc_cg i)
280 pCG (ibc_cg i)
@@ -943,6 +944,7 @@ instance Binary FnOpt where
943 ErrorHandler -> putWord8 9
944 ErrorHandler -> putWord8 9
944 ErrorReverse -> putWord8 10
945 ErrorReverse -> putWord8 10
945 CoveringFn -> putWord8 11
946 CoveringFn -> putWord8 11
947+ NoImplicit -> putWord8 12
946 get
948 get
947 = do i <- getWord8
949 = do i <- getWord8
948 case i of
950 case i of
@@ -959,6 +961,7 @@ instance Binary FnOpt where
959 9 -> return ErrorHandler
961 9 -> return ErrorHandler
960 10 -> return ErrorReverse
962 10 -> return ErrorReverse
961 11 -> return CoveringFn
963 11 -> return CoveringFn
964+ 12 -> return NoImplicit
962 _ -> error "Corrupted binary data for FnOpt"
965 _ -> error "Corrupted binary data for FnOpt"
963
966
964instance Binary Fixity where
967instance Binary Fixity where
src/Idris/Interactive.hs+4−2
@@ -18,6 +18,8 @@ import Idris.Delaborate
18import Idris.Output
18import Idris.Output
19import Idris.IdeSlave hiding (IdeSlaveCommand(..))
19import Idris.IdeSlave hiding (IdeSlaveCommand(..))
20
20
21+import Idris.Elab.Value
22+
21import Util.Pretty
23import Util.Pretty
22import Util.System
24import Util.System
23
25
@@ -174,8 +176,8 @@ doProofSearch h fn updatefile rec l n hints (Just depth)
174 (ProofSearch rec False depth t hints)]
176 (ProofSearch rec False depth t hints)]
175 let def = PClause fc mn (PRef fc mn) [] (body top) []
177 let def = PClause fc mn (PRef fc mn) [] (body top) []
176 newmv <- idrisCatch
178 newmv <- idrisCatch
177− (do elabDecl' EAll toplevel (PClauses fc [] mn [def])
179+ (do elabDecl' EAll recinfo (PClauses fc [] mn [def])
178− (tm, ty) <- elabVal toplevel ERHS (PRef fc mn)
180+ (tm, ty) <- elabVal recinfo ERHS (PRef fc mn)
179 ctxt <- getContext
181 ctxt <- getContext
180 i <- getIState
182 i <- getIState
181 return . flip displayS "" . renderPretty 1.0 80 $
183 return . flip displayS "" . renderPretty 1.0 80 $
src/Idris/ParseExpr.hs+5−1
@@ -320,7 +320,7 @@ simpleExpr syn =
320 <|> idiom syn
320 <|> idiom syn
321 <|> listExpr syn
321 <|> listExpr syn
322 <|> alt syn
322 <|> alt syn
323− <|> do lchar '!'
323+ <|> do reservedOp "!"
324 s <- simpleExpr syn
324 s <- simpleExpr syn
325 fc <- getFC
325 fc <- getFC
326 return (PAppBind fc s [])
326 return (PAppBind fc s [])
@@ -1278,6 +1278,10 @@ tactic syn = do reserved "intro"; ns <- sepBy (indentPropHolds gtProp *> name) (
1278 <|> do reserved "undo"; return Undo
1278 <|> do reserved "undo"; return Undo
1279 <|> do reserved "qed"; return Qed
1279 <|> do reserved "qed"; return Qed
1280 <|> do reserved "abandon"; return Abandon
1280 <|> do reserved "abandon"; return Abandon
1281+ <|> do reserved "skip"; return Skip
1282+ <|> do reserved "fail"
1283+ msg <- stringLiteral
1284+ return $ TFail [Idris.Core.TT.TextPart msg]
1281 <|> do lchar ':';
1285 <|> do lchar ':';
1282 ( (do reserved "q"; return Abandon)
1286 ( (do reserved "q"; return Abandon)
1283 <|> (do (reserved "e" <|> reserved "eval");
1287 <|> (do (reserved "e" <|> reserved "eval");
src/Idris/Parser.hs+3
@@ -376,6 +376,7 @@ fnDecl' syn = checkFixity $
376FnOpts ::= 'total'
376FnOpts ::= 'total'
377 | 'partial'
377 | 'partial'
378 | 'implicit'
378 | 'implicit'
379+ | '%' 'no_implicit'
379 | '%' 'assert_total'
380 | '%' 'assert_total'
380 | '%' 'error_handler'
381 | '%' 'error_handler'
381 | '%' 'reflection'
382 | '%' 'reflection'
@@ -402,6 +403,8 @@ fnOpts opts
402 <|> do reserved "covering"; fnOpts (CoveringFn : (opts \\ [TotalFn]))
403 <|> do reserved "covering"; fnOpts (CoveringFn : (opts \\ [TotalFn]))
403 <|> do try (lchar '%' *> reserved "export"); c <- stringLiteral;
404 <|> do try (lchar '%' *> reserved "export"); c <- stringLiteral;
404 fnOpts (CExport c : opts)
405 fnOpts (CExport c : opts)
406+ <|> do try (lchar '%' *> reserved "no_implicit");
407+ fnOpts (NoImplicit : opts)
405 <|> do try (lchar '%' *> reserved "assert_total");
408 <|> do try (lchar '%' *> reserved "assert_total");
406 fnOpts (AssertTotal : opts)
409 fnOpts (AssertTotal : opts)
407 <|> do try (lchar '%' *> reserved "error_handler");
410 <|> do try (lchar '%' *> reserved "error_handler");
src/Idris/Prover.hs+5−2
@@ -6,6 +6,9 @@ import Idris.Core.Evaluate
6import Idris.Core.CaseTree
6import Idris.Core.CaseTree
7import Idris.Core.Typecheck
7import Idris.Core.Typecheck
8
8
9+import Idris.Elab.Utils
10+import Idris.Elab.Value
11+
9import Idris.AbsSyntax
12import Idris.AbsSyntax
10import Idris.AbsSyntaxTree
13import Idris.AbsSyntaxTree
11import Idris.Delaborate
14import Idris.Delaborate
@@ -272,7 +275,7 @@ ploop fn d prompt prf e h
272 let OK env = envAtFocus (proof e)
275 let OK env = envAtFocus (proof e)
273 ctxt' = envCtxt env ctxt
276 ctxt' = envCtxt env ctxt
274 putIState ist { tt_ctxt = ctxt' }
277 putIState ist { tt_ctxt = ctxt' }
275− (tm, ty) <- elabVal toplevel ERHS t
278+ (tm, ty) <- elabVal recinfo ERHS t
276 let ppo = ppOptionIst ist
279 let ppo = ppOptionIst ist
277 ty' = normaliseC ctxt [] ty
280 ty' = normaliseC ctxt [] ty
278 h = idris_outh ist
281 h = idris_outh ist
@@ -296,7 +299,7 @@ ploop fn d prompt prf e h
296 ist' = ist { tt_ctxt = ctxt' }
299 ist' = ist { tt_ctxt = ctxt' }
297 bnd = map (\x -> (fst x, False)) env
300 bnd = map (\x -> (fst x, False)) env
298 putIState ist'
301 putIState ist'
299− (tm, ty) <- elabVal toplevel ERHS t
302+ (tm, ty) <- elabVal recinfo ERHS t
300 let tm' = force (normaliseAll ctxt' env tm)
303 let tm' = force (normaliseAll ctxt' env tm)
301 ty' = force (normaliseAll ctxt' env ty)
304 ty' = force (normaliseAll ctxt' env ty)
302 ppo = ppOption (idris_options ist')
305 ppo = ppOption (idris_options ist')
src/Idris/REPL.hs+20−11
@@ -34,6 +34,11 @@ import Idris.Interactive
34import Idris.WhoCalls
34import Idris.WhoCalls
35import Idris.TypeSearch (searchByType)
35import Idris.TypeSearch (searchByType)
36
36
37+import Idris.Elab.Type
38+import Idris.Elab.Clause
39+import Idris.Elab.Data
40+import Idris.Elab.Value
41+
37import Version_idris (gitHash)
42import Version_idris (gitHash)
38import Util.System
43import Util.System
39import Util.DynamicLinker
44import Util.DynamicLinker
@@ -655,7 +660,7 @@ process h fn (ChangeDirectory f)
655 return ()
660 return ()
656process h fn (Eval t)
661process h fn (Eval t)
657 = withErrorReflection $ do logLvl 5 $ show t
662 = withErrorReflection $ do logLvl 5 $ show t
658− (tm, ty) <- elabVal toplevel ERHS t
663+ (tm, ty) <- elabVal recinfo ERHS t
659 ctxt <- getContext
664 ctxt <- getContext
660 let tm' = force (normaliseAll ctxt [] tm)
665 let tm' = force (normaliseAll ctxt [] tm)
661 let ty' = force (normaliseAll ctxt [] ty)
666 let ty' = force (normaliseAll ctxt [] ty)
@@ -683,14 +688,18 @@ process h fn (NewDefn decls) = do
683 getClauseName (PClause fc name whole with rhs whereBlock) = name
688 getClauseName (PClause fc name whole with rhs whereBlock) = name
684 getClauseName (PWith fc name whole with rhs whereBlock) = name
689 getClauseName (PWith fc name whole with rhs whereBlock) = name
685 defineName :: [PDecl] -> Idris ()
690 defineName :: [PDecl] -> Idris ()
691+ defineName (tyDecl@(PTy docs argdocs syn fc opts name ty) : decls) = do
692+ elabDecl EAll recinfo tyDecl
693+ elabClauses recinfo fc opts name (concatMap getClauses decls)
686 defineName [PClauses fc opts _ [clause]] = do
694 defineName [PClauses fc opts _ [clause]] = do
687 let pterm = getRHS clause
695 let pterm = getRHS clause
688− (tm,ty) <- elabVal toplevel ERHS pterm
696+ (tm,ty) <- elabVal recinfo ERHS pterm
689 ctxt <- getContext
697 ctxt <- getContext
690 let tm' = force (normaliseAll ctxt [] tm)
698 let tm' = force (normaliseAll ctxt [] tm)
691 let ty' = force (normaliseAll ctxt [] ty)
699 let ty' = force (normaliseAll ctxt [] ty)
692 updateContext (addCtxtDef (getClauseName clause) (Function ty' tm'))
700 updateContext (addCtxtDef (getClauseName clause) (Function ty' tm'))
693 setReplDefined (Just $ getClauseName clause)
701 setReplDefined (Just $ getClauseName clause)
702+ defineName (PClauses{} : _) = tclift $ tfail (Msg "Only one function body is allowed without a type declaration.")
694 -- fixity and syntax declarations are ignored by elabDecls, so they'll have to be handled some other way
703 -- fixity and syntax declarations are ignored by elabDecls, so they'll have to be handled some other way
695 defineName (PFix fc fixity strs : defns) = do
704 defineName (PFix fc fixity strs : defns) = do
696 fmodifyState idris_fixities (map (Fix fixity) strs ++)
705 fmodifyState idris_fixities (map (Fix fixity) strs ++)
@@ -741,7 +750,7 @@ process h fn (Undefine names) = undefine names
741process h fn (ExecVal t)
750process h fn (ExecVal t)
742 = do ctxt <- getContext
751 = do ctxt <- getContext
743 ist <- getIState
752 ist <- getIState
744− (tm, ty) <- elabVal toplevel ERHS t
753+ (tm, ty) <- elabVal recinfo ERHS t
745-- let tm' = normaliseAll ctxt [] tm
754-- let tm' = normaliseAll ctxt [] tm
746 let ty' = normaliseAll ctxt [] ty
755 let ty' = normaliseAll ctxt [] ty
747 res <- execute tm
756 res <- execute tm
@@ -785,7 +794,7 @@ process h fn (Check (PRef _ n))
785
794
786
795
787process h fn (Check t)
796process h fn (Check t)
788− = do (tm, ty) <- elabVal toplevel ERHS t
797+ = do (tm, ty) <- elabVal recinfo ERHS t
789 ctxt <- getContext
798 ctxt <- getContext
790 ist <- getIState
799 ist <- getIState
791 let ppo = ppOptionIst ist
800 let ppo = ppOptionIst ist
@@ -880,7 +889,7 @@ process h fn (MakeLemma updatefile l n)
880process h fn (DoProofSearch updatefile rec l n hints)
889process h fn (DoProofSearch updatefile rec l n hints)
881 = doProofSearch h fn updatefile rec l n hints Nothing
890 = doProofSearch h fn updatefile rec l n hints Nothing
882process h fn (Spec t)
891process h fn (Spec t)
883− = do (tm, ty) <- elabVal toplevel ERHS t
892+ = do (tm, ty) <- elabVal recinfo ERHS t
884 ctxt <- getContext
893 ctxt <- getContext
885 ist <- getIState
894 ist <- getIState
886 let tm' = simplify ctxt [] {- (idris_statics ist) -} tm
895 let tm' = simplify ctxt [] {- (idris_statics ist) -} tm
@@ -959,13 +968,13 @@ process h fn (Prove n')
959 warnTotality
968 warnTotality
960
969
961process h fn (HNF t)
970process h fn (HNF t)
962− = do (tm, ty) <- elabVal toplevel ERHS t
971+ = do (tm, ty) <- elabVal recinfo ERHS t
963 ctxt <- getContext
972 ctxt <- getContext
964 ist <- getIState
973 ist <- getIState
965 let tm' = hnf ctxt [] tm
974 let tm' = hnf ctxt [] tm
966 iPrintResult (show (delab ist tm'))
975 iPrintResult (show (delab ist tm'))
967process h fn (TestInline t)
976process h fn (TestInline t)
968− = do (tm, ty) <- elabVal toplevel ERHS t
977+ = do (tm, ty) <- elabVal recinfo ERHS t
969 ctxt <- getContext
978 ctxt <- getContext
970 ist <- getIState
979 ist <- getIState
971 let tm' = inlineTerm ist tm
980 let tm' = inlineTerm ist tm
@@ -974,7 +983,7 @@ process h fn (TestInline t)
974process h fn Execute
983process h fn Execute
975 = idrisCatch
984 = idrisCatch
976 (do ist <- getIState
985 (do ist <- getIState
977− (m, _) <- elabVal toplevel ERHS
986+ (m, _) <- elabVal recinfo ERHS
978 (PApp fc
987 (PApp fc
979 (PRef fc (sUN "run__IO"))
988 (PRef fc (sUN "run__IO"))
980 [pexp $ PRef fc (sNS (sUN "main") ["Main"])])
989 [pexp $ PRef fc (sNS (sUN "main") ["Main"])])
@@ -990,7 +999,7 @@ process h fn Execute
990 (\e -> getIState >>= ihRenderError stdout . flip pprintErr e)
999 (\e -> getIState >>= ihRenderError stdout . flip pprintErr e)
991 where fc = fileFC "main"
1000 where fc = fileFC "main"
992process h fn (Compile codegen f)
1001process h fn (Compile codegen f)
993− = do (m, _) <- elabVal toplevel ERHS
1002+ = do (m, _) <- elabVal recinfo ERHS
994 (PApp fc (PRef fc (sUN "run__IO"))
1003 (PApp fc (PRef fc (sUN "run__IO"))
995 [pexp $ PRef fc (sNS (sUN "main") ["Main"])])
1004 [pexp $ PRef fc (sNS (sUN "main") ["Main"])])
996 compile codegen f m
1005 compile codegen f m
@@ -998,7 +1007,7 @@ process h fn (Compile codegen f)
998process h fn (LogLvl i) = setLogLevel i
1007process h fn (LogLvl i) = setLogLevel i
999-- Elaborate as if LHS of a pattern (debug command)
1008-- Elaborate as if LHS of a pattern (debug command)
1000process h fn (Pattelab t)
1009process h fn (Pattelab t)
1001− = do (tm, ty) <- elabVal toplevel ELHS t
1010+ = do (tm, ty) <- elabVal recinfo ELHS t
1002 iPrintResult $ show tm ++ "\n\n : " ++ show ty
1011 iPrintResult $ show tm ++ "\n\n : " ++ show ty
1003
1012
1004process h fn (Missing n)
1013process h fn (Missing n)
@@ -1416,7 +1425,7 @@ execScript expr = do i <- getIState
1416 Failure err -> do iputStrLn $ show (fixColour c err)
1425 Failure err -> do iputStrLn $ show (fixColour c err)
1417 runIO $ exitWith (ExitFailure 1)
1426 runIO $ exitWith (ExitFailure 1)
1418 Success term -> do ctxt <- getContext
1427 Success term -> do ctxt <- getContext
1419− (tm, _) <- elabVal toplevel ERHS term
1428+ (tm, _) <- elabVal recinfo ERHS term
1420 res <- execute tm
1429 res <- execute tm
1421 runIO $ exitWith ExitSuccess
1430 runIO $ exitWith ExitSuccess
1422
1431
src/Idris/TypeSearch.hs+2−2
@@ -28,7 +28,7 @@ import Idris.Core.TT hiding (score)
28import Idris.Core.Unify (match_unify)
28import Idris.Core.Unify (match_unify)
29import Idris.Delaborate (delabTy)
29import Idris.Delaborate (delabTy)
30import Idris.Docstrings (noDocs, overview)
30import Idris.Docstrings (noDocs, overview)
31−import Idris.ElabDecls (elabType')
31+import Idris.Elab.Type (elabType)
32import Idris.Output (ihRenderOutput, ihPrintResult, ihRenderResult)
32import Idris.Output (ihRenderOutput, ihPrintResult, ihRenderResult)
33
33
34import System.IO (Handle)
34import System.IO (Handle)
@@ -41,7 +41,7 @@ searchByType h pterm = do
41 pterm'' <- implicit toplevel syn n pterm'
41 pterm'' <- implicit toplevel syn n pterm'
42 i <- getIState
42 i <- getIState
43 let pterm''' = addImpl i pterm''
43 let pterm''' = addImpl i pterm''
44− ty <- elabType' False toplevel syn (fst noDocs) (snd noDocs) emptyFC [] n pterm'
44+ ty <- elabType toplevel syn (fst noDocs) (snd noDocs) emptyFC [] n pterm'
45 putIState i -- don't actually make any changes
45 putIState i -- don't actually make any changes
46 let names = searchUsing searchPred i ty
46 let names = searchUsing searchPred i ty
47 let names' = take numLimit $ names
47 let names' = take numLimit $ names
test/quasiquote004/Quasiquote004.idrnew file+51
@@ -0,0 +1,51 @@
1+module Quasiquote004
2+
3+import Language.Reflection
4+
5+%default total
6+
7+normPlus : List (TTName, Binder TT) -> TT -> Tactic
8+normPlus ctxt `((=) {Nat} {Nat} ~x ~y) = normPlus ctxt x `Seq` normPlus ctxt y
9+normPlus ctxt `(S ~n) = normPlus ctxt n
10+normPlus ctxt `(plus ~n (S ~m)) = Seq (Rewrite `(plusSuccRightSucc ~n ~m))
11+ (normPlus ctxt m)
12+normPlus _ _ = Skip
13+
14+
15+zero : List (TTName, Binder TT) -> TT -> Tactic
16+zero ctxt `(Nat) = Exact `(Z)
17+zero _ _ = Fail [TextPart "Not a Nat goal"]
18+
19+-- A number is fizzy if it is evenly divisible by 3
20+data Fizzy : Nat -> Type where
21+ ZeroFizzy : Fizzy Z
22+ Fizz : Fizzy n -> Fizzy (3 + n)
23+
24+-- Fizzy is a correct specification of divisibility by 3 - that is, if n is
25+-- fizzy then there exists some k such that n = 3*k.
26+fizzyCorrect : (n : Nat) -> Fizzy n -> (k : Nat ** n = 3 * k)
27+fizzyCorrect Z ZeroFizzy = (Z ** refl)
28+fizzyCorrect (S (S (S k))) (Fizz x) =
29+ let (k' ** ih) = fizzyCorrect k x
30+ in (S k' ** ?fizzyIsAOK)
31+
32+someNat : Nat
33+someNat = ?getMeNat
34+
35+notNat : String
36+notNat = ?getMeNat'
37+
38+---------- Proofs ----------
39+Quasiquote004.getMeNat = proof
40+ applyTactic zero
41+
42+Quasiquote004.fizzyIsAOK = proof
43+ compute
44+ intros
45+ applyTactic normPlus
46+ applyTactic normPlus
47+ rewrite ih
48+ trivial
49+
50+Quasiquote004.getMeNat' = proof
51+ applyTactic zero
test/quasiquote004/expectednew file+2
@@ -0,0 +1,2 @@
1+Quasiquote004.idr:50:25:When elaborating right hand side of Quasiquote004.getMeNat':
2+Not a Nat goal
test/quasiquote004/runnew file+3
@@ -0,0 +1,3 @@
1+#!/usr/bin/env bash
2+idris $@ --check --nocolour Quasiquote004.idr
3+rm -f *.ibc
test/reg049/expectednew file+2
@@ -0,0 +1,2 @@
1+reg049.idr:2:9:When elaborating constructor Main.Bogus:
2+{__False0} is not Main.Foo
test/reg049/reg049.idrnew file+5
@@ -0,0 +1,5 @@
1+data Foo : Type where
2+ Bogus : _|_
3+
4+uhOh : _|_
5+uhOh = Bogus
test/reg049/runnew file+3
@@ -0,0 +1,3 @@
1+#!/usr/bin/env bash
2+idris --nocolour --check $@ reg049.idr
3+rm -f *.ibc
test/reg050/badbangop.idrnew file+15
@@ -0,0 +1,15 @@
1+module badbangop
2+
3+-- Check that using "!" by itself as an operator does not work
4+
5+infixl 2 !
6+
7+(!) : List a -> Nat -> Maybe a
8+xs ! n = index' n xs
9+
10+aList : List Integer
11+aList = [1,2,3,4,5]
12+
13+opUse : Maybe Integer
14+opUse = aList ! 2
15+
test/reg050/baddoublebang.idrnew file+7
@@ -0,0 +1,7 @@
1+module baddoublebang
2+
3+-- Check that two bang bindings running together don't work
4+
5+doubleBang : Maybe (Maybe Nat) -> Maybe Nat
6+doubleBang mmn = do pure !!mmn
7+
test/reg050/expectednew file+27
@@ -0,0 +1,27 @@
1+badbangop.idr:16:1:When elaborating right hand side of opUse:
2+When elaborating an application of function Prelude.Monad.>>=:
3+ Can't unify
4+ List Integer
5+ with
6+ argTy -> retTy
7+
8+ Specifically:
9+ Can't unify
10+ List
11+ with
12+ \{uv0} => argTy -> uv
13+./baddoublebang.idr:6:26: error: not
14+ a terminator, expected: "$",
15+ "$>", "&&", "*", "+", "++", "-",
16+ "->", ".", "/", "/=", "::", ";",
17+ "<", "<$", "<$>", "<*>", "<+>",
18+ "<->", "<<", "<=", "<|>", "=",
19+ "==", ">", ">=", ">>", ">>=",
20+ "\\\\", "`", "in", "||", "~=~",
21+ ambiguous use of a left-associative operator,
22+ ambiguous use of a non-associative operator,
23+ ambiguous use of a right-associative operator,
24+ end of input, function argument,
25+ matching application expression
26+doubleBang mmn = do pure !!mmn
27+ ^
test/reg050/runnew file+5
@@ -0,0 +1,5 @@
1+#!/usr/bin/env bash
2+idris --nocolour --check $@ working.idr
3+idris --nocolour --check $@ badbangop.idr
4+idris --nocolour --check $@ baddoublebang.idr
5+rm -f *.ibc
test/reg050/working.idrnew file+21
@@ -0,0 +1,21 @@
1+module working
2+
3+-- Check that using an operator beginning with "!" works
4+
5+infixl 2 !!
6+
7+(!!) : List a -> Nat -> Maybe a
8+xs !! n = index' n xs
9+
10+aList : List Integer
11+aList = [1,2,3,4,5]
12+
13+opUse : Maybe Integer
14+opUse = aList !! 2
15+
16+opUseWithBang : Maybe Nat -> Maybe Integer
17+opUseWithBang mn = do aList !! !mn
18+
19+doubleBang : Maybe (Maybe Nat) -> Maybe Nat
20+doubleBang mmn = do pure ! !mmn
21+