on master help sign in
Merge remote-tracking branch 'refs/remotes/upstream/master' into issue/1318

Conflicts: CHANGELOG

commit40d07c4c2aa5438089a9f2846a2b6244ca3ab1b1 authorDavid Raymond Christiansen <david@davidchristiansen.dk> dateTue 5 Aug 2014, 09:51 (12 years ago) parent0337afed947282
49 files changed+4157−3005
CHANGELOG+1 idris.cabal+22−2 libs/base/Language/Reflection.idr+355−94 libs/base/Language/Reflection/Utils.idr+55−34 libs/effects/Effect/File.idr+9−5 libs/effects/Effects.idr+1 libs/effects/Makefile+11−4 src/Idris/AbsSyntax.hs+10−14 src/Idris/AbsSyntaxTree.hs+20−10 src/Idris/CaseSplit.hs+4−2 src/Idris/CmdOptions.hs+1 src/Idris/Core/Elaborate.hs+14−16 src/Idris/Core/ProofState.hs+30−105 src/Idris/Core/ProofTerm.hs+266 src/Idris/Core/Unify.hs+9 src/Idris/Elab/Class.hs+226 src/Idris/Elab/Clause.hs+877 src/Idris/Elab/Data.hs+489 src/Idris/Elab/Instance.hs+260 src/Idris/Elab/Provider.hs+117 src/Idris/Elab/Record.hs+242 src/Idris/Elab/Type.hs+200 src/Idris/Elab/Utils.hs+151 src/Idris/Elab/Value.hs+88 src/Idris/ElabDecls.hs+17−2252 src/Idris/ElabTerm.hs+79−24 src/Idris/Error.hs+2−3 src/Idris/IBC.hs+3 src/Idris/IdeSlave.hs+20−10 src/Idris/Interactive.hs+31−29 src/Idris/Output.hs+60−63 src/Idris/ParseExpr.hs+1−1 src/Idris/ParseHelpers.hs+2−2 src/Idris/Parser.hs+27−24 src/Idris/Prover.hs+56−47 src/Idris/REPL.hs+282−248 src/Idris/TypeSearch.hs+8−10 src/Pkg/Package.hs+1−1 src/Util/Net.hs+15−2 test/proof007/DefaultArgUnknownName.idr+7−1 test/proof007/expected+3−2 test/reg049/expected+2 test/reg049/reg049.idr+5 test/reg049/run+3 test/reg050/badbangop.idr+15 test/reg050/baddoublebang.idr+7 test/reg050/expected+27 test/reg050/run+5 test/reg050/working.idr+21
CHANGELOG+1
@@ -2,6 +2,7 @@ New in 0.9.15:
22--------------
33* Two new tactics: skip and fail. Skip does nothing, and fail takes a string as an argument and produces it as an error.
44* 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+* Stop showing irrelevant and inaccessible internal names in the interactive prover
56* The proof arguments in the List library functions are now implicit and solved automatically
67
78New in 0.9.14:
idris.cabal+22−2
@@ -1,5 +1,5 @@
11Name: idris
2−Version: 0.9.14
2+Version: 0.9.14.1
33License: BSD3
44License-file: LICENSE
55Author: Edwin Brady
@@ -241,6 +241,15 @@ Extra-source-files:
241241 test/reg047/run
242242 test/reg047/*.idr
243243 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
244253
245254 test/basic001/run
246255 test/basic001/*.idr
@@ -542,11 +551,22 @@ Library
542551 , Idris.Core.Evaluate
543552 , Idris.Core.Execute
544553 , Idris.Core.ProofState
554+ , Idris.Core.ProofTerm
545555 , Idris.Core.TC
546556 , Idris.Core.TT
547557 , Idris.Core.Typecheck
548558 , Idris.Core.Unify
549559
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+
550570 , Idris.AbsSyntax
551571 , Idris.AbsSyntaxTree
552572 , Idris.Apropos
@@ -649,7 +669,7 @@ Library
649669 , language-java >= 0.2.6
650670 , lens >= 4.1.1
651671 , mtl
652− , parsers >= 0.9 && < 0.11.0.2
672+ , parsers >= 0.9 && < 0.13
653673 , pretty
654674 , process
655675 , split
libs/base/Language/Reflection.idr+355−94
@@ -2,32 +2,44 @@ module Language.Reflection
22
33%access public
44
5−data TTName = UN String
6− -- ^ User-provided name
7− | NS TTName (List String)
8− -- ^ Root, namespaces
9− | MN Int String
10− -- ^ Machine chosen names
11− | NErased
12− -- ^ Name of somethng which is never used in scope
5+data TTName =
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`
11+ NS TTName (List String) |
12+ ||| Machine-chosen names
13+ MN Int String |
14+ ||| Name of something which is never used in scope
15+ NErased
1316%name TTName n, n'
1417
1518implicit
1619userSuppliedName : String -> TTName
1720userSuppliedName = UN
1821
19−data TTUExp = UVar Int
20− -- ^ universe variable
21− | UVal Int
22− -- ^ explicit universe variable
22+data TTUExp =
23+ ||| Universe variable
24+ UVar Int |
25+ ||| Explicit universe level
26+ UVal Int
2327%name TTUExp uexp
2428
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+
2536||| Primitive constants
2637data Const = I Int | BI Integer | Fl Float | Ch Char | Str String
27− | IType | BIType | FlType | ChType | StrType
2838 | B8 Bits8 | B16 Bits16 | B32 Bits32 | B64 Bits64
29− | B8Type | B16Type | B32Type | B64Type
30− | PtrType | VoidType | Forgot
39+ | B8V Bits8x16 | B16V Bits16x8
40+ | B32V Bits32x4 | B64V Bits64x2
41+ | AType ArithTy | StrType
42+ | PtrType | ManagedPtrType | BufferType | VoidType | Forgot
3143
3244%name Const c, c'
3345
@@ -125,91 +137,340 @@ instance Traversable Binder where
125137
126138
127139||| Reflection of the well typed core language
128−data TT = P NameType TTName TT
129− -- ^ named binders
130− | V Int
131− -- ^ variables
132− | Bind TTName (Binder TT) TT
133− -- ^ type annotated named bindings
134− | App TT TT
135− -- ^ (named) application of a function to a value
136− | TConst Const
137− -- ^ constants
138− | Proj TT Int
139− -- ^ argument projection; runtime only
140− | Erased
141− -- ^ erased terms
142− | Impossible
143− -- ^ impossible terms
144− | TType TTUExp
145− -- ^ types
146−
140+data TT =
141+ ||| A reference to some name (P for Parameter)
142+ P NameType TTName TT |
143+ ||| de Bruijn variables
144+ V Int |
145+ ||| Bind a variable
146+ Bind TTName (Binder TT) TT |
147+ ||| Apply one term to another
148+ App TT TT |
149+ ||| Embed a constant
150+ TConst Const |
151+ ||| Argument projection; runtime only
152+ Proj TT Int |
153+ ||| Erased terms
154+ Erased |
155+ ||| Impossible terms
156+ Impossible |
157+ ||| The type of types along (with universe constraints)
158+ TType TTUExp
147159%name TT tm, tm'
148160
149161||| Raw terms without types
150−data Raw = Var TTName
151− | RBind TTName (Binder Raw) Raw
152− | RApp Raw Raw
153− | RType
154− | RForce Raw
155− | RConstant Const
156−
162+data Raw =
163+ ||| Variables, global or local
164+ Var TTName |
165+ ||| Bind a variable
166+ RBind TTName (Binder Raw) Raw |
167+ ||| Application
168+ RApp Raw Raw |
169+ ||| The type of types
170+ RType |
171+ RForce Raw |
172+ ||| Embed a constant
173+ RConstant Const
157174%name Raw tm, tm'
158175
159176||| Error reports are a list of report parts
160−data ErrorReportPart = TextPart String
161− | NamePart TTName
162− | TermPart TT
163− | SubReport (List ErrorReportPart)
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)
164186%name ErrorReportPart part, p
165187
166−data Tactic = Try Tactic Tactic
167− -- ^ try the first tactic and resort to the second one on failure
168− | GoalType String Tactic
169− -- ^ only run if the goal has the right type
170− | Refine TTName
171− -- ^ resolve function name, find matching arguments in the
172− -- context and compute the proof target
173− | Seq Tactic Tactic
174− -- ^ apply both tactics in sequence
175− | Trivial
176− -- ^ intelligently construct the proof target from the context
177− | Search Int
178− -- ^ build a proof by applying contructors up to a maximum depth
179− | Instance
180− -- ^ resolve a type class
181− | Solve
182− -- ^ infer the proof target from the context
183− | Intros
184− -- ^ introduce all variables into the context
185− | Intro TTName
186− -- ^ introduce a named variable into the context, use the
187− -- first one if the given name is not found
188− | ApplyTactic TT
189− -- ^ invoke the reflected rep. of another tactic
190− | Reflect TT
191− -- ^ turn a value into its reflected representation
192− | ByReflection TT
193− -- ^ use a %reflection function
194− | Fill Raw
195− -- ^ turn a raw value back into a term
196− | Exact TT
197− -- ^ use the given value to conclude the proof
198− | Focus TTName
199− -- ^ focus a named hole
200− | Rewrite TT
201− -- ^ rewrite using the reflected rep. of a equality proof
202− | Induction TT
203− -- ^ do induction on the particular expression
204− | Case TT
205− -- ^ do case analysis on particular expression
206− | LetTac TTName TT
207− -- ^ name a reflected term
208− | LetTacTy TTName TT TT
209− -- ^ name a reflected term and type it
210− | Compute
211− -- ^ normalise the context
212− | Skip
213− -- ^ do nothing
214− | Fail (List ErrorReportPart)
188+||| A representation of Idris's tactics that can be returned from custom
189+||| tactic implementations. Generate these using `applyTactic`.
190+data Tactic =
191+ ||| Try the first tactic and resort to the second one on failure
192+ Try Tactic Tactic |
193+ ||| Only run if the goal has the right type
194+ GoalType String Tactic |
195+ ||| Resolve function name, find matching arguments in the
196+ ||| context and compute the proof target
197+ Refine TTName |
198+ ||| Apply both tactics in sequence
199+ Seq Tactic Tactic |
200+ ||| Intelligently construct the proof target from the context
201+ Trivial |
202+ ||| Build a proof by applying contructors up to a maximum depth
203+ Search Int |
204+ ||| Resolve a type class
205+ Instance |
206+ ||| Infer the proof target from the context
207+ Solve |
208+ ||| introduce all variables into the context
209+ Intros |
210+ ||| Introduce a named variable into the context, use the
211+ ||| first one if the given name is not found
212+ Intro TTName |
213+ ||| Invoke the reflected rep. of another tactic
214+ ApplyTactic TT |
215+ ||| Turn a value into its reflected representation
216+ Reflect TT |
217+ ||| Use a `%reflection` function
218+ ByReflection TT |
219+ ||| Turn a raw value back into a term
220+ Fill Raw |
221+ ||| Use the given value to conclude the proof
222+ Exact TT |
223+ ||| Focus on a particular hole
224+ Focus TTName |
225+ ||| Rewrite with an equality
226+ Rewrite TT |
227+ ||| Perform induction on a particular expression
228+ Induction TT |
229+ ||| Perform case analysis on a particular expression
230+ Case TT |
231+ ||| Name a reflected term
232+ LetTac TTName TT |
233+ ||| Name a reflected term and type it
234+ LetTacTy TTName TT TT |
235+ ||| Normalise the goal
236+ Compute |
237+ ||| Do nothing
238+ Skip |
239+ ||| Fail with an error message
240+ Fail (List ErrorReportPart)
215241%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/Utils.idr+55−34
@@ -3,6 +3,8 @@ module Language.Reflection.Utils
33import Language.Reflection
44import Language.Reflection.Errors
55
6+%default total
7+
68--------------------------------------------------------
79-- Tactic construction conveniences
810--------------------------------------------------------
@@ -83,46 +85,65 @@ instance Show Const where
8385 show (Fl f) = "(Fl " ++ show f ++ ")"
8486 show (Ch c) = "(Ch " ++ show c ++ ")"
8587 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"
9188 show (B8 b) = "(B8 ...)"
9289 show (B16 b) = "(B16 ...)"
9390 show (B32 b) = "(B32 ...)"
9491 show (B64 b) = "(B64 ...)"
95− show B8Type = "B8Type"
96− show B16Type = "B16Type"
97− show B32Type = "B32Type"
98− show B64Type = "B64Type"
99− show PtrType = "PtrType"
100− show VoidType = "VoidType"
101− show Forgot = "Forgot"
92+ show (B8V xs) = "(B8V ...)"
93+ show (B16V xs) = "(B16V ...)"
94+ show (B32V xs) = "(B32V ...)"
95+ show (B64V xs) = "(B64V ...)"
96+ show (AType x) = "(AType ...)"
97+ show StrType = "StrType"
98+ show PtrType = "PtrType"
99+ show ManagedPtrType = "ManagedPtrType"
100+ show BufferType = "BufferType"
101+ show VoidType = "VoidType"
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
102123
103124instance Eq Const where
104− (I i) == (I i') = i == i'
105− (BI n) == (BI n') = n == n'
106− (Fl f) == (Fl f') = f == f'
107− (Ch c) == (Ch c') = c == c'
108− (Str str) == (Str str') = str == str'
109− IType == IType = True
110− BIType == BIType = True
111− FlType == FlType = True
112− ChType == ChType = True
113− StrType == StrType = True
114− (B8 b) == (B8 b') = False -- FIXME: b == b'
115− (B16 b) == (B16 b') = False -- FIXME: b == b'
116− (B32 b) == (B32 b') = False -- FIXME: b == b'
117− (B64 b) == (B64 b') = False -- FIXME: b == b'
118− B8Type == B8Type = True
119− B16Type == B16Type = True
120− B32Type == B32Type = True
121− B64Type == B64Type = True
122− PtrType == PtrType = True
123− VoidType == VoidType = True
124− Forgot == Forgot = True
125− x == y = False
125+ (I x) == (I y) = x == y
126+ (BI x) == (BI y) = x == y
127+ (Fl x) == (Fl y) = x == y
128+ (Ch x) == (Ch y) = x == y
129+ (Str x) == (Str y) = x == y
130+ (B8 x) == (B8 y) = x == y
131+ (B16 x) == (B16 y) = x == y
132+ (B32 x) == (B32 y) = x == y
133+ (B64 x) == (B64 y) = x == y
134+ (B8V xs) == (B8V ys) = False -- TODO
135+ (B16V xs) == (B16V ys) = False -- TODO
136+ (B32V xs) == (B32V ys) = False -- TODO
137+ (B64V xs) == (B64V ys) = False -- TODO
138+ (AType x) == (AType y) = x == y
139+ StrType == StrType = True
140+ PtrType == PtrType = True
141+ ManagedPtrType == ManagedPtrType = True
142+ BufferType == BufferType = True
143+ VoidType == VoidType = True
144+ Forgot == Forgot = True
145+ _ == _ = False
146+
126147
127148instance Show NameType where
128149 show Bound = "Bound"
libs/effects/Effect/File.idr+9−5
@@ -60,10 +60,10 @@ data FileIO : Effect where
6060 ||| Only files that are open for reading can be read.
6161 ReadLine : {OpenFile Read} FileIO String
6262
63− ||| Write a line to a file.
63+ ||| Write a string to a file.
6464 |||
6565 ||| Only file that are open for writing can be written to.
66− WriteLine : String -> {OpenFile Write} FileIO ()
66+ WriteString : String -> {OpenFile Write} FileIO ()
6767
6868 ||| End of file?
6969 |||
@@ -82,8 +82,8 @@ instance Handler FileIO IO where
8282 k () ()
8383 handle (FH h) ReadLine k = do str <- fread h
8484 k str (FH h)
85− handle (FH h) (WriteLine str) k = do fwrite h str
86− k () (FH h)
85+ handle (FH h) (WriteString str) k = do fwrite h str
86+ k () (FH h)
8787 handle (FH h) EOF k = do e <- feof h
8888 k e (FH h)
8989
@@ -117,9 +117,13 @@ close = call $ Close
117117readLine : { [FILE_IO (OpenFile Read)] } Eff String
118118readLine = call $ ReadLine
119119
120+||| Write a string to a file.
121+writeString : String -> { [FILE_IO (OpenFile Write)] } Eff ()
122+writeString str = call $ WriteString str
123+
120124||| Write a line to a file.
121125writeLine : String -> { [FILE_IO (OpenFile Write)] } Eff ()
122−writeLine str = call $ WriteLine str
126+writeLine str = call $ WriteString (str ++ "\n")
123127
124128||| End of file?
125129eof : { [FILE_IO (OpenFile Read)] } Eff Bool
libs/effects/Effects.idr+1
@@ -152,6 +152,7 @@ data Eff : (x : Type)
152152 Eff t [x] xs' -> -- [x] (\v => xs) ->
153153 Eff t [l ::: x] (\v => map (l :::) (xs' v))
154154
155+%no_implicit
155156(>>=) : Eff a xs xs' ->
156157 ((val : a) -> Eff b (xs' val) xs'') -> Eff b xs xs''
157158(>>=) = ebind
libs/effects/Makefile+11−4
@@ -1,14 +1,21 @@
11IDRIS := idris
2+PKG := effects
23
34build:
4− $(IDRIS) --build effects.ipkg
5+ $(IDRIS) --build ${PKG}.ipkg
56
67clean:
7− $(IDRIS) --clean effects.ipkg
8+ $(IDRIS) --clean ${PKG}.ipkg
89
910install:
10− $(IDRIS) --install effects.ipkg
11+ $(IDRIS) --install ${PKG}.ipkg
1112
1213rebuild: clean build
1314
14−.PHONY: build clean install rebuild
15+doc:
16+ $(IDRIS) --mkdoc ${PKG}.ipkg
17+
18+doc_clean:
19+ rm -rf ${PKG}_doc
20+
21+.PHONY: build clean install rebuild doc doc_clean
src/Idris/AbsSyntax.hs+10−14
@@ -537,7 +537,7 @@ type1Doc = (annotate (AnnType "Type" "The type of types, one level up") $ text "
537537isetPrompt :: String -> Idris ()
538538isetPrompt p = do i <- getIState
539539 case idris_outputmode i of
540− IdeSlave n -> runIO . putStrLn $ convSExp "set-prompt" p n
540+ IdeSlave n h -> runIO . hPutStrLn h $ convSExp "set-prompt" p n
541541
542542-- | Tell clients how much was parsed and loaded
543543isetLoadedRegion :: Idris ()
@@ -546,8 +546,8 @@ isetLoadedRegion = do i <- getIState
546546 case span of
547547 Just fc ->
548548 case idris_outputmode i of
549− IdeSlave n ->
550− runIO . putStrLn $
549+ IdeSlave n h ->
550+ runIO . hPutStrLn h $
551551 convSExp "set-loaded-region" fc n
552552 Nothing -> return ()
553553
@@ -662,10 +662,10 @@ outputTy :: Idris OutputType
662662outputTy = do i <- getIState
663663 return $ opt_outputTy $ idris_options i
664664
665−setIdeSlave :: Bool -> Idris ()
666−setIdeSlave True = do i <- getIState
667− putIState $ i { idris_outputmode = (IdeSlave 0), idris_colourRepl = False }
668−setIdeSlave False = return ()
665+setIdeSlave :: Bool -> Handle -> Idris ()
666+setIdeSlave True h = do i <- getIState
667+ putIState $ i { idris_outputmode = (IdeSlave 0 h), idris_colourRepl = False }
668+setIdeSlave False _ = return ()
669669
670670setTargetTriple :: String -> Idris ()
671671setTargetTriple t = do i <- getIState
@@ -761,10 +761,6 @@ setColourise :: Bool -> Idris ()
761761setColourise b = do i <- getIState
762762 putIState $ i { idris_colourRepl = b }
763763
764−setOutH :: Handle -> Idris ()
765−setOutH h = do i <- getIState
766− putIState $ i { idris_outh = h }
767−
768764impShow :: Idris Bool
769765impShow = do i <- getIState
770766 return (opt_showimp (idris_options i))
@@ -793,10 +789,10 @@ logLvl l str = do i <- getIState
793789 let lvl = opt_logLevel (idris_options i)
794790 when (lvl >= l) $
795791 case idris_outputmode i of
796− RawOutput -> do runIO $ putStrLn str
797− IdeSlave n ->
792+ RawOutput h -> do runIO $ hPutStrLn h str
793+ IdeSlave n h ->
798794 do let good = SexpList [IntegerAtom (toInteger l), toSExp str]
799− runIO $ putStrLn $ convSExp "log" good n
795+ runIO . hPutStrLn h $ convSExp "log" good n
800796
801797cmdOptType :: Opt -> Idris Bool
802798cmdOptType x = do i <- getIState
src/Idris/AbsSyntaxTree.hs+20−10
@@ -35,15 +35,24 @@ import Debug.Trace
3535
3636import Text.PrettyPrint.Annotated.Leijen
3737
38+data ElabWhat = ETypes | EDefns | EAll
39+ deriving (Show, Eq)
40+
3841-- Data to pass to recursively called elaborators; e.g. for where blocks,
3942-- paramaterised declarations, etc.
4043
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.
4147data ElabInfo = EInfo { params :: [(Name, PTerm)],
4248 inblock :: Ctxt [Name], -- names in the block, and their params
4349 liftname :: Name -> Name,
44− namespace :: Maybe [String] }
50+ namespace :: Maybe [String],
51+ rec_elabDecl :: ElabWhat -> ElabInfo -> PDecl ->
52+ Idris () }
4553
46−toplevel = EInfo [] emptyContext id Nothing
54+toplevel :: ElabInfo
55+toplevel = EInfo [] emptyContext id Nothing (\_ _ _ -> fail "Not implemented")
4756
4857eInfoNames :: ElabInfo -> [Name]
4958eInfoNames info = map fst (params info) ++ M.keys (inblock info)
@@ -118,7 +127,9 @@ ppOptionIst = ppOption . idris_options
118127data LanguageExt = TypeProviders | ErrorReflection deriving (Show, Eq, Read, Ord)
119128
120129-- | The output mode in use
121−data OutputMode = RawOutput | IdeSlave Integer deriving Show
130+data OutputMode = RawOutput Handle -- ^ Print user output directly to the handle
131+ | IdeSlave Integer Handle -- ^ Send IDE output for some request ID to the handle
132+ deriving Show
122133
123134-- | How wide is the console?
124135data ConsoleWidth = InfinitelyWide -- ^ Have pretty-printer assume that lines should not be broken
@@ -183,7 +194,6 @@ data IState = IState {
183194 idris_outputmode :: OutputMode,
184195 idris_colourRepl :: Bool,
185196 idris_colourTheme :: ColourTheme,
186− idris_outh :: Handle,
187197 idris_errorhandlers :: [Name], -- ^ Global error handlers
188198 idris_nameIdx :: (Int, Ctxt (Int, Name)),
189199 idris_function_errorhandlers :: Ctxt (M.Map Name (S.Set Name)), -- ^ Specific error handlers
@@ -268,8 +278,8 @@ idrisInit = IState initContext [] [] emptyContext emptyContext emptyContext
268278 emptyContext emptyContext emptyContext emptyContext
269279 emptyContext emptyContext
270280 [] [] [] defaultOpts 6 [] [] [] [] [] [] [] [] [] [] [] [] []
271− [] [] Nothing [] Nothing [] [] Nothing Nothing [] Hidden False [] Nothing [] [] RawOutput
272− True defaultTheme stdout [] (0, emptyContext) emptyContext M.empty
281+ [] [] Nothing [] Nothing [] [] Nothing Nothing [] Hidden False [] Nothing [] []
282+ (RawOutput stdout) True defaultTheme [] (0, emptyContext) emptyContext M.empty
273283 AutomaticWidth S.empty Nothing Nothing
274284
275285-- | The monad for the main REPL - reading and processing files and updating
@@ -349,6 +359,7 @@ data Opt = Filename String
349359 | NoBanner
350360 | ColourREPL Bool
351361 | Ideslave
362+ | IdeslaveSocket
352363 | ShowLibs
353364 | ShowLibdir
354365 | ShowIncs
@@ -467,6 +478,7 @@ data FnOpt = Inlinable -- always evaluate when simplifying
467478 | Dictionary -- type class dictionary, eval only when
468479 -- a function argument, and further evaluation resutls
469480 | Implicit -- implicit coercion
481+ | NoImplicit -- do not apply implicit coercions
470482 | CExport String -- export, with a C name
471483 | ErrorHandler -- ^^ an error handler for use with the ErrorReflection extension
472484 | ErrorReverse -- ^^ attempt to reverse normalise before showing in error
@@ -1625,6 +1637,7 @@ instance Sized PTerm where
16251637 size (PProof tactics) = size tactics
16261638 size (PElabError err) = size err
16271639 size PImpossible = 1
1640+ size _ = 0
16281641
16291642getPArity :: PTerm -> Int
16301643getPArity (PPi _ _ _ sc) = 1 + getPArity sc
@@ -1704,7 +1717,7 @@ implicitNamesIn uvars ist tm = nub $ ni [] tm
17041717 (nub (concatMap (ni env) (map snd os))
17051718 \\ nub (concatMap (ni env) (map fst os)))
17061719 ni env (PLam n ty sc) = ni env ty ++ ni (n:env) sc
1707− ni env (PPi p n ty sc) = niTacImp env p ++ ni env ty ++ ni (n:env) sc
1720+ ni env (PPi p n ty sc) = ni env ty ++ ni (n:env) sc
17081721 ni env (PEq _ _ _ l r) = ni env l ++ ni env r
17091722 ni env (PRewrite _ l r _) = ni env l ++ ni env r
17101723 ni env (PTyped l r) = ni env l ++ ni env r
@@ -1718,9 +1731,6 @@ implicitNamesIn uvars ist tm = nub $ ni [] tm
17181731 ni env (PNoImplicits tm) = ni env tm
17191732 ni env _ = []
17201733
1721− niTacImp env (TacImp _ _ scr) = ni env scr
1722− niTacImp _ _ = []
1723−
17241734-- Return names which are free in the given term.
17251735namesIn :: [(Name, PTerm)] -> IState -> PTerm -> [Name]
17261736namesIn uvars ist tm = nub $ ni [] tm
src/Idris/CaseSplit.hs+4−2
@@ -16,6 +16,8 @@ import Idris.Parser
1616import Idris.Error
1717import Idris.Output
1818
19+import Idris.Elab.Value
20+
1921import Idris.Core.TT
2022import Idris.Core.Typecheck
2123import Idris.Core.Evaluate
@@ -55,7 +57,7 @@ split n t'
5557 = do ist <- getIState
5658 -- Make sure all the names in the term are accessible
5759 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')
5961 -- ASSUMPTION: tm is in normal form after elabValBind, so we don't
6062 -- need to do anything special to find out what family each argument
6163 -- is in
@@ -201,7 +203,7 @@ tidy ist tm ty = return tm
201203-- tidyVar t = t
202204
203205elabNewPat :: 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
205207 i <- getIState
206208 return (Just (delab i tm)))
207209 (\e -> do i <- getIState
src/Idris/CmdOptions.hs+1
@@ -71,6 +71,7 @@ parseFlags = many $
7171 flag' NoBanner (long "nobanner" <> help "Suppress the banner")
7272 <|> flag' Quiet (short 'q' <> long "quiet" <> help "Quiet verbosity")
7373 <|> flag' Ideslave (long "ideslave")
74+ <|> flag' IdeslaveSocket (long "ideslave-socket")
7475 <|> (Client <$> strOption (long "client"))
7576 <|> (OLogging <$> option (long "log" <> metavar "LEVEL" <> help "Debugging log level"))
7677 <|> flag' NoBasePkgs (long "nobasepkgs")
src/Idris/Core/Elaborate.hs+14−16
@@ -12,6 +12,8 @@ module Idris.Core.Elaborate(module Idris.Core.Elaborate,
1212 module Idris.Core.ProofState) where
1313
1414import Idris.Core.ProofState
15+import Idris.Core.ProofTerm(bound_in, getProofTerm, mkProofTerm, bound_in_term,
16+ refocus)
1517import Idris.Core.TT
1618import Idris.Core.Evaluate
1719import Idris.Core.Typecheck
@@ -128,10 +130,6 @@ elaborate ctxt n ty d elab = do let ps = initElaborator n ctxt ty
128130 (a, ES ps' str _) <- runElab d elab ps
129131 return $! (a, str)
130132
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−
135133-- | Modify the auxiliary state
136134updateAux :: (aux -> aux) -> Elab' aux ()
137135updateAux f = do ES (ps, a) l p <- get
@@ -190,12 +188,12 @@ set_context ctxt = do ES (p, a) logs prev <- get
190188-- get the proof term
191189get_term :: Elab' aux Term
192190get_term = do ES p _ _ <- get
193− return $! (pterm (fst p))
191+ return $! (getProofTerm (pterm (fst p)))
194192
195193-- get the proof term
196194update_term :: (Term -> Term) -> Elab' aux ()
197195update_term f = do ES (p,a) logs prev <- get
198− let p' = p { pterm = f (pterm p) }
196+ let p' = p { pterm = mkProofTerm (f (getProofTerm (pterm p))) }
199197 put (ES (p', a) logs prev)
200198
201199-- get the local context at the currently in focus hole
@@ -271,7 +269,7 @@ unique_hole' :: Bool -> Name -> Elab' aux Name
271269unique_hole' reusable n
272270 = do ES p _ _ <- get
273271 let bs = bound_in (pterm (fst p)) ++
274− bound_in (ptype (fst p))
272+ bound_in_term (ptype (fst p))
275273 let nouse = holes (fst p) ++ bs ++ dontunify (fst p) ++ usedns (fst p)
276274 n' <- return $! uniqueNameCtxt (context (fst p)) n nouse
277275 ES (p, a) s u <- get
@@ -280,14 +278,6 @@ unique_hole' reusable n
280278 put (ES (p { nextname = i + 1 }, a) s u)
281279 _ -> return $! ()
282280 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 _ = []
291281
292282elog :: String -> Elab' aux ()
293283elog str = do ES p logs prev <- get
@@ -401,6 +391,13 @@ focus n = processTactic' (Focus n)
401391movelast :: Name -> Elab' aux ()
402392movelast n = processTactic' (MoveLast n)
403393
394+-- | Set the zipper in the proof state to point at the current sub term
395+-- (This currently happens automatically, so this will have no effect...)
396+zipHere :: Elab' aux ()
397+zipHere = do ES (ps, a) s m <- get
398+ let pt' = refocus (Just (head (holes ps))) (pterm ps)
399+ put (ES (ps { pterm = pt' }, a) s m)
400+
404401matchProblems :: Bool -> Elab' aux ()
405402matchProblems all = processTactic' (MatchProblems all)
406403
@@ -429,7 +426,7 @@ reorder_claims n = processTactic' (Reorder n)
429426qed :: Elab' aux Term
430427qed = do processTactic' QED
431428 ES p _ _ <- get
432− return $! (pterm (fst p))
429+ return $! (getProofTerm (pterm (fst p)))
433430
434431undo :: Elab' aux ()
435432undo = processTactic' Undo
@@ -639,6 +636,7 @@ simple_app fun arg appstr =
639636arg :: Name -> Name -> Elab' aux ()
640637arg n tyhole = do ty <- unique_hole tyhole
641638 claim ty RType
639+ movelast ty
642640 forall n (Var ty)
643641
644642-- try a tactic, if it adds any unification problem, return an error
src/Idris/Core/ProofState.hs+30−105
@@ -12,6 +12,7 @@ import Idris.Core.Typecheck
1212import Idris.Core.Evaluate
1313import Idris.Core.TT
1414import Idris.Core.Unify
15+import Idris.Core.ProofTerm
1516
1617import Control.Monad.State.Strict
1718import Control.Applicative hiding (empty)
@@ -25,7 +26,7 @@ data ProofState = PS { thname :: Name,
2526 holes :: [Name], -- holes still to be solved
2627 usedns :: [Name], -- used names, don't use again
2728 nextname :: Int, -- name supply
28− pterm :: Term, -- current proof term
29+ pterm :: ProofTerm, -- current proof term
2930 ptype :: Type, -- original goal
3031 dontunify :: [Name], -- explicitly given by programmer, leave it
3132 unified :: (Name, [(Name, Term)]),
@@ -43,10 +44,6 @@ data ProofState = PS { thname :: Name,
4344 while_elaborating :: [FailContext]
4445 }
4546
46−data Goal = GD { premises :: Env,
47− goalType :: Binder Term
48− }
49−
5047data Tactic = Attack
5148 | Claim Name Raw
5249 | Reorder Name
@@ -141,13 +138,6 @@ instance Pretty ProofState OutputAnnotation where
141138 nest nestingSize (pretty n <+> colon <+> prettyEnv env (binderTy b) <+>
142139 nest nestingSize (prettyPs env bs))
143140
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−
151141holeName i = sMN i "hole"
152142
153143qshow :: Fails -> String
@@ -165,7 +155,7 @@ match_unify' ctxt env topx topy =
165155 " in " ++ show env ++
166156 "\nHoles: " ++ show (holes ps)
167157 ++ "\n"
168− ++ "\n" ++ show (pterm ps) ++ "\n\n"
158+ ++ "\n" ++ show (getProofTerm (pterm ps)) ++ "\n\n"
169159 ) $
170160 case match_unify ctxt env topx topy inj (holes ps) while of
171161 OK u -> traceWhen (unifylog ps)
@@ -226,9 +216,11 @@ unify' ctxt env topx topy =
226216-- ++ show (pterm ps)
227217 ++ "\n----------") $
228218 do let (h, ns) = unified ps
219+ -- solve in results (maybe unify should do this itself...)
220+ let u' = map (\(n, sol) -> (n, updateSolvedTerm u sol)) u
229221 -- if a metavar has multiple solutions, make a new unification
230222 -- problem for each.
231− uns <- mergeSolutions env (u ++ ns)
223+ uns <- mergeSolutions env (u' ++ ns)
232224 ps <- get
233225 let (ns', probs') = updateProblems (context ps) uns
234226 (fails ++ problems ps)
@@ -290,15 +282,14 @@ addLog str = action (\ps -> ps { plog = plog ps ++ str ++ "\n" })
290282newProof :: Name -> Context -> Type -> ProofState
291283newProof n ctxt ty = let h = holeName 0
292284 ty' = vToP ty in
293− PS n [h] [] 1 (Bind h (Hole ty')
294− (P Bound h ty')) ty [] (h, []) []
285+ PS n [h] [] 1 (mkProofTerm (Bind h (Hole ty')
286+ (P Bound h ty'))) ty [] (h, []) []
295287 Nothing [] []
296288 [] []
297289 Nothing ctxt "" False False []
298290
299291type TState = ProofState -- [TacticAction])
300−type RunTactic = Context -> Env -> Term -> StateT TState TC Term
301−type Hole = Maybe Name -- Nothing = default hole, first in list in proof state
292+type RunTactic = RunTactic' TState
302293
303294envAtFocus :: ProofState -> TC Env
304295envAtFocus ps
@@ -310,64 +301,13 @@ goalAtFocus :: ProofState -> TC (Binder Type)
310301goalAtFocus ps
311302 | not $ null (holes ps) = do g <- goal (Just (head (holes ps))) (pterm ps)
312303 return (goalType g)
313− | otherwise = Error . Msg $ "No goal in " ++ show (holes ps) ++ show (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)
304+ | otherwise = Error . Msg $ "No goal in " ++ show (holes ps) ++ show (getProofTerm (pterm ps))
330305
331306tactic :: Hole -> RunTactic -> StateT TState TC ()
332307tactic h f = do ps <- get
333− (tm', _) <- atH (context ps) [] (pterm ps)
308+ (tm', _) <- atHole h f (context ps) [] (pterm ps)
334309 ps <- get -- might have changed while processing
335310 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)
371311
372312computeLet :: Context -> Name -> Term -> Term
373313computeLet ctxt n tm = cl [] tm where
@@ -612,7 +552,7 @@ forall n ty ctxt env (Bind x (Hole t) (P _ x' _)) | x == x' =
612552forall n ty ctxt env _ = fail "Can't pi bind here"
613553
614554patvar :: Name -> RunTactic
615−patvar n ctxt env (Bind x (Hole t) sc) =
555+patvar n ctxt env (Bind x (Hole t) sc) =
616556 do action (\ps -> ps { holes = traceWhen (unifylog ps) ("Dropping pattern hole " ++ show x) $
617557 holes ps \\ [x],
618558 solved = Just (x, P Bound n t),
@@ -697,13 +637,13 @@ casetac tm induction ctxt env (Bind x (Hole t) (P _ x' _)) | x == x' = do
697637 let indxargs = drop (length restargs - length indicies) $ restargs
698638 let scr = last $ tail args'
699639 let indxnames = makeIndexNames indicies
700− currentNames <- query $ allTTNames . pterm
640+ currentNames <- query $ allTTNames . getProofTerm . pterm
701641 let tmnm = case tm of
702642 Var nm -> uniqueNameCtxt ctxt nm currentNames
703643 _ -> uniqueNameCtxt ctxt (sMN 0 "iv") currentNames
704644 let tmvar = P Bound tmnm tmt'
705645 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)
646+ consargs' <- query (\ps -> map (flip (uniqueNameCtxt (context ps)) (holes ps ++ allTTNames (getProofTerm (pterm ps))) *** uniqueBindersCtxt (context ps) (holes ps ++ allTTNames (getProofTerm (pterm ps)))) consargs)
707647 let res = flip (foldr substV) params $ (substV prop $ bindConsArgs consargs' (mkApp (P Ref (SN (tacn tnm)) (TType (UVal 0)))
708648 (params ++ [prop] ++ map makeConsArg consargs' ++ indicies ++ [tmv])))
709649 action (\ps -> ps {holes = holes ps \\ [x]})
@@ -800,7 +740,7 @@ solve_unified ctxt env tm =
800740 action (\ps -> ps { holes = traceWhen (unifylog ps) ("Dropping holes " ++ show (map fst unify)) $
801741 holes ps \\ map fst unify })
802742 action (\ps -> ps { pterm = updateSolved unify (pterm ps) })
803− return (updateSolved unify tm)
743+ return (updateSolvedTerm unify tm)
804744
805745dropGiven du [] hs = []
806746dropGiven du ((n, P Bound t ty) : us) hs
@@ -821,26 +761,9 @@ keepGiven du (u@(n, _) : us) hs
821761 | n `elem` du = u : keepGiven du us hs
822762keepGiven du (u : us) hs = keepGiven du us hs
823763
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−
841764updateEnv [] e = e
842765updateEnv ns [] = []
843−updateEnv ns ((n, b) : env) = (n, fmap (updateSolved ns) b) : updateEnv ns env
766+updateEnv ns ((n, b) : env) = (n, fmap (updateSolvedTerm ns) b) : updateEnv ns env
844767
845768updateError [] err = err
846769updateError ns (At f e) = At f (updateError ns e)
@@ -848,7 +771,7 @@ updateError ns (Elaborating s n e) = Elaborating s n (updateError ns e)
848771updateError ns (ElaboratingArg f a env e)
849772 = ElaboratingArg f a env (updateError ns e)
850773updateError ns (CantUnify b l r e xs sc)
851− = CantUnify b (updateSolved ns l) (updateSolved ns r) (updateError ns e) xs sc
774+ = CantUnify b (updateSolvedTerm ns l) (updateSolvedTerm ns r) (updateError ns e) xs sc
852775updateError ns e = e
853776
854777solveInProblems x val [] = []
@@ -868,7 +791,7 @@ mergeNotunified env ns = mnu ns [] [] where
868791updateNotunified [] nu = nu
869792updateNotunified ns nu = up nu where
870793 up [] = []
871− up ((n, t) : nus) = let t' = updateSolved ns t in
794+ up ((n, t) : nus) = let t' = updateSolvedTerm ns t in
872795 ((n, t') : up nus)
873796
874797-- FIXME: Why not just pass the whole proof state?
@@ -878,8 +801,8 @@ updateProblems :: Context -> [(Name, TT Name)] -> Fails -> [Name] -> [Name] -> [
878801updateProblems ctxt ns ps inj holes usupp = up ns ps where
879802 up ns [] = (ns, [])
880803 up ns ((x, y, env, err, while, um) : ps) =
881− let x' = updateSolved ns x
882− y' = updateSolved ns y
804+ let x' = updateSolvedTerm ns x
805+ y' = updateSolvedTerm ns y
883806 err' = updateError ns err
884807 env' = updateEnv ns env in
885808-- trace ("Updating " ++ show (x',y')) $
@@ -895,8 +818,8 @@ matchProblems all ns ctxt ps inj holes = up ns ps where
895818 up ns [] = (ns, [])
896819 up ns ((x, y, env, err, while, um) : ps)
897820 | all || um == Match =
898− let x' = updateSolved ns x
899− y' = updateSolved ns y
821+ let x' = updateSolvedTerm ns x
822+ y' = updateSolvedTerm ns y
900823 err' = updateError ns err
901824 env' = updateEnv ns env in
902825 case match_unify ctxt env' x' y' inj holes while of
@@ -909,19 +832,19 @@ matchProblems all ns ctxt ps inj holes = up ns ps where
909832
910833processTactic :: Tactic -> ProofState -> TC (ProofState, String)
911834processTactic QED ps = case holes ps of
912− [] -> do let tm = {- normalise (context ps) [] -} (pterm ps)
835+ [] -> do let tm = {- normalise (context ps) [] -} getProofTerm (pterm ps)
913836 (tm', ty', _) <- recheck (context ps) [] (forget tm) tm
914− return (ps { done = True, pterm = tm' },
837+ return (ps { done = True, pterm = mkProofTerm tm' },
915838 "Proof complete: " ++ showEnv [] tm')
916839 _ -> fail "Still holes to fill."
917−processTactic ProofState ps = return (ps, showEnv [] (pterm ps))
840+processTactic ProofState ps = return (ps, showEnv [] (getProofTerm (pterm ps)))
918841processTactic Undo ps = case previous ps of
919842 Nothing -> Error . Msg $ "Nothing to undo."
920843 Just pold -> return (pold, "")
921844processTactic EndUnify ps
922845 = let (h, ns_in) = unified ps
923846 ns = dropGiven (dontunify ps) ns_in (holes ps)
924− ns' = map (\ (n, t) -> (n, updateSolved ns t)) ns
847+ ns' = map (\ (n, t) -> (n, updateSolvedTerm ns t)) ns
925848 (ns'', probs') = updateProblems (context ps) ns' (problems ps)
926849 (injective ps) (holes ps)
927850 (map fst (notunified ps))
@@ -941,7 +864,9 @@ processTactic (Reorder n) ps
941864 = do ps' <- execStateT (tactic (Just n) reorder_claims) ps
942865 return (ps' { previous = Just ps, plog = "" }, plog ps')
943866processTactic (ComputeLet n) ps
944− = return (ps { pterm = computeLet (context ps) n (pterm ps) }, "")
867+ = return (ps { pterm = mkProofTerm $
868+ computeLet (context ps) n
869+ (getProofTerm (pterm ps)) }, "")
945870processTactic UnifyProblems ps
946871 = let (ns', probs') = updateProblems (context ps) []
947872 (problems ps)
@@ -977,7 +902,7 @@ processTactic t ps
977902 = case solved ps' of
978903 Just s -> traceWhen (unifylog ps')
979904 ("SOLVED " ++ show s) $
980− updateProblems (context ps')
905+ updateProblems (context ps')
981906 [s] (problems ps')
982907 (injective ps')
983908 (holes ps')
src/Idris/Core/ProofTerm.hsnew file+266
@@ -0,0 +1,266 @@
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, refocus,
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+data TermPath = Top
22+ | AppL TermPath Term
23+ | AppR Term TermPath
24+ | InBind Name BinderPath Term
25+ | InScope Name (Binder Term) TermPath
26+ deriving Show
27+
28+data BinderPath = Binder (Binder TermPath)
29+ | LetT TermPath Term
30+ | LetV Term TermPath
31+ | GuessT TermPath Term
32+ | GuessV Term TermPath
33+ deriving Show
34+
35+replaceTop :: TermPath -> TermPath -> TermPath
36+replaceTop p Top = p
37+replaceTop p (AppL l t) = AppL (replaceTop p l) t
38+replaceTop p (AppR t r) = AppR t (replaceTop p r)
39+replaceTop p (InBind n bp sc) = InBind n (replaceTopB p bp) sc
40+ where
41+ replaceTopB p (Binder b) = Binder (fmap (replaceTop p) b)
42+ replaceTopB p (LetT t v) = LetT (replaceTop p t) v
43+ replaceTopB p (LetV t v) = LetV t (replaceTop p v)
44+ replaceTopB p (GuessT t v) = GuessT (replaceTop p t) v
45+ replaceTopB p (GuessV t v) = GuessV t (replaceTop p v)
46+replaceTop p (InScope n b sc) = InScope n b (replaceTop p sc)
47+
48+rebuildTerm :: Term -> TermPath -> Term
49+rebuildTerm tm Top = tm
50+rebuildTerm tm (AppL p a) = App (rebuildTerm tm p) a
51+rebuildTerm tm (AppR f p) = App f (rebuildTerm tm p)
52+rebuildTerm tm (InScope n b p) = Bind n b (rebuildTerm tm p)
53+rebuildTerm tm (InBind n bp sc) = Bind n (rebuildBinder tm bp) sc
54+
55+rebuildBinder :: Term -> BinderPath -> Binder Term
56+rebuildBinder tm (Binder p) = fmap (rebuildTerm tm) p
57+rebuildBinder tm (LetT p t) = Let (rebuildTerm tm p) t
58+rebuildBinder tm (LetV v p) = Let v (rebuildTerm tm p)
59+rebuildBinder tm (GuessT p t) = Guess (rebuildTerm tm p) t
60+rebuildBinder tm (GuessV v p) = Guess v (rebuildTerm tm p)
61+
62+findHole :: Name -> Env -> Term -> Maybe (TermPath, Env, Term)
63+findHole n env t = fh' env Top t where
64+ fh' env path tm@(Bind x h sc)
65+ | hole h && n == x = Just (path, env, tm)
66+ fh' env path (App f a)
67+ | Just (p, env', tm) <- fh' env path a = Just (AppR f p, env', tm)
68+ | Just (p, env', tm) <- fh' env path f = Just (AppL p a, env', tm)
69+ fh' env path (Bind x b sc)
70+ | Just (bp, env', tm) <- fhB env path b = Just (InBind x bp sc, env', tm)
71+ | Just (p, env', tm) <- fh' ((x,b):env) path sc = Just (InScope x b p, env', tm)
72+ fh' _ _ _ = Nothing
73+
74+ fhB env path (Let t v)
75+ | Just (p, env', tm) <- fh' env path t = Just (LetT p v, env', tm)
76+ | Just (p, env', tm) <- fh' env path v = Just (LetV t p, env', tm)
77+ fhB env path (Guess t v)
78+ | Just (p, env', tm) <- fh' env path t = Just (GuessT p v, env', tm)
79+ | Just (p, env', tm) <- fh' env path v = Just (GuessV t p, env', tm)
80+ fhB env path b
81+ | Just (p, env', tm) <- fh' env path (binderTy b)
82+ = Just (Binder (fmap (\_ -> p) b), env', tm)
83+ fhB _ _ _ = Nothing
84+
85+data ProofTerm = PT { -- wholeterm :: Term,
86+ path :: TermPath,
87+ subterm_env :: Env,
88+ subterm :: Term,
89+ updates :: [(Name, Term)] }
90+ deriving Show
91+
92+type RunTactic' a = Context -> Env -> Term -> StateT a TC Term
93+type Hole = Maybe Name -- Nothing = default hole, first in list in proof state
94+
95+refocus :: Hole -> ProofTerm -> ProofTerm
96+refocus h t = let res = refocus' h t in res
97+-- trace ("OLD: " ++ show t ++ "\n" ++
98+-- "REFOCUSSED " ++ show h ++ ": " ++ show res) res
99+refocus' (Just n) pt@(PT path env tm ups)
100+ | Just (p', env', tm') <- findHole n env tm
101+ = PT (replaceTop p' path) env' tm' ups
102+ | Just (p', env', tm') <- findHole n [] (rebuildTerm tm (updateSolvedPath ups path))
103+ = PT p' env' tm' []
104+ | otherwise = pt
105+refocus' _ pt = pt
106+
107+data Goal = GD { premises :: Env,
108+ goalType :: Binder Term
109+ }
110+
111+mkProofTerm :: Term -> ProofTerm
112+mkProofTerm tm = PT Top [] tm []
113+
114+getProofTerm :: ProofTerm -> Term
115+getProofTerm (PT path _ sub ups) = rebuildTerm sub (updateSolvedPath ups path)
116+
117+same Nothing n = True
118+same (Just x) n = x == n
119+
120+hole (Hole _) = True
121+hole (Guess _ _) = True
122+hole _ = False
123+
124+updateSolvedTerm :: [(Name, Term)] -> Term -> Term
125+updateSolvedTerm [] x = x
126+updateSolvedTerm xs x = -- updateSolved' xs x where
127+-- This version below saves allocations, because it doesn't need to reallocate
128+-- the term if there are no updates to do, but costs an extra pass. Below
129+-- version works better on larger terms...
130+ if noneOf (map fst xs) x
131+ then x
132+ else updateSolved' xs x where
133+ updateSolved' [] x = x
134+ updateSolved' xs (Bind n (Hole ty) t)
135+ | Just v <- lookup n xs
136+ = case xs of
137+ [_] -> substV v $ psubst n v t -- some may be Vs! Can't assume
138+ -- explicit names
139+ _ -> substV v $ psubst n v (updateSolved' xs t)
140+ updateSolved' xs (Bind n b t)
141+ | otherwise = Bind n (fmap (updateSolved' xs) b) (updateSolved' xs t)
142+ updateSolved' xs (App f a)
143+ = App (updateSolved' xs f) (updateSolved' xs a)
144+ updateSolved' xs (P _ n@(MN _ _) _)
145+ | Just v <- lookup n xs = v
146+ updateSolved' xs t = t
147+
148+ noneOf ns (P _ n _) | n `elem` ns = False
149+ noneOf ns (App f a) = noneOf ns a && noneOf ns f
150+ noneOf ns (Bind n (Hole ty) t) = n `notElem` ns && noneOf ns ty && noneOf ns t
151+ noneOf ns (Bind n b t) = noneOf ns t && noneOfB ns b
152+ where
153+ noneOfB ns (Let t v) = noneOf ns t && noneOf ns v
154+ noneOfB ns (Guess t v) = noneOf ns t && noneOf ns v
155+ noneOfB ns b = noneOf ns (binderTy b)
156+ noneOf ns _ = True
157+
158+updateEnv [] e = e
159+updateEnv ns [] = []
160+updateEnv ns ((n, b) : env) = (n, fmap (updateSolvedTerm ns) b) : updateEnv ns env
161+
162+updateSolvedPath [] t = t
163+updateSolvedPath ns Top = Top
164+updateSolvedPath ns (AppL p r) = AppL p (updateSolvedTerm ns r)
165+updateSolvedPath ns (AppR l p) = AppR (updateSolvedTerm ns l) p
166+updateSolvedPath ns (InBind n b sc)
167+ = InBind n (updateSolvedPathB b) (updateSolvedTerm ns sc)
168+ where
169+ updateSolvedPathB (Binder b) = Binder (fmap (updateSolvedPath ns) b)
170+ updateSolvedPathB (LetT p v) = LetT (updateSolvedPath ns p) (updateSolvedTerm ns v)
171+ updateSolvedPathB (LetV v p) = LetV (updateSolvedTerm ns v) (updateSolvedPath ns p)
172+ updateSolvedPathB (GuessT p v) = GuessT (updateSolvedPath ns p) (updateSolvedTerm ns v)
173+ updateSolvedPathB (GuessV v p) = GuessV (updateSolvedTerm ns v) (updateSolvedPath ns p)
174+updateSolvedPath ns (InScope n (Hole ty) t)
175+ | Just v <- lookup n ns = case ns of
176+ [_] -> updateSolvedPath [(n,v)] t
177+ _ -> updateSolvedPath ns $
178+ updateSolvedPath [(n,v)] t
179+updateSolvedPath ns (InScope n b sc)
180+ = InScope n (fmap (updateSolvedTerm ns) b) (updateSolvedPath ns sc)
181+
182+updateSolved :: [(Name, Term)] -> ProofTerm -> ProofTerm
183+updateSolved xs pt@(PT path env sub ups)
184+ = PT path -- (updateSolvedPath xs path)
185+ (updateEnv xs (filter (\(n, t) -> n `notElem` map fst xs) env))
186+ (updateSolvedTerm xs sub)
187+ (ups ++ xs)
188+
189+goal :: Hole -> ProofTerm -> TC Goal
190+goal h pt@(PT path env sub ups)
191+-- | OK ginf <- g env sub = return ginf
192+ | otherwise = g [] (rebuildTerm sub (updateSolvedPath ups path))
193+ where
194+ g :: Env -> Term -> TC Goal
195+ g env (Bind n b@(Guess _ _) sc)
196+ | same h n = return $ GD env b
197+ | otherwise
198+ = gb env b `mplus` g ((n, b):env) sc
199+ g env (Bind n b sc) | hole b && same h n = return $ GD env b
200+ | otherwise
201+ = g ((n, b):env) sc `mplus` gb env b
202+ g env (App f a) = g env a `mplus` g env f
203+ g env t = fail "Can't find hole"
204+
205+ gb env (Let t v) = g env v `mplus` g env t
206+ gb env (Guess t v) = g env v `mplus` g env t
207+ gb env t = g env (binderTy t)
208+
209+atHole :: Hole -> RunTactic' a -> Context -> Env -> ProofTerm ->
210+ StateT a TC (ProofTerm, Bool)
211+atHole h f c e pt -- @(PT path env sub)
212+ = do let PT path env sub ups = refocus h pt
213+ (tm, u) <- atH f c env sub
214+ return (PT path env tm ups, u)
215+-- if u then return (PT path env tm ups, u)
216+-- else do let PT path env sub ups = refocus h pt
217+-- (tm, u) <- atH f c env sub
218+-- return (PT path env tm ups, u)
219+ where
220+ updated o = do o' <- o
221+ return (o', True)
222+
223+ ulift2 f c env op a b
224+ = do (b', u) <- atH f c env b
225+ if u then return (op a b', True)
226+ else do (a', u) <- atH f c env a
227+ return (op a' b', u)
228+
229+ -- Search the things most likely to contain the binding first!
230+
231+ atH :: RunTactic' a -> Context -> Env -> Term -> StateT a TC (Term, Bool)
232+ atH f c env binder@(Bind n b@(Guess t v) sc)
233+ | same h n = updated (f c env binder)
234+ | otherwise
235+ = do -- binder first
236+ (b', u) <- ulift2 f c env Guess t v
237+ if u then return (Bind n b' sc, True)
238+ else do (sc', u) <- atH f c ((n, b) : env) sc
239+ return (Bind n b' sc', u)
240+ atH f c env binder@(Bind n b sc)
241+ | hole b && same h n = updated (f c env binder)
242+ | otherwise -- scope first
243+ = do (sc', u) <- atH f c ((n, b) : env) sc
244+ if u then return (Bind n b sc', True)
245+ else do (b', u) <- atHb f c env b
246+ return (Bind n b' sc', u)
247+ atH tac c env (App f a) = ulift2 tac c env App f a
248+ atH tac c env t = return (t, False)
249+
250+ atHb f c env (Let t v) = ulift2 f c env Let t v
251+ atHb f c env (Guess t v) = ulift2 f c env Guess t v
252+ atHb f c env t = do (ty', u) <- atH f c env (binderTy t)
253+ return (t { binderTy = ty' }, u)
254+
255+bound_in :: ProofTerm -> [Name]
256+bound_in (PT path _ tm ups) = bound_in_term (rebuildTerm tm (updateSolvedPath ups path))
257+
258+bound_in_term :: Term -> [Name]
259+bound_in_term (Bind n b sc) = n : bi b ++ bound_in_term sc
260+ where
261+ bi (Let t v) = bound_in_term t ++ bound_in_term v
262+ bi (Guess t v) = bound_in_term t ++ bound_in_term v
263+ bi b = bound_in_term (binderTy b)
264+bound_in_term (App f a) = bound_in_term f ++ bound_in_term a
265+bound_in_term _ = []
266+
src/Idris/Core/Unify.hs+9
@@ -333,6 +333,15 @@ unify ctxt env topx topy inj holes usersupp from =
333333 = unifyTmpFail tx ty
334334 | injective ty && not (holeIn env x || x `elem` holes)
335335 = unifyTmpFail tx ty
336+ -- pick the one bound earliest if both are holes
337+ | tx /= ty && (holeIn env x || x `elem` holes)
338+ && (holeIn env y || y `elem` holes)
339+ = case compare (envPos 0 x env) (envPos 0 y env) of
340+ LT -> do sc 1; checkCycle bnames (x, ty)
341+ _ -> do sc 1; checkCycle bnames (y, tx)
342+ where envPos i n ((n',_):env) | n == n' = i
343+ envPos i n (_:env) = envPos (i+1) n env
344+ envPos _ _ _ = 100000
336345 un' fn bnames xtm@(P _ x _) tm
337346 | pureTerm tm, holeIn env x || x `elem` holes
338347 = do UI s f <- get
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
2020import Idris.Output (iputStrLn, pshow, iWarn)
2121import IRTS.Lang
2222
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+
2333import Idris.Core.TT
2434import Idris.Core.Elaborate hiding (Tactic(..))
2535import Idris.Core.Evaluate
@@ -48,638 +58,14 @@ import Data.List.Split (splitOn)
4858
4959import Util.Pretty(pretty, text)
5060
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 ["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"
54161
542− scrutineeArgName :: Name
543− scrutineeArgName = sUN "scrutineeArg"
544−
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
62+-- Top level elaborator info, supporting recursive elaboration
63+recinfo :: ElabInfo
64+recinfo = EInfo [] emptyContext id Nothing elabDecl'
67865
67966-- | Elaborate primitives
680−
68167elabPrims :: Idris ()
682−elabPrims = do mapM_ (elabDecl EAll toplevel)
68+elabPrims = do mapM_ (elabDecl' EAll recinfo)
68369 (map (\(opt, decl, docs, argdocs) -> PData docs argdocs defaultSyntax (fileFC "builtin") opt decl)
68470 (zip4
68571 [inferOpts, unitOpts, falseOpts, pairOpts, eqOpts]
@@ -687,7 +73,7 @@ elabPrims = do mapM_ (elabDecl EAll toplevel)
68773 [emptyDocstring, unitDoc, falseDoc, pairDoc, eqDoc]
68874 [[], [], [], pairParamDoc, eqParamDoc]))
68975 addNameHint eqTy (sUN "prf")
690− elabDecl EAll toplevel elimDecl
76+ elabDecl' EAll recinfo elimDecl
69177 mapM_ elabPrim primitives
69278 -- Special case prim__believe_me because it doesn't work on just constants
69379 elabBelieveMe
@@ -748,71 +134,6 @@ elabPrims = do mapM_ (elabDecl EAll toplevel)
748134 idris_scprims = (synEq, (4, LNoOp)) : idris_scprims i
749135 }
750136
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−
816137elabTransform :: ElabInfo -> FC -> Bool -> PTerm -> PTerm -> Idris ()
817138elabTransform info fc safe lhs_in rhs_in
818139 = do ctxt <- getContext
@@ -845,1518 +166,13 @@ elabTransform info fc safe lhs_in rhs_in
845166 addTrans (clhs_tm, crhs_tm)
846167 addIBC (IBCTrans (clhs_tm, crhs_tm))
847168
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−
2353169elabDecls :: ElabInfo -> [PDecl] -> Idris ()
2354170elabDecls info ds = do mapM_ (elabDecl EAll info) ds
2355−-- mapM_ (elabDecl EDefns info) ds
2356171
2357172elabDecl :: ElabWhat -> ElabInfo -> PDecl -> Idris ()
2358173elabDecl what info d
2359− = idrisCatch (withErrorReflection $ elabDecl' what info d) (setAndReport)
174+ = let info' = info { rec_elabDecl = elabDecl' } in
175+ idrisCatch (withErrorReflection $ elabDecl' what info' d) (setAndReport)
2360176
2361177elabDecl' _ info (PFix _ _ _)
2362178 = return () -- nothing to elaborate
@@ -2464,54 +280,3 @@ elabDecl' what info (PTransform fc safety old new)
2464280 = elabTransform info fc safety old new
2465281elabDecl' _ _ _ = return () -- skipped this time
2466282
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+79−24
@@ -17,6 +17,7 @@ import Idris.Core.Unify
1717import Idris.Core.Typecheck (check, recheck)
1818import Idris.ErrReverse (errReverse)
1919import Idris.ElabQuasiquote (extractUnquotes)
20+import qualified Util.Pretty as U
2021
2122import Control.Applicative ((<$>))
2223import Control.Monad
@@ -26,6 +27,8 @@ import qualified Data.Map as M
2627import Data.Maybe (mapMaybe, fromMaybe)
2728import qualified Data.Set as S
2829import qualified Data.Text as T
30+import Data.Vector.Unboxed (Vector)
31+import qualified Data.Vector.Unboxed as V
2932
3033import Debug.Trace
3134
@@ -142,6 +145,7 @@ elab ist info emode opts fn tm
142145 compute -- expand type synonyms, etc
143146 elabE (False, False, False, False) tm -- (in argument, guarded, in type, in qquote)
144147 end_unify
148+ ptm <- get_term
145149 when pattern -- convert remaining holes to pattern vars
146150 (do update_term orderPats
147151 unify_all
@@ -688,7 +692,6 @@ elab ist info emode opts fn tm
688692 (caseBlock fc cname'
689693 (map (isScr scr) (reverse args)) opts)
690694 -- elaborate case
691− env <- get_env
692695 updateAux (newdef : )
693696 -- if we haven't got the type yet, hopefully we'll get it later!
694697 movelast tyn
@@ -853,9 +856,23 @@ elab ist info emode opts fn tm
853856 addImplBound ist (map fst env) (PApp fc (PRef fc (sUN "Delay"))
854857 [pexp t])
855858
859+
860+ -- Don't put implicit coercions around applications which are marked
861+ -- as '%noImplicit', or around case blocks, otherwise we get exponential
862+ -- blowup especially where there are errors deep in large expressions.
863+ notImplicitable (PApp _ f _) = notImplicitable f
864+ -- TMP HACK no coercing on bind (make this configurable)
865+ notImplicitable (PRef _ n)
866+ | [opts] <- lookupCtxt n (idris_flags ist)
867+ = NoImplicit `elem` opts
868+ notImplicitable (PAlternative True as) = any notImplicitable as
856869 -- case is tricky enough without implicit coercions! If they are needed,
857870 -- they can go in the branches separately.
871+ notImplicitable (PCase _ _ _) = True
872+ notImplicitable _ = False
873+
858874 insertCoerce ina t@(PCase _ _ _) = return t
875+ insertCoerce ina t | notImplicitable t = return t
859876 insertCoerce ina t =
860877 do ty <- goal
861878 -- Check for possible coercions to get to the goal
@@ -889,7 +906,7 @@ elab ist info emode opts fn tm
889906 elabArgs ist ina failed fc r f (n:ns) force (Placeholder : args)
890907 = elabArgs ist ina failed fc r f ns force args
891908 elabArgs ist ina failed fc r f ((argName, holeName):ns) force (t : args)
892− = do elabArg argName holeName t
909+ = elabArg argName holeName t
893910 where elabArg argName holeName t =
894911 do now_elaborating fc f argName
895912 wrapErr f argName $ do
@@ -1559,15 +1576,7 @@ reifyTTBinderApp reif f [t]
15591576reifyTTBinderApp _ f args = fail ("Unknown reflection binder: " ++ show (f, args))
15601577
15611578reifyTTConst :: Term -> ElabD Const
1562−reifyTTConst (P _ n _) | n == reflm "IType" = return (AType (ATInt ITNative))
1563−reifyTTConst (P _ n _) | n == reflm "BIType" = return (AType (ATInt ITBig))
1564−reifyTTConst (P _ n _) | n == reflm "FlType" = return (AType ATFloat)
1565−reifyTTConst (P _ n _) | n == reflm "ChType" = return (AType (ATInt ITChar))
15661579reifyTTConst (P _ n _) | n == reflm "StrType" = return $ StrType
1567−reifyTTConst (P _ n _) | n == reflm "B8Type" = return (AType (ATInt (ITFixed IT8)))
1568−reifyTTConst (P _ n _) | n == reflm "B16Type" = return (AType (ATInt (ITFixed IT16)))
1569−reifyTTConst (P _ n _) | n == reflm "B32Type" = return (AType (ATInt (ITFixed IT32)))
1570−reifyTTConst (P _ n _) | n == reflm "B64Type" = return (AType (ATInt (ITFixed IT64)))
15711580reifyTTConst (P _ n _) | n == reflm "PtrType" = return $ PtrType
15721581reifyTTConst (P _ n _) | n == reflm "VoidType" = return $ VoidType
15731582reifyTTConst (P _ n _) | n == reflm "Forgot" = return $ Forgot
@@ -1576,6 +1585,8 @@ reifyTTConst t@(App _ _)
15761585reifyTTConst t = fail ("Unknown reflection constant: " ++ show t)
15771586
15781587reifyTTConstApp :: Name -> Term -> ElabD Const
1588+reifyTTConstApp f aty
1589+ | f == reflm "AType" = fmap AType (reifyArithTy aty)
15791590reifyTTConstApp f (Constant c@(I _))
15801591 | f == reflm "I" = return $ c
15811592reifyTTConstApp f (Constant c@(BI _))
@@ -1596,6 +1607,26 @@ reifyTTConstApp f (Constant c@(B64 _))
15961607 | f == reflm "B64" = return $ c
15971608reifyTTConstApp f arg = fail ("Unknown reflection constant: " ++ show (f, arg))
15981609
1610+reifyArithTy :: Term -> ElabD ArithTy
1611+reifyArithTy (App (P _ n _) intTy) | n == reflm "ATInt" = fmap ATInt (reifyIntTy intTy)
1612+reifyArithTy (P _ n _) | n == reflm "ATFloat" = return ATFloat
1613+reifyArithTy x = fail ("Couldn't reify reflected ArithTy: " ++ show x)
1614+
1615+reifyNativeTy :: Term -> ElabD NativeTy
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 (P _ n _) | n == reflm "IT8" = return IT8
1620+reifyNativeTy x = fail $ "Couldn't reify reflected NativeTy " ++ show x
1621+
1622+reifyIntTy :: Term -> ElabD IntTy
1623+reifyIntTy (App (P _ n _) nt) | n == reflm "ITFixed" = fmap ITFixed (reifyNativeTy nt)
1624+reifyIntTy (P _ n _) | n == reflm "ITNative" = return ITNative
1625+reifyIntTy (P _ n _) | n == reflm "ITBig" = return ITBig
1626+reifyIntTy (P _ n _) | n == reflm "ITChar" = return ITChar
1627+reifyIntTy (App (App (P _ n _) nt) (Constant (I i))) | n == reflm "ITVec" = fmap (flip ITVec i)
1628+ (reifyNativeTy nt)
1629+
15991630reifyTTUExp :: Term -> ElabD UExp
16001631reifyTTUExp t@(App _ _)
16011632 = case unApply t of
@@ -1790,8 +1821,9 @@ reflectName (MN i n)
17901821reflectName (NErased) = Var (reflm "NErased")
17911822reflectName n = Var (reflm "NErased") -- special name, not yet implemented
17921823
1793−-- | Elaborate a name to a pattern. This means that NS and UN will be intact,
1794−-- while all others become _
1824+-- | Elaborate a name to a pattern. This means that NS and UN will be intact.
1825+-- MNs corresponding to will care about the string but not the number. All
1826+-- others become _.
17951827reflectNameQuotePattern :: Name -> ElabD ()
17961828reflectNameQuotePattern n@(UN s)
17971829 = do fill $ reflectName n
@@ -1799,6 +1831,12 @@ reflectNameQuotePattern n@(UN s)
17991831reflectNameQuotePattern n@(NS _ _)
18001832 = do fill $ reflectName n
18011833 solve
1834+reflectNameQuotePattern (MN _ n)
1835+ = do i <- getNameFrom (sMN 0 "mnCounter")
1836+ claim i (RConstant (AType (ATInt ITNative)))
1837+ movelast i
1838+ fill $ reflCall "MN" [Var i, RConstant (Str $ T.unpack n)]
1839+ solve
18021840reflectNameQuotePattern _ -- for all other names, match any
18031841 = do nameHole <- getNameFrom (sMN 0 "name")
18041842 claim nameHole (Var (reflm "TTName"))
@@ -1829,28 +1867,45 @@ reflectBinderQuote unq (PVar t)
18291867reflectBinderQuote unq (PVTy t)
18301868 = reflCall "PVTy" [Var (reflm "TT"), reflectQuote unq t]
18311869
1870+mkList :: Raw -> [Raw] -> Raw
1871+mkList ty [] = RApp (Var (sNS (sUN "Nil") ["List", "Prelude"])) ty
1872+mkList ty (x:xs) = RApp (RApp (RApp (Var (sNS (sUN "::") ["List", "Prelude"])) ty)
1873+ x)
1874+ (mkList ty xs)
1875+
18321876reflectConstant :: Const -> Raw
18331877reflectConstant c@(I _) = reflCall "I" [RConstant c]
18341878reflectConstant c@(BI _) = reflCall "BI" [RConstant c]
18351879reflectConstant c@(Fl _) = reflCall "Fl" [RConstant c]
18361880reflectConstant c@(Ch _) = reflCall "Ch" [RConstant c]
18371881reflectConstant c@(Str _) = reflCall "Str" [RConstant c]
1838−reflectConstant (AType (ATInt ITNative)) = Var (reflm "IType")
1839−reflectConstant (AType (ATInt ITBig)) = Var (reflm "BIType")
1840−reflectConstant (AType ATFloat) = Var (reflm "FlType")
1841−reflectConstant (AType (ATInt ITChar)) = Var (reflm "ChType")
1842−reflectConstant (StrType) = Var (reflm "StrType")
18431882reflectConstant c@(B8 _) = reflCall "B8" [RConstant c]
18441883reflectConstant c@(B16 _) = reflCall "B16" [RConstant c]
18451884reflectConstant c@(B32 _) = reflCall "B32" [RConstant c]
18461885reflectConstant c@(B64 _) = reflCall "B64" [RConstant c]
1847−reflectConstant (AType (ATInt (ITFixed IT8))) = Var (reflm "B8Type")
1848−reflectConstant (AType (ATInt (ITFixed IT16))) = Var (reflm "B16Type")
1849−reflectConstant (AType (ATInt (ITFixed IT32))) = Var (reflm "B32Type")
1850−reflectConstant (AType (ATInt (ITFixed IT64))) = Var (reflm "B64Type")
1851−reflectConstant (PtrType) = Var (reflm "PtrType")
1852−reflectConstant (VoidType) = Var (reflm "VoidType")
1853−reflectConstant (Forgot) = Var (reflm "Forgot")
1886+reflectConstant (B8V ws) = reflCall "B8V" [mkList (Var (sUN "Bits8")) . map (RConstant . B8) . V.toList $ ws]
1887+reflectConstant (B16V ws) = reflCall "B8V" [mkList (Var (sUN "Bits16")) . map (RConstant . B16) . V.toList $ ws]
1888+reflectConstant (B32V ws) = reflCall "B8V" [mkList (Var (sUN "Bits32")) . map (RConstant . B32) . V.toList $ ws]
1889+reflectConstant (B64V ws) = reflCall "B8V" [mkList (Var (sUN "Bits64")) . map (RConstant . B64) . V.toList $ ws]
1890+reflectConstant (AType (ATInt ITNative)) = reflCall "AType" [reflCall "ATInt" [Var (reflm "ITNative")]]
1891+reflectConstant (AType (ATInt ITBig)) = reflCall "AType" [reflCall "ATInt" [Var (reflm "ITBig")]]
1892+reflectConstant (AType ATFloat) = reflCall "AType" [Var (reflm "ATFloat")]
1893+reflectConstant (AType (ATInt ITChar)) = reflCall "AType" [reflCall "ATInt" [Var (reflm "ITChar")]]
1894+reflectConstant StrType = Var (reflm "StrType")
1895+reflectConstant (AType (ATInt (ITFixed IT8))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITFixed" [Var (reflm "IT8")]]]
1896+reflectConstant (AType (ATInt (ITFixed IT16))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITFixed" [Var (reflm "IT16")]]]
1897+reflectConstant (AType (ATInt (ITFixed IT32))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITFixed" [Var (reflm "IT32")]]]
1898+reflectConstant (AType (ATInt (ITFixed IT64))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITFixed" [Var (reflm "IT64")]]]
1899+reflectConstant (AType (ATInt (ITVec IT8 c))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITVec" [Var (reflm "IT8"), RConstant (I c)]]]
1900+reflectConstant (AType (ATInt (ITVec IT16 c))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITVec" [Var (reflm "IT16"), RConstant (I c)]]]
1901+reflectConstant (AType (ATInt (ITVec IT32 c))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITVec" [Var (reflm "IT32"), RConstant (I c)]]]
1902+reflectConstant (AType (ATInt (ITVec IT64 c))) = reflCall "AType" [reflCall "ATInt" [reflCall "ITVec" [Var (reflm "IT64"), RConstant (I c)]]]
1903+reflectConstant PtrType = Var (reflm "PtrType")
1904+reflectConstant ManagedPtrType = Var (reflm "ManagedPtrType")
1905+reflectConstant BufferType = Var (reflm "BufferType")
1906+reflectConstant VoidType = Var (reflm "VoidType")
1907+reflectConstant Forgot = Var (reflm "Forgot")
1908+
18541909
18551910reflectUExp :: UExp -> Raw
18561911reflectUExp (UVar i) = reflCall "UVar" [RConstant (I i)]
src/Idris/Error.hs+2−3
@@ -42,12 +42,11 @@ idrisCatch = catchError
4242
4343setAndReport :: Err -> Idris ()
4444setAndReport e = do ist <- getIState
45− let h = idris_outh ist
4645 case (unwrap e) of
4746 At fc e -> do setErrSpan fc
48− ihWarn h fc $ pprintErr ist e
47+ iWarn fc $ pprintErr ist e
4948 _ -> do setErrSpan (getErrSpan e)
50− ihWarn h emptyFC $ pprintErr ist e
49+ iWarn emptyFC $ pprintErr ist e
5150 where unwrap (ProofSearchFail e) = e -- remove bookkeeping constructor
5251 unwrap e = e
5352
src/Idris/IBC.hs+3
@@ -274,6 +274,7 @@ process i fn
274274 pDefs (symbols i) (ibc_defs i)
275275 pPatdefs (ibc_patdefs i)
276276 pAccess (ibc_access i)
277+ pFlags (ibc_flags i)
277278 pTotal (ibc_total i)
278279 pTotCheckErr (ibc_totcheckfail i)
279280 pCG (ibc_cg i)
@@ -943,6 +944,7 @@ instance Binary FnOpt where
943944 ErrorHandler -> putWord8 9
944945 ErrorReverse -> putWord8 10
945946 CoveringFn -> putWord8 11
947+ NoImplicit -> putWord8 12
946948 get
947949 = do i <- getWord8
948950 case i of
@@ -959,6 +961,7 @@ instance Binary FnOpt where
959961 9 -> return ErrorHandler
960962 10 -> return ErrorReverse
961963 11 -> return CoveringFn
964+ 12 -> return NoImplicit
962965 _ -> error "Corrupted binary data for FnOpt"
963966
964967instance Binary Fixity where
src/Idris/IdeSlave.hs+20−10
@@ -1,6 +1,6 @@
11{-# LANGUAGE FlexibleInstances, IncoherentInstances, PatternGuards #-}
22
3−module Idris.IdeSlave(parseMessage, convSExp, IdeSlaveCommand(..), sexpToCommand, toSExp, SExp(..), SExpable, Opt(..)) where
3+module Idris.IdeSlave(parseMessage, convSExp, IdeSlaveCommand(..), sexpToCommand, toSExp, SExp(..), SExpable, Opt(..), ideSlaveEpoch, getLen, getNChar) where
44
55import Text.Printf
66import Numeric
@@ -12,12 +12,24 @@ import qualified Data.ByteString.UTF8 as UTF8
1212-- import qualified Data.Text as T
1313import Text.Trifecta hiding (Err)
1414import Text.Trifecta.Delta
15+import System.IO
1516
1617import Idris.Core.TT
1718import Idris.Core.Binary
1819
1920import Control.Applicative hiding (Const)
2021
22+getNChar :: Handle -> Int -> String -> IO (String)
23+getNChar _ 0 s = return (reverse s)
24+getNChar h n s = do c <- hGetChar h
25+ getNChar h (n - 1) (c : s)
26+
27+getLen :: Handle -> IO (Either Err Int)
28+getLen h = do s <- getNChar h 6 ""
29+ case readHex s of
30+ ((num, ""):_) -> return $ Right num
31+ _ -> return $ Left . Msg $ "Couldn't read length " ++ s
32+
2133data SExp = SexpList [SExp]
2234 | StringAtom String
2335 | BoolAtom Bool
@@ -247,19 +259,14 @@ sexpToCommand _
247259parseMessage :: String -> Either Err (SExp, Integer)
248260parseMessage x = case receiveString x of
249261 Right (SexpList [cmd, (IntegerAtom id)]) -> Right (cmd, id)
262+ Right x -> Left . Msg $ "Invalid message " ++ show x
250263 Left err -> Left err
251264
252265receiveString :: String -> Either Err SExp
253266receiveString x =
254− case readHex (take 6 x) of
255− ((num, ""):_) ->
256− let msg = drop 6 x in
257− if (length msg) /= (num - 1)
258− then Left . Msg $ "bad input length"
259− else (case parseSExp msg of
260− Failure _ -> Left . Msg $ "parse failure"
261− Success r -> Right r)
262− _ -> Left . Msg $ "readHex failed"
267+ case parseSExp x of
268+ Failure _ -> Left . Msg $ "parse failure"
269+ Success r -> Right r
263270
264271convSExp :: SExpable a => String -> a -> Integer -> String
265272convSExp pre s id =
@@ -269,3 +276,6 @@ convSExp pre s id =
269276
270277getHexLength :: String -> String
271278getHexLength s = printf "%06x" (1 + (length s))
279+
280+ideSlaveEpoch :: Int
281+ideSlaveEpoch = 1
src/Idris/Interactive.hs+31−29
@@ -18,6 +18,8 @@ import Idris.Delaborate
1818import Idris.Output
1919import Idris.IdeSlave hiding (IdeSlaveCommand(..))
2020
21+import Idris.Elab.Value
22+
2123import Util.Pretty
2224import Util.System
2325
@@ -29,8 +31,8 @@ import Data.Maybe (fromMaybe)
2931
3032import Debug.Trace
3133
32−caseSplitAt :: Handle -> FilePath -> Bool -> Int -> Name -> Idris ()
33−caseSplitAt h fn updatefile l n
34+caseSplitAt :: FilePath -> Bool -> Int -> Name -> Idris ()
35+caseSplitAt fn updatefile l n
3436 = do src <- runIO $ readFile fn
3537 res <- splitOnLine l n fn
3638 iLOG (showSep "\n" (map show res))
@@ -41,11 +43,11 @@ caseSplitAt h fn updatefile l n
4143 then do let fb = fn ++ "~" -- make a backup!
4244 runIO $ writeFile fb (unlines before ++ new ++ unlines later)
4345 runIO $ copyFile fb fn
44− else -- do ihputStrLn h (show res)
45− ihPrintResult h new
46+ else -- do iputStrLn (show res)
47+ iPrintResult new
4648
47−addClauseFrom :: Handle -> FilePath -> Bool -> Int -> Name -> Idris ()
48−addClauseFrom h fn updatefile l n
49+addClauseFrom :: FilePath -> Bool -> Int -> Name -> Idris ()
50+addClauseFrom fn updatefile l n
4951 = do src <- runIO $ readFile fn
5052 let (before, tyline : later) = splitAt (l-1) (lines src)
5153 let indent = getIndent 0 (show n) tyline
@@ -59,15 +61,15 @@ addClauseFrom h fn updatefile l n
5961 cl ++ "\n" ++
6062 unlines rest)
6163 runIO $ copyFile fb fn
62− else ihPrintResult h cl
64+ else iPrintResult cl
6365 where
6466 getIndent i n [] = 0
6567 getIndent i n xs | take 9 xs == "instance " = i
6668 getIndent i n xs | take (length n) xs == n = i
6769 getIndent i n (x : xs) = getIndent (i + 1) n xs
6870
69−addProofClauseFrom :: Handle -> FilePath -> Bool -> Int -> Name -> Idris ()
70−addProofClauseFrom h fn updatefile l n
71+addProofClauseFrom :: FilePath -> Bool -> Int -> Name -> Idris ()
72+addProofClauseFrom fn updatefile l n
7173 = do src <- runIO $ readFile fn
7274 let (before, tyline : later) = splitAt (l-1) (lines src)
7375 let indent = getIndent 0 (show n) tyline
@@ -81,14 +83,14 @@ addProofClauseFrom h fn updatefile l n
8183 cl ++ "\n" ++
8284 unlines rest)
8385 runIO $ copyFile fb fn
84− else ihPrintResult h cl
86+ else iPrintResult cl
8587 where
8688 getIndent i n [] = 0
8789 getIndent i n xs | take (length n) xs == n = i
8890 getIndent i n (x : xs) = getIndent (i + 1) n xs
8991
90−addMissing :: Handle -> FilePath -> Bool -> Int -> Name -> Idris ()
91−addMissing h fn updatefile l n
92+addMissing :: FilePath -> Bool -> Int -> Name -> Idris ()
93+addMissing fn updatefile l n
9294 = do src <- runIO $ readFile fn
9395 let (before, tyline : later) = splitAt (l-1) (lines src)
9496 let indent = getIndent 0 (show n) tyline
@@ -106,7 +108,7 @@ addMissing h fn updatefile l n
106108 runIO $ writeFile fb (unlines (before ++ nonblank)
107109 ++ extras ++ unlines rest)
108110 runIO $ copyFile fb fn
109− else ihPrintResult h extras
111+ else iPrintResult extras
110112 where showPat = show . stripNS
111113 stripNS tm = mapPT dens tm where
112114 dens (PRef fc n) = PRef fc (nsroot n)
@@ -133,8 +135,8 @@ addMissing h fn updatefile l n
133135 getIndent i n (x : xs) = getIndent (i + 1) n xs
134136
135137
136−makeWith :: Handle -> FilePath -> Bool -> Int -> Name -> Idris ()
137−makeWith h fn updatefile l n
138+makeWith :: FilePath -> Bool -> Int -> Name -> Idris ()
139+makeWith fn updatefile l n
138140 = do src <- runIO $ readFile fn
139141 let (before, tyline : later) = splitAt (l-1) (lines src)
140142 let ind = getIndent tyline
@@ -149,15 +151,15 @@ makeWith h fn updatefile l n
149151 ++ with ++ "\n" ++
150152 unlines rest)
151153 runIO $ copyFile fb fn
152− else ihPrintResult h with
154+ else iPrintResult with
153155 where getIndent s = length (takeWhile isSpace s)
154156
155157
156−doProofSearch :: Handle -> FilePath -> Bool -> Bool ->
158+doProofSearch :: FilePath -> Bool -> Bool ->
157159 Int -> Name -> [Name] -> Maybe Int -> Idris ()
158−doProofSearch h fn updatefile rec l n hints Nothing
159− = doProofSearch h fn updatefile rec l n hints (Just 10)
160−doProofSearch h fn updatefile rec l n hints (Just depth)
160+doProofSearch fn updatefile rec l n hints Nothing
161+ = doProofSearch fn updatefile rec l n hints (Just 10)
162+doProofSearch fn updatefile rec l n hints (Just depth)
161163 = do src <- runIO $ readFile fn
162164 let (before, tyline : later) = splitAt (l-1) (lines src)
163165 ctxt <- getContext
@@ -174,8 +176,8 @@ doProofSearch h fn updatefile rec l n hints (Just depth)
174176 (ProofSearch rec False depth t hints)]
175177 let def = PClause fc mn (PRef fc mn) [] (body top) []
176178 newmv <- idrisCatch
177− (do elabDecl' EAll toplevel (PClauses fc [] mn [def])
178− (tm, ty) <- elabVal toplevel ERHS (PRef fc mn)
179+ (do elabDecl' EAll recinfo (PClauses fc [] mn [def])
180+ (tm, ty) <- elabVal recinfo ERHS (PRef fc mn)
179181 ctxt <- getContext
180182 i <- getIState
181183 return . flip displayS "" . renderPretty 1.0 80 $
@@ -190,7 +192,7 @@ doProofSearch h fn updatefile rec l n hints (Just depth)
190192 updateMeta False tyline (show n) newmv ++ "\n"
191193 ++ unlines later)
192194 runIO $ copyFile fb fn
193− else ihPrintResult h newmv
195+ else iPrintResult newmv
194196 where dropCtxt 0 sc = sc
195197 dropCtxt i (PPi _ _ _ sc) = dropCtxt (i - 1) sc
196198 dropCtxt i (PLet _ _ _ sc) = dropCtxt (i - 1) sc
@@ -233,8 +235,8 @@ addBracket True new | any isSpace new = '(' : new ++ ")"
233235 | otherwise = new
234236
235237
236−makeLemma :: Handle -> FilePath -> Bool -> Int -> Name -> Idris ()
237−makeLemma h fn updatefile l n
238+makeLemma :: FilePath -> Bool -> Int -> Name -> Idris ()
239+makeLemma fn updatefile l n
238240 = do src <- runIO $ readFile fn
239241 let (before, tyline : later) = splitAt (l-1) (lines src)
240242
@@ -264,8 +266,8 @@ makeLemma h fn updatefile l n
264266 runIO $ writeFile fb (addLem before tyline lem lem_app later)
265267 runIO $ copyFile fb fn
266268 else case idris_outputmode i of
267− RawOutput -> ihPrintResult h $ lem ++ "\n" ++ lem_app
268− IdeSlave n ->
269+ RawOutput _ -> iPrintResult $ lem ++ "\n" ++ lem_app
270+ IdeSlave n h ->
269271 let good = SexpList [SymbolAtom "ok",
270272 SexpList [SymbolAtom "metavariable-lemma",
271273 SexpList [SymbolAtom "replace-metavariable",
@@ -282,8 +284,8 @@ makeLemma h fn updatefile l n
282284 runIO $ writeFile fb (addProv before tyline lem_app later)
283285 runIO $ copyFile fb fn
284286 else case idris_outputmode i of
285− RawOutput -> ihPrintResult h $ lem_app
286− IdeSlave n ->
287+ RawOutput _ -> iPrintResult $ lem_app
288+ IdeSlave n h ->
287289 let good = SexpList [SymbolAtom "ok",
288290 SexpList [SymbolAtom "provisional-definition-lemma",
289291 SexpList [SymbolAtom "definition-clause",
src/Idris/Output.hs+60−63
@@ -24,27 +24,28 @@ pshow ist err = displayDecorated (consoleDecorate ist) .
2424 renderPretty 1.0 80 .
2525 fmap (fancifyAnnots ist) $ pprintErr ist err
2626
27−ihWarn :: Handle -> FC -> Doc OutputAnnotation -> Idris ()
28−ihWarn h fc err = do i <- getIState
29− case idris_outputmode i of
30− RawOutput ->
31− do err' <- iRender . fmap (fancifyAnnots i) $
32− if fc_fname fc /= ""
33− then text (show fc) <> colon <//> err
34− else err
35− runIO . hPutStrLn h $ displayDecorated (consoleDecorate i) err'
36− IdeSlave n ->
37− do err' <- iRender . fmap (fancifyAnnots i) $ err
38− let (str, spans) = displaySpans err'
39− runIO . hPutStrLn h $
40− convSExp "warning" (fc_fname fc, fc_start fc, fc_end fc, str, spans) n
27+iWarn :: FC -> Doc OutputAnnotation -> Idris ()
28+iWarn fc err =
29+ do i <- getIState
30+ case idris_outputmode i of
31+ RawOutput h ->
32+ do err' <- iRender . fmap (fancifyAnnots i) $
33+ if fc_fname fc /= ""
34+ then text (show fc) <> colon <//> err
35+ else err
36+ runIO . hPutStrLn h $ displayDecorated (consoleDecorate i) err'
37+ IdeSlave n h ->
38+ do err' <- iRender . fmap (fancifyAnnots i) $ err
39+ let (str, spans) = displaySpans err'
40+ runIO . hPutStrLn h $
41+ convSExp "warning" (fc_fname fc, fc_start fc, fc_end fc, str, spans) n
4142
4243iRender :: Doc a -> Idris (SimpleDoc a)
4344iRender d = do w <- getWidth
4445 ist <- getIState
4546 let ideSlave = case idris_outputmode ist of
46− IdeSlave _ -> True
47− _ -> False
47+ IdeSlave _ _ -> True
48+ _ -> False
4849 case w of
4950 InfinitelyWide -> return $ renderPretty 1.0 1000000000 d
5051 ColsWide n -> return $
@@ -63,37 +64,37 @@ consoleDisplayAnnotated h output = do ist <- getIState
6364 displayDecorated (consoleDecorate ist) $
6465 rendered
6566
66−ihPrintTermWithType :: Handle -> Doc OutputAnnotation -> Doc OutputAnnotation -> Idris ()
67−ihPrintTermWithType h tm ty = ihRenderResult h (tm <+> colon <+> align ty)
67+iPrintTermWithType :: Doc OutputAnnotation -> Doc OutputAnnotation -> Idris ()
68+iPrintTermWithType tm ty = iRenderResult (tm <+> colon <+> align ty)
6869
6970-- | Pretty-print a collection of overloadings to REPL or IDESlave - corresponds to :t name
70−ihPrintFunTypes :: Handle -> [(Name, Bool)] -> Name -> [(Name, PTerm)] -> Idris ()
71−ihPrintFunTypes h bnd n [] = ihPrintError h $ "No such variable " ++ show n
72−ihPrintFunTypes h bnd n overloads = do ist <- getIState
73− let ppo = ppOptionIst ist
74− let infixes = idris_infixes ist
75− let output = vsep (map (uncurry (ppOverload ppo infixes)) overloads)
76− ihRenderResult h output
71+iPrintFunTypes :: [(Name, Bool)] -> Name -> [(Name, PTerm)] -> Idris ()
72+iPrintFunTypes bnd n [] = iPrintError $ "No such variable " ++ show n
73+iPrintFunTypes bnd n overloads = do ist <- getIState
74+ let ppo = ppOptionIst ist
75+ let infixes = idris_infixes ist
76+ let output = vsep (map (uncurry (ppOverload ppo infixes)) overloads)
77+ iRenderResult output
7778 where fullName n = prettyName True True bnd n
7879 ppOverload ppo infixes n tm =
7980 fullName n <+> colon <+> align (pprintPTerm ppo bnd [] infixes tm)
8081
81−ihRenderOutput :: Handle -> Doc OutputAnnotation -> Idris ()
82−ihRenderOutput h doc =
82+iRenderOutput :: Doc OutputAnnotation -> Idris ()
83+iRenderOutput doc =
8384 do i <- getIState
8485 case idris_outputmode i of
85− RawOutput -> do out <- iRender doc
86− runIO $ putStrLn (displayDecorated (consoleDecorate i) out)
87− IdeSlave n ->
86+ RawOutput h -> do out <- iRender doc
87+ runIO $ putStrLn (displayDecorated (consoleDecorate i) out)
88+ IdeSlave n h ->
8889 do (str, spans) <- fmap displaySpans . iRender . fmap (fancifyAnnots i) $ doc
8990 let out = [toSExp str, toSExp spans]
90− runIO . putStrLn $ convSExp "write-decorated" out n
91+ runIO . hPutStrLn h $ convSExp "write-decorated" out n
9192
92−ihRenderResult :: Handle -> Doc OutputAnnotation -> Idris ()
93−ihRenderResult h d = do ist <- getIState
94− case idris_outputmode ist of
95− RawOutput -> consoleDisplayAnnotated h d
96− IdeSlave n -> ideSlaveReturnAnnotated n h d
93+iRenderResult :: Doc OutputAnnotation -> Idris ()
94+iRenderResult d = do ist <- getIState
95+ case idris_outputmode ist of
96+ RawOutput h -> consoleDisplayAnnotated h d
97+ IdeSlave n h -> ideSlaveReturnAnnotated n h d
9798
9899ideSlaveReturnWithStatus :: String -> Integer -> Handle -> Doc OutputAnnotation -> Idris ()
99100ideSlaveReturnWithStatus status n h out = do
@@ -111,56 +112,52 @@ ideSlaveReturnAnnotated :: Integer -> Handle -> Doc OutputAnnotation -> Idris ()
111112ideSlaveReturnAnnotated = ideSlaveReturnWithStatus "ok"
112113
113114-- | Show an error with semantic highlighting
114−ihRenderError :: Handle -> Doc OutputAnnotation -> Idris ()
115−ihRenderError h e = do ist <- getIState
116− case idris_outputmode ist of
117− RawOutput -> consoleDisplayAnnotated h e
118− IdeSlave n -> ideSlaveReturnWithStatus "error" n h e
119−
120−ihPrintWithStatus :: String -> Handle -> String -> Idris ()
121−ihPrintWithStatus status h s = do
115+iRenderError :: Doc OutputAnnotation -> Idris ()
116+iRenderError e = do ist <- getIState
117+ case idris_outputmode ist of
118+ RawOutput h -> consoleDisplayAnnotated h e
119+ IdeSlave n h -> ideSlaveReturnWithStatus "error" n h e
120+
121+iPrintWithStatus :: String -> String -> Idris ()
122+iPrintWithStatus status s = do
122123 i <- getIState
123124 case idris_outputmode i of
124− RawOutput -> case s of
125+ RawOutput h -> case s of
125126 "" -> return ()
126127 s -> runIO $ hPutStrLn h s
127− IdeSlave n ->
128+ IdeSlave n h ->
128129 let good = SexpList [SymbolAtom status, toSExp s] in
129130 runIO $ hPutStrLn h $ convSExp "return" good n
130131
131132
132−ihPrintResult :: Handle -> String -> Idris ()
133−ihPrintResult = ihPrintWithStatus "ok"
133+iPrintResult :: String -> Idris ()
134+iPrintResult = iPrintWithStatus "ok"
134135
135−ihPrintError :: Handle -> String -> Idris ()
136−ihPrintError = ihPrintWithStatus "error"
136+iPrintError :: String -> Idris ()
137+iPrintError = iPrintWithStatus "error"
137138
138−ihputStrLn :: Handle -> String -> Idris ()
139−ihputStrLn h s = do i <- getIState
140− case idris_outputmode i of
141− RawOutput -> runIO $ hPutStrLn h s
142− IdeSlave n -> runIO . hPutStrLn h $ convSExp "write-string" s n
139+iputStrLn :: String -> Idris ()
140+iputStrLn s = do i <- getIState
141+ case idris_outputmode i of
142+ RawOutput h -> runIO $ hPutStrLn h s
143+ IdeSlave n h -> runIO . hPutStrLn h $ convSExp "write-string" s n
143144
144−iputStrLn = ihputStrLn stdout
145−iPrintError = ihPrintError stdout
146−iPrintResult = ihPrintResult stdout
147−iWarn = ihWarn stdout
148145
149146ideslavePutSExp :: SExpable a => String -> a -> Idris ()
150147ideslavePutSExp cmd info = do i <- getIState
151148 case idris_outputmode i of
152− IdeSlave n -> runIO . putStrLn $ convSExp cmd info n
149+ IdeSlave n h -> runIO . hPutStrLn h $ convSExp cmd info n
153150 _ -> return ()
154151
155152-- TODO: send structured output similar to the metavariable list
156153iputGoal :: SimpleDoc OutputAnnotation -> Idris ()
157154iputGoal g = do i <- getIState
158155 case idris_outputmode i of
159− RawOutput -> runIO $ putStrLn (displayDecorated (consoleDecorate i) g)
160− IdeSlave n ->
156+ RawOutput h -> runIO $ hPutStrLn h (displayDecorated (consoleDecorate i) g)
157+ IdeSlave n h ->
161158 let (str, spans) = displaySpans . fmap (fancifyAnnots i) $ g
162159 goal = [toSExp str, toSExp spans]
163− in runIO . putStrLn $ convSExp "write-goal" goal n
160+ in runIO . hPutStrLn h $ convSExp "write-goal" goal n
164161
165162-- | Warn about totality problems without failing to compile
166163warnTotality :: Idris ()
src/Idris/ParseExpr.hs+1−1
@@ -320,7 +320,7 @@ simpleExpr syn =
320320 <|> idiom syn
321321 <|> listExpr syn
322322 <|> alt syn
323− <|> do lchar '!'
323+ <|> do reservedOp "!"
324324 s <- simpleExpr syn
325325 fc <- getFC
326326 return (PAppBind fc s [])
src/Idris/ParseHelpers.hs+2−2
@@ -17,7 +17,7 @@ import Idris.Core.TT
1717import Idris.Core.Evaluate
1818import Idris.Delaborate (pprintErr)
1919import Idris.Docstrings
20−import Idris.Output (ihWarn)
20+import Idris.Output (iWarn)
2121
2222import qualified Util.Pretty as Pretty (text)
2323
@@ -79,7 +79,7 @@ clearParserWarnings = do ist <- getIState
7979
8080reportParserWarnings :: Idris ()
8181reportParserWarnings = do ist <- getIState
82− mapM_ (uncurry $ ihWarn (idris_outh ist))
82+ mapM_ (uncurry iWarn)
8383 (map (\ (fc, err) -> (fc, pprintErr ist err)) .
8484 reverse .
8585 nub $
src/Idris/Parser.hs+27−24
@@ -376,6 +376,7 @@ fnDecl' syn = checkFixity $
376376FnOpts ::= 'total'
377377 | 'partial'
378378 | 'implicit'
379+ | '%' 'no_implicit'
379380 | '%' 'assert_total'
380381 | '%' 'error_handler'
381382 | '%' 'reflection'
@@ -402,6 +403,8 @@ fnOpts opts
402403 <|> do reserved "covering"; fnOpts (CoveringFn : (opts \\ [TotalFn]))
403404 <|> do try (lchar '%' *> reserved "export"); c <- stringLiteral;
404405 fnOpts (CExport c : opts)
406+ <|> do try (lchar '%' *> reserved "no_implicit");
407+ fnOpts (NoImplicit : opts)
405408 <|> do try (lchar '%' *> reserved "assert_total");
406409 fnOpts (AssertTotal : opts)
407410 <|> do try (lchar '%' *> reserved "error_handler");
@@ -1156,8 +1159,8 @@ parseProg syn fname input mrk
11561159 let (fc, msg) = findFC doc
11571160 i <- getIState
11581161 case idris_outputmode i of
1159− RawOutput -> ihputStrLn (idris_outh i) (show $ fixColour (idris_colourRepl i) doc)
1160− IdeSlave n -> ihWarn (idris_outh i) fc (P.text msg)
1162+ RawOutput h -> iputStrLn (show $ fixColour (idris_colourRepl i) doc)
1163+ IdeSlave n h -> iWarn fc (P.text msg)
11611164 putIState (i { errSpan = Just fc })
11621165 return []
11631166 Success (x, i) -> do putIState i
@@ -1173,17 +1176,17 @@ parseProg syn fname input mrk
11731176 return (ds, i')
11741177
11751178{- | Load idris module and show error if something wrong happens -}
1176−loadModule :: Handle -> FilePath -> Idris String
1177−loadModule outh f
1178− = idrisCatch (loadModule' outh f)
1179+loadModule :: FilePath -> Idris String
1180+loadModule f
1181+ = idrisCatch (loadModule' f)
11791182 (\e -> do setErrSpan (getErrSpan e)
11801183 ist <- getIState
1181− ihWarn outh (getErrSpan e) $ pprintErr ist e
1184+ iWarn (getErrSpan e) $ pprintErr ist e
11821185 return "")
11831186
11841187{- | Load idris module -}
1185−loadModule' :: Handle -> FilePath -> Idris String
1186−loadModule' outh f
1188+loadModule' :: FilePath -> Idris String
1189+loadModule' f
11871190 = do i <- getIState
11881191 let file = takeWhile (/= ' ') f
11891192 ibcsd <- valIBCSubDir i
@@ -1193,21 +1196,21 @@ loadModule' outh f
11931196 then iLOG $ "Already read " ++ file
11941197 else do putIState (i { imported = file : imported i })
11951198 case fp of
1196− IDR fn -> loadSource outh False fn Nothing
1197− LIDR fn -> loadSource outh True fn Nothing
1199+ IDR fn -> loadSource False fn Nothing
1200+ LIDR fn -> loadSource True fn Nothing
11981201 IBC fn src ->
11991202 idrisCatch (loadIBC fn)
12001203 (\c -> do iLOG $ fn ++ " failed " ++ pshow i c
12011204 case src of
1202− IDR sfn -> loadSource outh False sfn Nothing
1203− LIDR sfn -> loadSource outh True sfn Nothing)
1205+ IDR sfn -> loadSource False sfn Nothing
1206+ LIDR sfn -> loadSource True sfn Nothing)
12041207 let (dir, fh) = splitFileName file
12051208 return (dropExtension fh)
12061209
12071210
12081211{- | Load idris code from file -}
1209−loadFromIFile :: Handle -> IFileType -> Maybe Int -> Idris ()
1210−loadFromIFile h i@(IBC fn src) maxline
1212+loadFromIFile :: IFileType -> Maybe Int -> Idris ()
1213+loadFromIFile i@(IBC fn src) maxline
12111214 = do iLOG $ "Skipping " ++ getSrcFile i
12121215 idrisCatch (loadIBC fn)
12131216 (\err -> ierror $ LoadingFailed fn err)
@@ -1216,22 +1219,22 @@ loadFromIFile h i@(IBC fn src) maxline
12161219 getSrcFile (LIDR fn) = fn
12171220 getSrcFile (IBC f src) = getSrcFile src
12181221
1219−loadFromIFile h (IDR fn) maxline = loadSource' h False fn maxline
1220−loadFromIFile h (LIDR fn) maxline = loadSource' h True fn maxline
1222+loadFromIFile (IDR fn) maxline = loadSource' False fn maxline
1223+loadFromIFile (LIDR fn) maxline = loadSource' True fn maxline
12211224
12221225{-| Load idris source code and show error if something wrong happens -}
1223−loadSource' :: Handle -> Bool -> FilePath -> Maybe Int -> Idris ()
1224−loadSource' h lidr r maxline
1225− = idrisCatch (loadSource h lidr r maxline)
1226+loadSource' :: Bool -> FilePath -> Maybe Int -> Idris ()
1227+loadSource' lidr r maxline
1228+ = idrisCatch (loadSource lidr r maxline)
12261229 (\e -> do setErrSpan (getErrSpan e)
12271230 ist <- getIState
12281231 case e of
1229− At f e' -> ihWarn h f (pprintErr ist e')
1230− _ -> ihWarn h (getErrSpan e) (pprintErr ist e))
1232+ At f e' -> iWarn f (pprintErr ist e')
1233+ _ -> iWarn (getErrSpan e) (pprintErr ist e))
12311234
12321235{- | Load Idris source code-}
1233−loadSource :: Handle -> Bool -> FilePath -> Maybe Int -> Idris ()
1234−loadSource h lidr f toline
1236+loadSource :: Bool -> FilePath -> Maybe Int -> Idris ()
1237+loadSource lidr f toline
12351238 = do iLOG ("Reading " ++ f)
12361239 i <- getIState
12371240 let def_total = default_total i
@@ -1275,7 +1278,7 @@ loadSource h lidr f toline
12751278 logLvl 3 (show (idris_infixes i))
12761279 -- Now add all the declarations to the context
12771280 v <- verbose
1278− when v $ ihputStrLn h $ "Type checking " ++ f
1281+ when v $ iputStrLn $ "Type checking " ++ f
12791282 -- we totality check after every Mutual block, so if
12801283 -- anything is a single definition, wrap it in a
12811284 -- mutual block on its own
src/Idris/Prover.hs+56−47
@@ -6,6 +6,9 @@ import Idris.Core.Evaluate
66import Idris.Core.CaseTree
77import Idris.Core.Typecheck
88
9+import Idris.Elab.Utils
10+import Idris.Elab.Value
11+
912import Idris.AbsSyntax
1013import Idris.AbsSyntaxTree
1114import Idris.Delaborate
@@ -16,12 +19,13 @@ import Idris.Parser hiding (params)
1619import Idris.Error
1720import Idris.DataOpts
1821import Idris.Completion
19−import Idris.IdeSlave
22+import qualified Idris.IdeSlave as IdeSlave
2023import Idris.Output
2124import Idris.TypeSearch (searchByType)
2225
2326import Text.Trifecta.Result(Result(..))
2427
28+import System.IO (Handle, stdin, stdout, hPutStrLn)
2529import System.Console.Haskeline
2630import System.Console.Haskeline.History
2731import Control.Monad.State.Strict
@@ -67,8 +71,8 @@ prove opt ctxt lit n ty
6771 iLOG $ "Adding " ++ show tm
6872 i <- getIState
6973 case idris_outputmode i of
70− IdeSlave _ -> ideslavePutSExp "end-proof-mode" (n, showProof lit n prf)
71− _ -> iputStrLn $ showProof lit n prf
74+ IdeSlave _ _ -> ideslavePutSExp "end-proof-mode" (n, showProof lit n prf)
75+ _ -> iputStrLn $ showProof lit n prf
7276 let proofs = proof_list i
7377 putIState (i { proof_list = (n, prf) : proofs })
7478 let tree = simpleCase False True False CompileTime (fileFC "proof") [] [] [([], P Ref n ty, tm)]
@@ -90,9 +94,8 @@ prove opt ctxt lit n ty
9094 [([], P Ref n ty, ptm')] ty)
9195 solveDeferred n
9296 case idris_outputmode i of
93− IdeSlave n ->
94− runIO . putStrLn $
95− convSExp "return" (SymbolAtom "ok", "") n
97+ IdeSlave n h ->
98+ runIO . hPutStrLn h $ IdeSlave.convSExp "return" (IdeSlave.SymbolAtom "ok", "") n
9699 _ -> return ()
97100
98101elabStep :: ElabState [PDecl] -> ElabD a -> Idris (a, ElabState [PDecl])
@@ -137,6 +140,8 @@ dumpState ist ps@(PS nm (h:hs) _ _ tm _ _ _ _ _ _ problems i _ _ ctxy _ _ _ _) =
137140 prettyPs bnd [] = empty
138141 prettyPs bnd ((n@(MN _ r), _) : bs)
139142 | r == txt "rewrite_rule" = prettyPs ((n, False):bnd) bs
143+ prettyPs bnd ((n@(MN _ _), _) : bs)
144+ | not (n `elem` freeEnvNames bs) = prettyPs bnd bs
140145 prettyPs bnd ((n, Let t v) : bs) =
141146 line <> bindingOf n False <+> text "=" <+> tPretty bnd v <+> colon <+>
142147 align (tPretty bnd t) <> prettyPs ((n, False):bnd) bs
@@ -165,27 +170,35 @@ dumpState ist ps@(PS nm (h:hs) _ _ tm _ _ _ _ _ _ problems i _ _ ctxy _ _ _ _) =
165170 text "---------- Other goals: ----------" <$$>
166171 nest nestingSize (align . cat . punctuate (text ",") . map (flip bindingOf False) $ hs)
167172
173+ freeEnvNames :: Env -> [Name]
174+ freeEnvNames = foldl (++) [] . map (\(n, b) -> freeNames (Bind n b Erased))
175+
168176lifte :: ElabState [PDecl] -> ElabD a -> Idris a
169177lifte st e = do (v, _) <- elabStep st e
170178 return v
171179
172−receiveInput :: ElabState [PDecl] -> Idris (Maybe String)
173−receiveInput e =
180+receiveInput :: Handle -> ElabState [PDecl] -> Idris (Maybe String)
181+receiveInput h e =
174182 do i <- getIState
175− l <- runIO $ getLine
176− (sexp, id) <- case parseMessage l of
183+ let inh = if h == stdout then stdin else h
184+ len' <- runIO $ IdeSlave.getLen inh
185+ len <- case len' of
186+ Left err -> ierror err
187+ Right n -> return n
188+ l <- runIO $ IdeSlave.getNChar inh len ""
189+ (sexp, id) <- case IdeSlave.parseMessage l of
177190 Left err -> ierror err
178191 Right (sexp, id) -> return (sexp, id)
179− putIState $ i { idris_outputmode = (IdeSlave id) }
180− case sexpToCommand sexp of
181− Just (REPLCompletions prefix) ->
192+ putIState $ i { idris_outputmode = (IdeSlave id h) }
193+ case IdeSlave.sexpToCommand sexp of
194+ Just (IdeSlave.REPLCompletions prefix) ->
182195 do (unused, compls) <- proverCompletion (assumptionNames e) (reverse prefix, "")
183− let good = SexpList [SymbolAtom "ok", toSExp (map replacement compls, reverse unused)]
196+ let good = IdeSlave.SexpList [IdeSlave.SymbolAtom "ok", IdeSlave.toSExp (map replacement compls, reverse unused)]
184197 ideslavePutSExp "return" good
185− receiveInput e
186− Just (Interpret cmd) -> return (Just cmd)
187− Just (TypeOf str) -> return (Just (":t " ++ str))
188− Just (DocsFor str) -> return (Just (":doc " ++ str))
198+ receiveInput h e
199+ Just (IdeSlave.Interpret cmd) -> return (Just cmd)
200+ Just (IdeSlave.TypeOf str) -> return (Just (":t " ++ str))
201+ Just (IdeSlave.DocsFor str) -> return (Just (":doc " ++ str))
189202 _ -> return Nothing
190203
191204ploop :: Name -> Bool -> String -> [String] -> ElabState [PDecl] -> Maybe History -> Idris (Term, [String])
@@ -195,17 +208,18 @@ ploop fn d prompt prf e h
195208 when d $ dumpState i (proof e)
196209 (x, h') <-
197210 case idris_outputmode i of
198− RawOutput -> runInputT (proverSettings e) $
199− -- Manually track the history so that we can use the proof state
200− do _ <- case h of
201− Just history -> putHistory history
202− Nothing -> return ()
203− l <- getInputLine (prompt ++ "> ")
204− h' <- getHistory
205− return (l, Just h')
206− IdeSlave n ->
211+ RawOutput _ ->
212+ runInputT (proverSettings e) $
213+ -- Manually track the history so that we can use the proof state
214+ do case h of
215+ Just history -> putHistory history
216+ Nothing -> return ()
217+ l <- getInputLine (prompt ++ "> ")
218+ h' <- getHistory
219+ return (l, Just h')
220+ IdeSlave _ handle ->
207221 do isetPrompt prompt
208− i <- receiveInput e
222+ i <- receiveInput handle e
209223 return (i, h)
210224 (cmd, step) <- case x of
211225 Nothing -> do iPrintError ""; ifail "Abandoned"
@@ -237,7 +251,8 @@ ploop fn d prompt prf e h
237251 (\err -> return (False, e, False, prf, Left err))
238252 ideslavePutSExp "write-proof-state" (prf', length prf')
239253 case res of
240− Left err -> do iPrintError (pshow i err)
254+ Left err -> do ist <- getIState
255+ iRenderError $ pprintErr ist err
241256 ploop fn d prompt prf' st h'
242257 Right ok ->
243258 if done then do (tm, _) <- elabStep st get_term
@@ -250,8 +265,7 @@ ploop fn d prompt prf e h
250265 ist <- getIState
251266 imp <- impShow
252267 idrisCatch (do
253− let h = idris_outh ist
254− OK env = envAtFocus (proof e)
268+ let OK env = envAtFocus (proof e)
255269 ctxt' = envCtxt env ctxt
256270 bnd = map (\x -> (fst x, False)) env
257271 ist' = ist { tt_ctxt = ctxt' }
@@ -259,8 +273,8 @@ ploop fn d prompt prf e h
259273 -- Unlike the REPL, metavars have no special treatment, to
260274 -- make it easier to see how to prove with them.
261275 let action = case lookupNames n ctxt' of
262− [] -> ihPrintError h $ "No such variable " ++ show n
263− ts -> ihPrintFunTypes h bnd n (map (\n -> (n, delabTy ist' n)) ts)
276+ [] -> iPrintError $ "No such variable " ++ show n
277+ ts -> iPrintFunTypes bnd n (map (\n -> (n, delabTy ist' n)) ts)
264278 putIState ist
265279 return (False, e, False, prf, Right action))
266280 (\err -> do putIState ist ; ierror err)
@@ -272,17 +286,16 @@ ploop fn d prompt prf e h
272286 let OK env = envAtFocus (proof e)
273287 ctxt' = envCtxt env ctxt
274288 putIState ist { tt_ctxt = ctxt' }
275− (tm, ty) <- elabVal toplevel ERHS t
289+ (tm, ty) <- elabVal recinfo ERHS t
276290 let ppo = ppOptionIst ist
277291 ty' = normaliseC ctxt [] ty
278− h = idris_outh ist
279292 infixes = idris_infixes ist
280293 action = case tm of
281294 TType _ ->
282− ihPrintTermWithType h (prettyImp ppo PType) type1Doc
295+ iPrintTermWithType (prettyImp ppo PType) type1Doc
283296 _ -> let bnd = map (\x -> (fst x, False)) env in
284− ihPrintTermWithType h (pprintPTerm ppo bnd [] infixes (delab ist tm))
285− (pprintPTerm ppo bnd [] infixes (delab ist ty))
297+ iPrintTermWithType (pprintPTerm ppo bnd [] infixes (delab ist tm))
298+ (pprintPTerm ppo bnd [] infixes (delab ist ty))
286299 putIState ist
287300 return (False, e, False, prf, Right action))
288301 (\err -> do putIState ist { tt_ctxt = ctxt } ; ierror err)
@@ -296,32 +309,28 @@ ploop fn d prompt prf e h
296309 ist' = ist { tt_ctxt = ctxt' }
297310 bnd = map (\x -> (fst x, False)) env
298311 putIState ist'
299− (tm, ty) <- elabVal toplevel ERHS t
312+ (tm, ty) <- elabVal recinfo ERHS t
300313 let tm' = force (normaliseAll ctxt' env tm)
301314 ty' = force (normaliseAll ctxt' env ty)
302315 ppo = ppOption (idris_options ist')
303316 infixes = idris_infixes ist
304317 tmDoc = pprintPTerm ppo bnd [] infixes (delab ist' tm')
305318 tyDoc = pprintPTerm ppo bnd [] infixes (delab ist' ty')
306− action = ihPrintTermWithType (idris_outh ist') tmDoc tyDoc
319+ action = iPrintTermWithType tmDoc tyDoc
307320 putIState ist
308321 return (False, e, False, prf, Right action))
309322 (\err -> do putIState ist ; ierror err)
310323 docStr :: Either Name Const -> Idris (Bool, ElabState [PDecl], Bool, [String], Either Err (Idris ()))
311324 docStr (Left n) = do ist <- getIState
312− let h = idris_outh ist
313325 idrisCatch (case lookupCtxtName n (idris_docstrings ist) of
314326 [] -> return (False, e, False, prf,
315327 Left . Msg $ "No documentation for " ++ show n)
316328 ns -> do toShow <- mapM (showDoc ist) ns
317329 return (False, e, False, prf,
318− Right $ ihRenderResult h (vsep toShow)))
330+ Right $ iRenderResult (vsep toShow)))
319331 (\err -> do putIState ist ; ierror err)
320332 where showDoc ist (n, d) = do doc <- getDocs n
321333 return $ pprintDocs ist doc
322334 docStr (Right c) = do ist <- getIState
323− let h = idris_outh ist
324− return (False, e, False, prf, Right . ihRenderResult h $ pprintConstDocs ist c (constDocs c))
325− search t = do ist <- getIState
326− let h = idris_outh ist
327− return (False, e, False, prf, Right $ searchByType h t)
335+ return (False, e, False, prf, Right . iRenderResult $ pprintConstDocs ist c (constDocs c))
336+ search t = return (False, e, False, prf, Right $ searchByType t)
src/Idris/REPL.hs+282−248
@@ -34,10 +34,15 @@ import Idris.Interactive
3434import Idris.WhoCalls
3535import Idris.TypeSearch (searchByType)
3636
37+import Idris.Elab.Type
38+import Idris.Elab.Clause
39+import Idris.Elab.Data
40+import Idris.Elab.Value
41+
3742import Version_idris (gitHash)
3843import Util.System
3944import Util.DynamicLinker
40−import Util.Net (listenOnLocalhost)
45+import Util.Net (listenOnLocalhost, listenOnLocalhostAnyPort)
4146import Util.Pretty hiding ((</>))
4247
4348import Idris.Core.Evaluate
@@ -86,6 +91,8 @@ import Data.Word (Word)
8691import Data.Either (partitionEithers)
8792import Control.DeepSeq
8893
94+import Numeric ( readHex )
95+
8996import Debug.Trace
9097
9198-- | Run the REPL
@@ -144,7 +151,7 @@ startServer orig fn_in = do tid <- runIO $ forkOS serverLoop
144151 -- TODO: option for port number
145152 serverLoop = withSocketsDo $
146153 do sock <- listenOnLocalhost $ PortNumber 4294
147− loop fn orig sock
154+ loop fn orig { idris_colourRepl = False } sock
148155
149156 fn = case fn_in of
150157 (f:_) -> f
@@ -154,7 +161,10 @@ startServer orig fn_in = do tid <- runIO $ forkOS serverLoop
154161 = do (h,_,_) <- accept sock
155162 hSetEncoding h utf8
156163 cmd <- hGetLine h
157− (ist', fn) <- processNetCmd orig ist h fn cmd
164+ let isth = case idris_outputmode ist of
165+ RawOutput _ -> ist {idris_outputmode = RawOutput h}
166+ IdeSlave n _ -> ist {idris_outputmode = IdeSlave n h}
167+ (ist', fn) <- processNetCmd orig isth h fn cmd
158168 hClose h
159169 loop fn ist' sock
160170
@@ -180,12 +190,18 @@ processNetCmd orig i h fn cmd
180190 setOutH h
181191 setQuiet True
182192 setVerbose False
183− mods <- loadInputs h [f] toline
193+ mods <- loadInputs [f] toline
184194 ist <- getIState
185195 return (ist, f)
186− processNet fn c = do process h fn c
196+ processNet fn c = do process fn c
187197 ist <- getIState
188198 return (ist, fn)
199+ setOutH :: Handle -> Idris ()
200+ setOutH h =
201+ do ist <- getIState
202+ putIState $ case idris_outputmode ist of
203+ RawOutput _ -> ist {idris_outputmode = RawOutput h}
204+ IdeSlave n _ -> ist {idris_outputmode = IdeSlave n h}
189205
190206-- | Run a command on the server on localhost
191207runClient :: String -> IO ()
@@ -201,55 +217,73 @@ runClient str = withSocketsDo $ do
201217 else do l <- hGetLine h
202218 hGetResp (acc ++ l ++ "\n") h
203219
220+initIdeslaveSocket :: IO Handle
221+initIdeslaveSocket = do
222+ (sock, port) <- listenOnLocalhostAnyPort
223+ putStrLn $ show port
224+ (h, _, _) <- accept sock
225+ hSetEncoding h utf8
226+ return h
227+
204228-- | Run the IdeSlave
205−ideslaveStart :: IState -> [FilePath] -> Idris ()
206−ideslaveStart orig mods
207− = do i <- getIState
229+ideslaveStart :: Bool -> IState -> [FilePath] -> Idris ()
230+ideslaveStart s orig mods
231+ = do h <- runIO $ if s then initIdeslaveSocket else return stdout
232+ setIdeSlave True h
233+ i <- getIState
208234 case idris_outputmode i of
209− IdeSlave n ->
210− when (mods /= []) (do isetPrompt (mkPrompt mods))
211− ideslave orig mods
212−
213−
214−ideslave :: IState -> [FilePath] -> Idris ()
215−ideslave orig mods
235+ IdeSlave n h ->
236+ do runIO $ hPutStrLn h $ IdeSlave.convSExp "protocol-version" IdeSlave.ideSlaveEpoch n
237+ case mods of
238+ a:_ -> runIdeSlaveCommand h n i "" [] (IdeSlave.LoadFile a Nothing)
239+ _ -> return ()
240+ ideslave h orig mods
241+
242+ideslave :: Handle -> IState -> [FilePath] -> Idris ()
243+ideslave h orig mods
216244 = do idrisCatch
217− (do l <- runIO $ getLine
245+ (do let inh = if h == stdout then stdin else h
246+ len' <- runIO $ IdeSlave.getLen inh
247+ len <- case len' of
248+ Left err -> ierror err
249+ Right n -> return n
250+ l <- runIO $ IdeSlave.getNChar inh len ""
218251 (sexp, id) <- case IdeSlave.parseMessage l of
219252 Left err -> ierror err
220253 Right (sexp, id) -> return (sexp, id)
221254 i <- getIState
222− putIState $ i { idris_outputmode = (IdeSlave id) }
255+ putIState $ i { idris_outputmode = (IdeSlave id h) }
223256 idrisCatch -- to report correct id back!
224257 (do let fn = case mods of
225258 (f:_) -> f
226− _ -> ""
259+ _ -> ""
227260 case IdeSlave.sexpToCommand sexp of
228− Just cmd -> runIdeSlaveCommand id orig fn mods cmd
261+ Just cmd -> runIdeSlaveCommand h id orig fn mods cmd
229262 Nothing -> iPrintError "did not understand" )
230263 (\e -> do iPrintError $ show e))
231264 (\e -> do iPrintError $ show e)
232− ideslave orig mods
265+ ideslave h orig mods
233266
234267-- | Run IDESlave commands
235−runIdeSlaveCommand :: Integer -- ^^ The continuation ID for the client
268+runIdeSlaveCommand :: Handle -- ^^ The handle for communication
269+ -> Integer -- ^^ The continuation ID for the client
236270 -> IState -- ^^ The original IState
237271 -> FilePath -- ^^ The current open file
238272 -> [FilePath] -- ^^ The currently loaded modules
239273 -> IdeSlave.IdeSlaveCommand -- ^^ The command to process
240274 -> Idris ()
241−runIdeSlaveCommand id orig fn mods (IdeSlave.Interpret cmd) =
275+runIdeSlaveCommand h id orig fn mods (IdeSlave.Interpret cmd) =
242276 do c <- colourise
243277 i <- getIState
244278 case parseCmd i "(input)" cmd of
245279 Failure err -> iPrintError $ show (fixColour c err)
246280 Success (Prove n') ->
247281 idrisCatch
248− (do process stdout fn (Prove n')
282+ (do process fn (Prove n')
249283 isetPrompt (mkPrompt mods)
250284 case idris_outputmode i of
251− IdeSlave n -> -- signal completion of proof to ide
252− runIO . hPutStrLn stdout $
285+ IdeSlave n h -> -- signal completion of proof to ide
286+ runIO . hPutStrLn h $
253287 IdeSlave.convSExp "return"
254288 (IdeSlave.SymbolAtom "ok", "")
255289 n
@@ -257,26 +291,26 @@ runIdeSlaveCommand id orig fn mods (IdeSlave.Interpret cmd) =
257291 (\e -> do ist <- getIState
258292 isetPrompt (mkPrompt mods)
259293 case idris_outputmode i of
260− IdeSlave n ->
261− runIO . hPutStrLn stdout $
294+ IdeSlave n h ->
295+ runIO . hPutStrLn h $
262296 IdeSlave.convSExp "abandon-proof" "Abandoned" n
263297 _ -> return ()
264− ihRenderError stdout $ pprintErr ist e)
298+ iRenderError $ pprintErr ist e)
265299 Success cmd -> idrisCatch
266300 (ideslaveProcess fn cmd)
267− (\e -> getIState >>= ihRenderError stdout . flip pprintErr e)
268−runIdeSlaveCommand id orig fn mods (IdeSlave.REPLCompletions str) =
301+ (\e -> getIState >>= iRenderError . flip pprintErr e)
302+runIdeSlaveCommand h id orig fn mods (IdeSlave.REPLCompletions str) =
269303 do (unused, compls) <- replCompletion (reverse str, "")
270304 let good = IdeSlave.SexpList [IdeSlave.SymbolAtom "ok",
271305 IdeSlave.toSExp (map replacement compls,
272306 reverse unused)]
273− runIO $ putStrLn $ IdeSlave.convSExp "return" good id
274−runIdeSlaveCommand id orig fn mods (IdeSlave.LoadFile filename toline) =
307+ runIO . hPutStrLn h $ IdeSlave.convSExp "return" good id
308+runIdeSlaveCommand h id orig fn mods (IdeSlave.LoadFile filename toline) =
275309 do i <- getIState
276310 clearErr
277311 putIState (orig { idris_options = idris_options i,
278− idris_outputmode = (IdeSlave id) })
279− loadInputs stdout [filename] toline
312+ idris_outputmode = (IdeSlave id h) })
313+ loadInputs [filename] toline
280314 isetPrompt (mkPrompt [filename])
281315 -- Report either success or failure
282316 i <- getIState
@@ -286,45 +320,45 @@ runIdeSlaveCommand id orig fn mods (IdeSlave.LoadFile filename toline) =
286320 (\fc -> IdeSlave.SexpList [IdeSlave.SymbolAtom "ok",
287321 IdeSlave.toSExp fc])
288322 (idris_parsedSpan i)
289− in runIO . putStrLn $ IdeSlave.convSExp "return" msg id
323+ in runIO . hPutStrLn h $ IdeSlave.convSExp "return" msg id
290324 Just x -> iPrintError $ "didn't load " ++ filename
291− ideslave orig [filename]
292−runIdeSlaveCommand id orig fn mods (IdeSlave.TypeOf name) =
325+ ideslave h orig [filename]
326+runIdeSlaveCommand h id orig fn mods (IdeSlave.TypeOf name) =
293327 case splitName name of
294328 Left err -> iPrintError err
295− Right n -> process stdout "(ideslave)"
329+ Right n -> process "(ideslave)"
296330 (Check (PRef (FC "(ideslave)" (0,0) (0,0)) n))
297331 where splitName :: String -> Either String Name
298332 splitName s = case reverse $ splitOn "." s of
299333 [] -> Left ("Didn't understand name '" ++ s ++ "'")
300334 [n] -> Right $ sUN n
301335 (n:ns) -> Right $ sNS (sUN n) ns
302−runIdeSlaveCommand id orig fn mods (IdeSlave.DocsFor name) =
336+runIdeSlaveCommand h id orig fn mods (IdeSlave.DocsFor name) =
303337 case parseConst orig name of
304− Success c -> process stdout "(ideslave)" (DocStr (Right c))
338+ Success c -> process "(ideslave)" (DocStr (Right c))
305339 Failure _ ->
306340 case splitName name of
307341 Left err -> iPrintError err
308− Right n -> process stdout "(ideslave)" (DocStr (Left n))
309−runIdeSlaveCommand id orig fn mods (IdeSlave.CaseSplit line name) =
310− process stdout fn (CaseSplitAt False line (sUN name))
311−runIdeSlaveCommand id orig fn mods (IdeSlave.AddClause line name) =
312− process stdout fn (AddClauseFrom False line (sUN name))
313−runIdeSlaveCommand id orig fn mods (IdeSlave.AddProofClause line name) =
314− process stdout fn (AddProofClauseFrom False line (sUN name))
315−runIdeSlaveCommand id orig fn mods (IdeSlave.AddMissing line name) =
316− process stdout fn (AddMissing False line (sUN name))
317−runIdeSlaveCommand id orig fn mods (IdeSlave.MakeWithBlock line name) =
318− process stdout fn (MakeWith False line (sUN name))
319−runIdeSlaveCommand id orig fn mods (IdeSlave.ProofSearch r line name hints depth) =
320− doProofSearch stdout fn False r line (sUN name) (map sUN hints) depth
321−runIdeSlaveCommand id orig fn mods (IdeSlave.MakeLemma line name) =
342+ Right n -> process "(ideslave)" (DocStr (Left n))
343+runIdeSlaveCommand h id orig fn mods (IdeSlave.CaseSplit line name) =
344+ process fn (CaseSplitAt False line (sUN name))
345+runIdeSlaveCommand h id orig fn mods (IdeSlave.AddClause line name) =
346+ process fn (AddClauseFrom False line (sUN name))
347+runIdeSlaveCommand h id orig fn mods (IdeSlave.AddProofClause line name) =
348+ process fn (AddProofClauseFrom False line (sUN name))
349+runIdeSlaveCommand h id orig fn mods (IdeSlave.AddMissing line name) =
350+ process fn (AddMissing False line (sUN name))
351+runIdeSlaveCommand h id orig fn mods (IdeSlave.MakeWithBlock line name) =
352+ process fn (MakeWith False line (sUN name))
353+runIdeSlaveCommand h id orig fn mods (IdeSlave.ProofSearch r line name hints depth) =
354+ doProofSearch fn False r line (sUN name) (map sUN hints) depth
355+runIdeSlaveCommand h id orig fn mods (IdeSlave.MakeLemma line name) =
322356 case splitName name of
323357 Left err -> iPrintError err
324− Right n -> process stdout fn (MakeLemma False line n)
325−runIdeSlaveCommand id orig fn mods (IdeSlave.Apropos a) =
326− process stdout fn (Apropos a)
327−runIdeSlaveCommand id orig fn mods (IdeSlave.GetOpts) =
358+ Right n -> process fn (MakeLemma False line n)
359+runIdeSlaveCommand h id orig fn mods (IdeSlave.Apropos a) =
360+ process fn (Apropos a)
361+runIdeSlaveCommand h id orig fn mods (IdeSlave.GetOpts) =
328362 do ist <- getIState
329363 let opts = idris_options ist
330364 let impshow = opt_showimp opts
@@ -332,16 +366,16 @@ runIdeSlaveCommand id orig fn mods (IdeSlave.GetOpts) =
332366 let options = (IdeSlave.SymbolAtom "ok",
333367 [(IdeSlave.SymbolAtom "show-implicits", impshow),
334368 (IdeSlave.SymbolAtom "error-context", errCtxt)])
335− runIO . putStrLn $ IdeSlave.convSExp "return" options id
336−runIdeSlaveCommand id orig fn mods (IdeSlave.SetOpt IdeSlave.ShowImpl b) =
369+ runIO . hPutStrLn h $ IdeSlave.convSExp "return" options id
370+runIdeSlaveCommand h id orig fn mods (IdeSlave.SetOpt IdeSlave.ShowImpl b) =
337371 do setImpShow b
338372 let msg = (IdeSlave.SymbolAtom "ok", b)
339− runIO . putStrLn $ IdeSlave.convSExp "return" msg id
340−runIdeSlaveCommand id orig fn mods (IdeSlave.SetOpt IdeSlave.ErrContext b) =
373+ runIO . hPutStrLn h $ IdeSlave.convSExp "return" msg id
374+runIdeSlaveCommand h id orig fn mods (IdeSlave.SetOpt IdeSlave.ErrContext b) =
341375 do setErrContext b
342376 let msg = (IdeSlave.SymbolAtom "ok", b)
343− runIO . putStrLn $ IdeSlave.convSExp "return" msg id
344−runIdeSlaveCommand id orig fn mods (IdeSlave.Metavariables cols) =
377+ runIO . hPutStrLn h $ IdeSlave.convSExp "return" msg id
378+runIdeSlaveCommand h id orig fn mods (IdeSlave.Metavariables cols) =
345379 do ist <- getIState
346380 let mvs = reverse $ map fst (idris_metavars ist) \\ primDefs
347381 let ppo = ppOptionIst ist
@@ -357,7 +391,7 @@ runIdeSlaveCommand id orig fn mods (IdeSlave.Metavariables cols) =
357391 (zip bnds hs),
358392 render ist bnd c pc))
359393 splitMvs
360− runIO . putStrLn $
394+ runIO . hPutStrLn h $
361395 IdeSlave.convSExp "return" (IdeSlave.SymbolAtom "ok", mvOutput) id
362396 where mapPair f g xs = zip (map (f . fst) xs) (map (g . snd) xs)
363397 mapSnd f xs = zip (map fst xs) (map (f . snd) xs)
@@ -402,32 +436,32 @@ runIdeSlaveCommand id orig fn mods (IdeSlave.Metavariables cols) =
402436 let (out, spans) = render ist bnd t pt in
403437 (show n , out, spans)
404438
405−runIdeSlaveCommand id orig fn mods (IdeSlave.WhoCalls n) =
439+runIdeSlaveCommand h id orig fn mods (IdeSlave.WhoCalls n) =
406440 case splitName n of
407441 Left err -> iPrintError err
408442 Right n -> do calls <- whoCalls n
409443 ist <- getIState
410444 let msg = (IdeSlave.SymbolAtom "ok",
411445 map (\ (n,ns) -> (pn ist n, map (pn ist) ns)) calls)
412− runIO . putStrLn $ IdeSlave.convSExp "return" msg id
446+ runIO . hPutStrLn h $ IdeSlave.convSExp "return" msg id
413447 where pn ist = displaySpans .
414448 renderPretty 0.9 1000 .
415449 fmap (fancifyAnnots ist) .
416450 prettyName True True []
417−runIdeSlaveCommand id orig fn mods (IdeSlave.CallsWho n) =
451+runIdeSlaveCommand h id orig fn mods (IdeSlave.CallsWho n) =
418452 case splitName n of
419453 Left err -> iPrintError err
420454 Right n -> do calls <- callsWho n
421455 ist <- getIState
422456 let msg = (IdeSlave.SymbolAtom "ok",
423457 map (\ (n,ns) -> (pn ist n, map (pn ist) ns)) calls)
424− runIO . putStrLn $ IdeSlave.convSExp "return" msg id
458+ runIO . hPutStrLn h $ IdeSlave.convSExp "return" msg id
425459 where pn ist = displaySpans .
426460 renderPretty 0.9 1000 .
427461 fmap (fancifyAnnots ist) .
428462 prettyName True True []
429463
430−runIdeSlaveCommand id orig fn modes (IdeSlave.TermNormalise bnd tm) =
464+runIdeSlaveCommand h id orig fn modes (IdeSlave.TermNormalise bnd tm) =
431465 do ctxt <- getContext
432466 ist <- getIState
433467 let tm' = force (normaliseAll ctxt [] tm)
@@ -441,15 +475,15 @@ runIdeSlaveCommand id orig fn modes (IdeSlave.TermNormalise bnd tm) =
441475 displaySpans .
442476 renderPretty 0.9 80 .
443477 fmap (fancifyAnnots ist) $ ptm)
444− runIO . putStrLn $ IdeSlave.convSExp "return" msg id
445−runIdeSlaveCommand id orig fn modes (IdeSlave.TermShowImplicits bnd tm) =
446− ideSlaveForceTermImplicits id bnd True tm
447−runIdeSlaveCommand id orig fn modes (IdeSlave.TermNoImplicits bnd tm) =
448− ideSlaveForceTermImplicits id bnd False tm
478+ runIO . hPutStrLn h $ IdeSlave.convSExp "return" msg id
479+runIdeSlaveCommand h id orig fn modes (IdeSlave.TermShowImplicits bnd tm) =
480+ ideSlaveForceTermImplicits h id bnd True tm
481+runIdeSlaveCommand h id orig fn modes (IdeSlave.TermNoImplicits bnd tm) =
482+ ideSlaveForceTermImplicits h id bnd False tm
449483
450484-- | Show a term for IDESlave with the specified implicitness
451−ideSlaveForceTermImplicits :: Integer -> [(Name, Bool)] -> Bool -> Term -> Idris ()
452−ideSlaveForceTermImplicits id bnd impl tm =
485+ideSlaveForceTermImplicits :: Handle -> Integer -> [(Name, Bool)] -> Bool -> Term -> Idris ()
486+ideSlaveForceTermImplicits h id bnd impl tm =
453487 do ist <- getIState
454488 let expl = annotate (AnnTerm bnd tm)
455489 (pprintPTerm ((ppOptionIst ist) { ppopt_impl = impl })
@@ -459,7 +493,7 @@ ideSlaveForceTermImplicits id bnd impl tm =
459493 displaySpans .
460494 renderPretty 0.9 80 .
461495 fmap (fancifyAnnots ist) $ expl)
462− runIO . putStrLn $ IdeSlave.convSExp "return" msg id
496+ runIO . hPutStrLn h $ IdeSlave.convSExp "return" msg id
463497
464498splitName :: String -> Either String Name
465499splitName s = case reverse $ splitOn "." s of
@@ -468,70 +502,70 @@ splitName s = case reverse $ splitOn "." s of
468502 (n:ns) -> Right $ sNS (sUN n) ns
469503
470504ideslaveProcess :: FilePath -> Command -> Idris ()
471−ideslaveProcess fn Warranty = process stdout fn Warranty
472−ideslaveProcess fn Help = process stdout fn Help
473−ideslaveProcess fn (ChangeDirectory f) = do process stdout fn (ChangeDirectory f)
505+ideslaveProcess fn Warranty = process fn Warranty
506+ideslaveProcess fn Help = process fn Help
507+ideslaveProcess fn (ChangeDirectory f) = do process fn (ChangeDirectory f)
474508 iPrintResult "changed directory to"
475−ideslaveProcess fn (Eval t) = process stdout fn (Eval t)
476−ideslaveProcess fn (NewDefn decls) = do process stdout fn (NewDefn decls)
509+ideslaveProcess fn (Eval t) = process fn (Eval t)
510+ideslaveProcess fn (NewDefn decls) = do process fn (NewDefn decls)
477511 iPrintResult "defined"
478−ideslaveProcess fn (ExecVal t) = process stdout fn (ExecVal t)
479−ideslaveProcess fn (Check (PRef x n)) = process stdout fn (Check (PRef x n))
480−ideslaveProcess fn (Check t) = process stdout fn (Check t)
481−ideslaveProcess fn (DocStr n) = process stdout fn (DocStr n)
482−ideslaveProcess fn Universes = process stdout fn Universes
483−ideslaveProcess fn (Defn n) = do process stdout fn (Defn n)
512+ideslaveProcess fn (ExecVal t) = process fn (ExecVal t)
513+ideslaveProcess fn (Check (PRef x n)) = process fn (Check (PRef x n))
514+ideslaveProcess fn (Check t) = process fn (Check t)
515+ideslaveProcess fn (DocStr n) = process fn (DocStr n)
516+ideslaveProcess fn Universes = process fn Universes
517+ideslaveProcess fn (Defn n) = do process fn (Defn n)
484518 iPrintResult ""
485−ideslaveProcess fn (TotCheck n) = process stdout fn (TotCheck n)
486−ideslaveProcess fn (DebugInfo n) = do process stdout fn (DebugInfo n)
519+ideslaveProcess fn (TotCheck n) = process fn (TotCheck n)
520+ideslaveProcess fn (DebugInfo n) = do process fn (DebugInfo n)
487521 iPrintResult ""
488−ideslaveProcess fn (Search t) = process stdout fn (Search t)
489−ideslaveProcess fn (Spec t) = process stdout fn (Spec t)
522+ideslaveProcess fn (Search t) = process fn (Search t)
523+ideslaveProcess fn (Spec t) = process fn (Spec t)
490524-- RmProof and AddProof not supported!
491−ideslaveProcess fn (ShowProof n') = process stdout fn (ShowProof n')
492−ideslaveProcess fn (HNF t) = process stdout fn (HNF t)
493−--ideslaveProcess fn TTShell = process stdout fn TTShell -- need some prove mode!
494−ideslaveProcess fn (TestInline t) = process stdout fn (TestInline t)
525+ideslaveProcess fn (ShowProof n') = process fn (ShowProof n')
526+ideslaveProcess fn (HNF t) = process fn (HNF t)
527+--ideslaveProcess fn TTShell = process fn TTShell -- need some prove mode!
528+ideslaveProcess fn (TestInline t) = process fn (TestInline t)
495529
496−ideslaveProcess fn Execute = do process stdout fn Execute
530+ideslaveProcess fn Execute = do process fn Execute
497531 iPrintResult ""
498−ideslaveProcess fn (Compile codegen f) = do process stdout fn (Compile codegen f)
532+ideslaveProcess fn (Compile codegen f) = do process fn (Compile codegen f)
499533 iPrintResult ""
500−ideslaveProcess fn (LogLvl i) = do process stdout fn (LogLvl i)
534+ideslaveProcess fn (LogLvl i) = do process fn (LogLvl i)
501535 iPrintResult ""
502−ideslaveProcess fn (Pattelab t) = process stdout fn (Pattelab t)
503−ideslaveProcess fn (Missing n) = process stdout fn (Missing n)
504−ideslaveProcess fn (DynamicLink l) = do process stdout fn (DynamicLink l)
536+ideslaveProcess fn (Pattelab t) = process fn (Pattelab t)
537+ideslaveProcess fn (Missing n) = process fn (Missing n)
538+ideslaveProcess fn (DynamicLink l) = do process fn (DynamicLink l)
505539 iPrintResult ""
506−ideslaveProcess fn ListDynamic = do process stdout fn ListDynamic
540+ideslaveProcess fn ListDynamic = do process fn ListDynamic
507541 iPrintResult ""
508−ideslaveProcess fn Metavars = process stdout fn Metavars
509−ideslaveProcess fn (SetOpt ErrContext) = do process stdout fn (SetOpt ErrContext)
542+ideslaveProcess fn Metavars = process fn Metavars
543+ideslaveProcess fn (SetOpt ErrContext) = do process fn (SetOpt ErrContext)
510544 iPrintResult ""
511−ideslaveProcess fn (UnsetOpt ErrContext) = do process stdout fn (UnsetOpt ErrContext)
545+ideslaveProcess fn (UnsetOpt ErrContext) = do process fn (UnsetOpt ErrContext)
512546 iPrintResult ""
513−ideslaveProcess fn (SetOpt ShowImpl) = do process stdout fn (SetOpt ShowImpl)
547+ideslaveProcess fn (SetOpt ShowImpl) = do process fn (SetOpt ShowImpl)
514548 iPrintResult ""
515−ideslaveProcess fn (UnsetOpt ShowImpl) = do process stdout fn (UnsetOpt ShowImpl)
549+ideslaveProcess fn (UnsetOpt ShowImpl) = do process fn (UnsetOpt ShowImpl)
516550 iPrintResult ""
517−ideslaveProcess fn (SetOpt ShowOrigErr) = do process stdout fn (SetOpt ShowOrigErr)
551+ideslaveProcess fn (SetOpt ShowOrigErr) = do process fn (SetOpt ShowOrigErr)
518552 iPrintResult ""
519−ideslaveProcess fn (UnsetOpt ShowOrigErr) = do process stdout fn (UnsetOpt ShowOrigErr)
553+ideslaveProcess fn (UnsetOpt ShowOrigErr) = do process fn (UnsetOpt ShowOrigErr)
520554 iPrintResult ""
521−ideslaveProcess fn (SetOpt x) = process stdout fn (SetOpt x)
522−ideslaveProcess fn (UnsetOpt x) = process stdout fn (UnsetOpt x)
523−ideslaveProcess fn (CaseSplitAt False pos str) = process stdout fn (CaseSplitAt False pos str)
524−ideslaveProcess fn (AddProofClauseFrom False pos str) = process stdout fn (AddProofClauseFrom False pos str)
525−ideslaveProcess fn (AddClauseFrom False pos str) = process stdout fn (AddClauseFrom False pos str)
526−ideslaveProcess fn (AddMissing False pos str) = process stdout fn (AddMissing False pos str)
527−ideslaveProcess fn (MakeWith False pos str) = process stdout fn (MakeWith False pos str)
528−ideslaveProcess fn (DoProofSearch False r pos str xs) = process stdout fn (DoProofSearch False r pos str xs)
529−ideslaveProcess fn (SetConsoleWidth w) = do process stdout fn (SetConsoleWidth w)
555+ideslaveProcess fn (SetOpt x) = process fn (SetOpt x)
556+ideslaveProcess fn (UnsetOpt x) = process fn (UnsetOpt x)
557+ideslaveProcess fn (CaseSplitAt False pos str) = process fn (CaseSplitAt False pos str)
558+ideslaveProcess fn (AddProofClauseFrom False pos str) = process fn (AddProofClauseFrom False pos str)
559+ideslaveProcess fn (AddClauseFrom False pos str) = process fn (AddClauseFrom False pos str)
560+ideslaveProcess fn (AddMissing False pos str) = process fn (AddMissing False pos str)
561+ideslaveProcess fn (MakeWith False pos str) = process fn (MakeWith False pos str)
562+ideslaveProcess fn (DoProofSearch False r pos str xs) = process fn (DoProofSearch False r pos str xs)
563+ideslaveProcess fn (SetConsoleWidth w) = do process fn (SetConsoleWidth w)
530564 iPrintResult ""
531−ideslaveProcess fn (Apropos a) = do process stdout fn (Apropos a)
565+ideslaveProcess fn (Apropos a) = do process fn (Apropos a)
532566 iPrintResult ""
533−ideslaveProcess fn (WhoCalls n) = process stdout fn (WhoCalls n)
534−ideslaveProcess fn (CallsWho n) = process stdout fn (CallsWho n)
567+ideslaveProcess fn (WhoCalls n) = process fn (WhoCalls n)
568+ideslaveProcess fn (CallsWho n) = process fn (CallsWho n)
535569ideslaveProcess fn _ = iPrintError "command not recognized or not supported"
536570
537571
@@ -563,18 +597,18 @@ processInput cmd orig inputs
563597 , idris_colourTheme = idris_colourTheme i
564598 }
565599 clearErr
566− mods <- loadInputs stdout inputs Nothing
600+ mods <- loadInputs inputs Nothing
567601 return (Just inputs)
568602 Success (Load f toline) ->
569603 do putIState orig { idris_options = idris_options i
570604 , idris_colourTheme = idris_colourTheme i
571605 }
572606 clearErr
573− mod <- loadInputs stdout [f] toline
607+ mod <- loadInputs [f] toline
574608 return (Just [f])
575609 Success (ModImport f) ->
576610 do clearErr
577− fmod <- loadModule stdout f
611+ fmod <- loadModule f
578612 return (Just (inputs ++ [fmod]))
579613 Success Edit -> do -- takeMVar stvar
580614 edit fn orig
@@ -583,7 +617,7 @@ processInput cmd orig inputs
583617 return (Just inputs)
584618 Success Quit -> do when (not quiet) (iputStrLn "Bye bye")
585619 return Nothing
586− Success cmd -> do idrisCatch (process stdout fn cmd)
620+ Success cmd -> do idrisCatch (process fn cmd)
587621 (\e -> do msg <- showErr e ; iputStrLn msg)
588622 return (Just inputs)
589623
@@ -619,7 +653,7 @@ edit f orig
619653 putIState $ orig { idris_options = idris_options i
620654 , idris_colourTheme = idris_colourTheme i
621655 }
622− loadInputs stdout [f] Nothing
656+ loadInputs [f] Nothing
623657-- clearOrigPats
624658 iucheck
625659 return ()
@@ -645,15 +679,15 @@ insertScript prf (p@"---------- Proofs ----------" : "" : xs)
645679 = p : "" : prf : xs
646680insertScript prf (x : xs) = x : insertScript prf xs
647681
648−process :: Handle -> FilePath -> Command -> Idris ()
649−process h fn Help = iPrintResult displayHelp
650−process h fn Warranty = iPrintResult warranty
651−process h fn (ChangeDirectory f)
682+process :: FilePath -> Command -> Idris ()
683+process fn Help = iPrintResult displayHelp
684+process fn Warranty = iPrintResult warranty
685+process fn (ChangeDirectory f)
652686 = do runIO $ setCurrentDirectory f
653687 return ()
654−process h fn (Eval t)
688+process fn (Eval t)
655689 = withErrorReflection $ do logLvl 5 $ show t
656− (tm, ty) <- elabVal toplevel ERHS t
690+ (tm, ty) <- elabVal recinfo ERHS t
657691 ctxt <- getContext
658692 let tm' = force (normaliseAll ctxt [] tm)
659693 let ty' = force (normaliseAll ctxt [] ty)
@@ -664,10 +698,10 @@ process h fn (Eval t)
664698 logLvl 10 $ "Debug: " ++ showEnvDbg [] tm'
665699 let tmDoc = pprintDelab ist tm'
666700 tyDoc = pprintDelab ist ty'
667− ihPrintTermWithType h tmDoc tyDoc
701+ iPrintTermWithType tmDoc tyDoc
668702
669703
670−process h fn (NewDefn decls) = logLvl 3 ("Defining names using these decls: " ++ show namedGroups) >> mapM_ defineName namedGroups where
704+process fn (NewDefn decls) = logLvl 3 ("Defining names using these decls: " ++ show namedGroups) >> mapM_ defineName namedGroups where
671705 namedGroups = groupBy (\d1 d2 -> getName d1 == getName d2) decls
672706 getName :: PDecl -> Maybe Name
673707 getName (PTy docs argdocs syn fc opts name ty) = Just name
@@ -679,17 +713,17 @@ process h fn (NewDefn decls) = logLvl 3 ("Defining names using these decls: " ++
679713 getClauseName (PWith fc name whole with rhs whereBlock) = name
680714 defineName :: [PDecl] -> Idris ()
681715 defineName (tyDecl@(PTy docs argdocs syn fc opts name ty) : decls) = do
682− elabDecl EAll toplevel tyDecl
683− elabClauses toplevel fc opts name (concatMap getClauses decls)
716+ elabDecl EAll recinfo tyDecl
717+ elabClauses recinfo fc opts name (concatMap getClauses decls)
684718 defineName [PClauses fc opts _ [clause]] = do
685719 let pterm = getRHS clause
686− (tm,ty) <- elabVal toplevel ERHS pterm
720+ (tm,ty) <- elabVal recinfo ERHS pterm
687721 ctxt <- getContext
688722 let tm' = force (normaliseAll ctxt [] tm)
689723 let ty' = force (normaliseAll ctxt [] ty)
690724 updateContext (addCtxtDef (getClauseName clause) (Function ty' tm'))
691725 defineName [PData doc argdocs syn fc opts decl] = do
692− elabData toplevel syn doc argdocs fc opts decl
726+ elabData recinfo syn doc argdocs fc opts decl
693727 getClauses (PClauses fc opts name clauses) = clauses
694728 getClauses _ = []
695729 getRHS :: PClause -> PTerm
@@ -698,28 +732,28 @@ process h fn (NewDefn decls) = logLvl 3 ("Defining names using these decls: " ++
698732 getRHS (PClauseR fc with rhs whereBlock) = rhs
699733 getRHS (PWithR fc with rhs whereBlock) = rhs
700734
701−process h fn (ExecVal t)
735+process fn (ExecVal t)
702736 = do ctxt <- getContext
703737 ist <- getIState
704− (tm, ty) <- elabVal toplevel ERHS t
738+ (tm, ty) <- elabVal recinfo ERHS t
705739-- let tm' = normaliseAll ctxt [] tm
706740 let ty' = normaliseAll ctxt [] ty
707741 res <- execute tm
708742 let (resOut, tyOut) = (prettyIst ist (delab ist res),
709743 prettyIst ist (delab ist ty'))
710− ihPrintTermWithType h resOut tyOut
744+ iPrintTermWithType resOut tyOut
711745
712−process h fn (Check (PRef _ n))
746+process fn (Check (PRef _ n))
713747 = do ctxt <- getContext
714748 ist <- getIState
715749 let ppo = ppOptionIst ist
716750 case lookupNames n ctxt of
717751 ts@(t:_) ->
718752 case lookup t (idris_metavars ist) of
719− Just (_, i, _) -> ihRenderResult h . fmap (fancifyAnnots ist) $
753+ Just (_, i, _) -> iRenderResult . fmap (fancifyAnnots ist) $
720754 showMetavarInfo ppo ist n i
721− Nothing -> ihPrintFunTypes h [] n (map (\n -> (n, delabTy ist n)) ts)
722− [] -> ihPrintError h $ "No such variable " ++ show n
755+ Nothing -> iPrintFunTypes [] n (map (\n -> (n, delabTy ist n)) ts)
756+ [] -> iPrintError $ "No such variable " ++ show n
723757 where
724758 showMetavarInfo ppo ist n i
725759 = case lookupTy n (tt_ctxt ist) of
@@ -744,32 +778,32 @@ process h fn (Check (PRef _ n))
744778 tPretty bnd ist t = pprintPTerm (ppOptionIst ist) bnd [] (idris_infixes ist) t
745779
746780
747−process h fn (Check t)
748− = do (tm, ty) <- elabVal toplevel ERHS t
781+process fn (Check t)
782+ = do (tm, ty) <- elabVal recinfo ERHS t
749783 ctxt <- getContext
750784 ist <- getIState
751785 let ppo = ppOptionIst ist
752786 ty' = normaliseC ctxt [] ty
753787 case tm of
754788 TType _ ->
755− ihPrintTermWithType h (prettyIst ist PType) type1Doc
756− _ -> ihPrintTermWithType h (pprintDelab ist tm)
757− (pprintDelab ist ty)
789+ iPrintTermWithType (prettyIst ist PType) type1Doc
790+ _ -> iPrintTermWithType (pprintDelab ist tm)
791+ (pprintDelab ist ty)
758792
759−process h fn (DocStr (Left n))
793+process fn (DocStr (Left n))
760794 = do ist <- getIState
761795 case lookupCtxtName n (idris_docstrings ist) of
762796 [] -> iPrintError $ "No documentation for " ++ show n
763797 ns -> do toShow <- mapM (showDoc ist) ns
764− ihRenderResult h (vsep toShow)
798+ iRenderResult (vsep toShow)
765799 where showDoc ist (n, d) = do doc <- getDocs n
766800 return $ pprintDocs ist doc
767801
768−process h fn (DocStr (Right c))
802+process fn (DocStr (Right c))
769803 = do ist <- getIState
770− ihRenderResult h $ pprintConstDocs ist c (constDocs c)
804+ iRenderResult $ pprintConstDocs ist c (constDocs c)
771805
772−process h fn Universes
806+process fn Universes
773807 = do i <- getIState
774808 let cs = idris_constraints i
775809-- iputStrLn $ showSep "\n" (map show cs)
@@ -779,7 +813,7 @@ process h fn Universes
779813 case ucheck cs of
780814 Error e -> iPrintError $ pshow i e
781815 OK _ -> iPrintResult "Universes OK"
782−process h fn (Defn n)
816+process fn (Defn n)
783817 = do i <- getIState
784818 iputStrLn "Compiled patterns:\n"
785819 iputStrLn $ show (lookupDef n (tt_ctxt i))
@@ -794,20 +828,20 @@ process h fn (Defn n)
794828 = let i' = i { idris_options = (idris_options i) { opt_showimp = True } }
795829 in iputStrLn (showTm i' (delab i lhs) ++ " = " ++
796830 showTm i' (delab i rhs))
797−process h fn (TotCheck n)
831+process fn (TotCheck n)
798832 = do i <- getIState
799833 case lookupNameTotal n (tt_ctxt i) of
800− [] -> ihPrintError h $ "Unknown operator " ++ show n
834+ [] -> iPrintError $ "Unknown operator " ++ show n
801835 ts -> do ist <- getIState
802836 c <- colourise
803837 let ppo = ppOptionIst ist
804838 let showN = showName (Just ist) [] ppo c
805− ihPrintResult h . concat . intersperse "\n" .
839+ iPrintResult . concat . intersperse "\n" .
806840 map (\(n, t) -> showN n ++ " is " ++ showTotal t i) $
807841 ts
808842
809843
810−process h fn (DebugInfo n)
844+process fn (DebugInfo n)
811845 = do i <- getIState
812846 let oi = lookupCtxtName n (idris_optimisation i)
813847 when (not (null oi)) $ iputStrLn (show oi)
@@ -824,29 +858,29 @@ process h fn (DebugInfo n)
824858 iputStrLn $ "Size change: " ++ show sc
825859 when (not (null cg')) $ do iputStrLn "Call graph:\n"
826860 iputStrLn (show cg')
827−process h fn (Search t) = searchByType h t
828−process h fn (CaseSplitAt updatefile l n)
829− = caseSplitAt h fn updatefile l n
830−process h fn (AddClauseFrom updatefile l n)
831− = addClauseFrom h fn updatefile l n
832−process h fn (AddProofClauseFrom updatefile l n)
833− = addProofClauseFrom h fn updatefile l n
834−process h fn (AddMissing updatefile l n)
835− = addMissing h fn updatefile l n
836−process h fn (MakeWith updatefile l n)
837− = makeWith h fn updatefile l n
838−process h fn (MakeLemma updatefile l n)
839− = makeLemma h fn updatefile l n
840−process h fn (DoProofSearch updatefile rec l n hints)
841− = doProofSearch h fn updatefile rec l n hints Nothing
842−process h fn (Spec t)
843− = do (tm, ty) <- elabVal toplevel ERHS t
861+process fn (Search t) = searchByType t
862+process fn (CaseSplitAt updatefile l n)
863+ = caseSplitAt fn updatefile l n
864+process fn (AddClauseFrom updatefile l n)
865+ = addClauseFrom fn updatefile l n
866+process fn (AddProofClauseFrom updatefile l n)
867+ = addProofClauseFrom fn updatefile l n
868+process fn (AddMissing updatefile l n)
869+ = addMissing fn updatefile l n
870+process fn (MakeWith updatefile l n)
871+ = makeWith fn updatefile l n
872+process fn (MakeLemma updatefile l n)
873+ = makeLemma fn updatefile l n
874+process fn (DoProofSearch updatefile rec l n hints)
875+ = doProofSearch fn updatefile rec l n hints Nothing
876+process fn (Spec t)
877+ = do (tm, ty) <- elabVal recinfo ERHS t
844878 ctxt <- getContext
845879 ist <- getIState
846880 let tm' = simplify ctxt [] {- (idris_statics ist) -} tm
847881 iPrintResult (show (delab ist tm'))
848882
849−process h fn (RmProof n')
883+process fn (RmProof n')
850884 = do i <- getIState
851885 n <- resolveProof n'
852886 let proofs = proof_list i
@@ -862,7 +896,7 @@ process h fn (RmProof n')
862896 let ms = idris_metavars i
863897 putIState $ i { idris_metavars = (n, (Nothing, 0, False)) : ms }
864898
865−process h fn' (AddProof prf)
899+process fn' (AddProof prf)
866900 = do fn <- do
867901 let fn'' = takeWhile (/= ' ') fn'
868902 ex <- runIO $ doesFileExist fn''
@@ -892,7 +926,7 @@ process h fn' (AddProof prf)
892926 iputStrLn $ "Added proof " ++ show n
893927 where ls = (lines prog)
894928
895−process h fn (ShowProof n')
929+process fn (ShowProof n')
896930 = do i <- getIState
897931 n <- resolveProof n'
898932 let proofs = proof_list i
@@ -900,7 +934,7 @@ process h fn (ShowProof n')
900934 Nothing -> iPrintError "No proof to show"
901935 Just p -> iPrintResult $ showProof False n p
902936
903−process h fn (Prove n')
937+process fn (Prove n')
904938 = do ctxt <- getContext
905939 ist <- getIState
906940 let ns = lookupNames n' ctxt
@@ -918,23 +952,23 @@ process h fn (Prove n')
918952 mapM_ checkDeclTotality (idris_totcheck i)
919953 warnTotality
920954
921−process h fn (HNF t)
922− = do (tm, ty) <- elabVal toplevel ERHS t
955+process fn (HNF t)
956+ = do (tm, ty) <- elabVal recinfo ERHS t
923957 ctxt <- getContext
924958 ist <- getIState
925959 let tm' = hnf ctxt [] tm
926960 iPrintResult (show (delab ist tm'))
927−process h fn (TestInline t)
928− = do (tm, ty) <- elabVal toplevel ERHS t
961+process fn (TestInline t)
962+ = do (tm, ty) <- elabVal recinfo ERHS t
929963 ctxt <- getContext
930964 ist <- getIState
931965 let tm' = inlineTerm ist tm
932966 c <- colourise
933967 iPrintResult (showTm ist (delab ist tm'))
934−process h fn Execute
968+process fn Execute
935969 = idrisCatch
936970 (do ist <- getIState
937− (m, _) <- elabVal toplevel ERHS
971+ (m, _) <- elabVal recinfo ERHS
938972 (PApp fc
939973 (PRef fc (sUN "run__IO"))
940974 [pexp $ PRef fc (sNS (sUN "main") ["Main"])])
@@ -943,33 +977,33 @@ process h fn Execute
943977 t <- codegen
944978 compile t tmpn m
945979 case idris_outputmode ist of
946− RawOutput -> do runIO $ system tmpn
947− return ()
948− IdeSlave n -> runIO . hPutStrLn h $
949− IdeSlave.convSExp "run-program" tmpn n)
950− (\e -> getIState >>= ihRenderError stdout . flip pprintErr e)
980+ RawOutput h -> do runIO $ system tmpn
981+ return ()
982+ IdeSlave n h -> runIO . hPutStrLn h $
983+ IdeSlave.convSExp "run-program" tmpn n)
984+ (\e -> getIState >>= iRenderError . flip pprintErr e)
951985 where fc = fileFC "main"
952−process h fn (Compile codegen f)
953− = do (m, _) <- elabVal toplevel ERHS
986+process fn (Compile codegen f)
987+ = do (m, _) <- elabVal recinfo ERHS
954988 (PApp fc (PRef fc (sUN "run__IO"))
955989 [pexp $ PRef fc (sNS (sUN "main") ["Main"])])
956990 compile codegen f m
957991 where fc = fileFC "main"
958−process h fn (LogLvl i) = setLogLevel i
992+process fn (LogLvl i) = setLogLevel i
959993-- Elaborate as if LHS of a pattern (debug command)
960−process h fn (Pattelab t)
961− = do (tm, ty) <- elabVal toplevel ELHS t
994+process fn (Pattelab t)
995+ = do (tm, ty) <- elabVal recinfo ELHS t
962996 iPrintResult $ show tm ++ "\n\n : " ++ show ty
963997
964−process h fn (Missing n)
998+process fn (Missing n)
965999 = do i <- getIState
9661000 let i' = i { idris_options = (idris_options i) { opt_showimp = True } }
9671001 case lookupCtxt n (idris_patdefs i) of
968− [] -> ihPrintError h $ "Unknown operator " ++ show n
1002+ [] -> iPrintError $ "Unknown operator " ++ show n
9691003 [(_, tms)] ->
9701004 iPrintResult (showSep "\n" (map (showTm i') tms))
9711005 _ -> iPrintError $ "Ambiguous name"
972−process h fn (DynamicLink l)
1006+process fn (DynamicLink l)
9731007 = do i <- getIState
9741008 let importdirs = opt_importdirs (idris_options i)
9751009 lib = trim l
@@ -982,80 +1016,80 @@ process h fn (DynamicLink l)
9821016 return ()
9831017 else putIState $ i { idris_dynamic_libs = x:libs }
9841018 where trim = reverse . dropWhile isSpace . reverse . dropWhile isSpace
985−process h fn ListDynamic
1019+process fn ListDynamic
9861020 = do i <- getIState
9871021 iputStrLn "Dynamic libraries:"
9881022 showLibs $ idris_dynamic_libs i
9891023 where showLibs [] = return ()
9901024 showLibs ((Lib name _):ls) = do iputStrLn $ "\t" ++ name; showLibs ls
991−process h fn Metavars
1025+process fn Metavars
9921026 = do ist <- getIState
9931027 let mvs = map fst (idris_metavars ist) \\ primDefs
9941028 case mvs of
9951029 [] -> iPrintError "No global metavariables to solve"
9961030 _ -> iPrintResult $ "Global metavariables:\n\t" ++ show mvs
997−process h fn NOP = return ()
998−
999−process h fn (SetOpt ErrContext) = setErrContext True
1000−process h fn (UnsetOpt ErrContext) = setErrContext False
1001−process h fn (SetOpt ShowImpl) = setImpShow True
1002−process h fn (UnsetOpt ShowImpl) = setImpShow False
1003−process h fn (SetOpt ShowOrigErr) = setShowOrigErr True
1004−process h fn (UnsetOpt ShowOrigErr) = setShowOrigErr False
1005−process h fn (SetOpt AutoSolve) = setAutoSolve True
1006−process h fn (UnsetOpt AutoSolve) = setAutoSolve False
1007−process h fn (SetOpt NoBanner) = setNoBanner True
1008−process h fn (UnsetOpt NoBanner) = setNoBanner False
1009−process h fn (SetOpt WarnReach) = fmodifyState opts_idrisCmdline $ nub . (WarnReach:)
1010−process h fn (UnsetOpt WarnReach) = fmodifyState opts_idrisCmdline $ delete WarnReach
1011−
1012−process h fn (SetOpt _) = iPrintError "Not a valid option"
1013−process h fn (UnsetOpt _) = iPrintError "Not a valid option"
1014−process h fn (SetColour ty c) = setColour ty c
1015−process h fn ColourOn
1031+process fn NOP = return ()
1032+
1033+process fn (SetOpt ErrContext) = setErrContext True
1034+process fn (UnsetOpt ErrContext) = setErrContext False
1035+process fn (SetOpt ShowImpl) = setImpShow True
1036+process fn (UnsetOpt ShowImpl) = setImpShow False
1037+process fn (SetOpt ShowOrigErr) = setShowOrigErr True
1038+process fn (UnsetOpt ShowOrigErr) = setShowOrigErr False
1039+process fn (SetOpt AutoSolve) = setAutoSolve True
1040+process fn (UnsetOpt AutoSolve) = setAutoSolve False
1041+process fn (SetOpt NoBanner) = setNoBanner True
1042+process fn (UnsetOpt NoBanner) = setNoBanner False
1043+process fn (SetOpt WarnReach) = fmodifyState opts_idrisCmdline $ nub . (WarnReach:)
1044+process fn (UnsetOpt WarnReach) = fmodifyState opts_idrisCmdline $ delete WarnReach
1045+
1046+process fn (SetOpt _) = iPrintError "Not a valid option"
1047+process fn (UnsetOpt _) = iPrintError "Not a valid option"
1048+process fn (SetColour ty c) = setColour ty c
1049+process fn ColourOn
10161050 = do ist <- getIState
10171051 putIState $ ist { idris_colourRepl = True }
1018−process h fn ColourOff
1052+process fn ColourOff
10191053 = do ist <- getIState
10201054 putIState $ ist { idris_colourRepl = False }
1021−process h fn ListErrorHandlers =
1055+process fn ListErrorHandlers =
10221056 do ist <- getIState
10231057 iPrintResult $ case idris_errorhandlers ist of
10241058 [] -> "No registered error handlers"
10251059 handlers -> "Registered error handlers: " ++ (concat . intersperse ", " . map show) handlers
1026−process h fn (SetConsoleWidth w) = setWidth w
1060+process fn (SetConsoleWidth w) = setWidth w
10271061
1028−process h fn (Apropos a) =
1062+process fn (Apropos a) =
10291063 do ist <- getIState
10301064 let names = apropos ist (T.pack a)
10311065 let aproposInfo = [ (n,
10321066 delabTy ist n,
10331067 fmap (overview . fst) (lookupCtxtExact n (idris_docstrings ist)))
10341068 | n <- sort names, isUN n ]
1035− ihRenderResult h $ vsep (map (prettyDocumentedIst ist) aproposInfo)
1069+ iRenderResult $ vsep (map (prettyDocumentedIst ist) aproposInfo)
10361070 where isUN (UN _) = True
10371071 isUN (NS n _) = isUN n
10381072 isUN _ = False
10391073
1040−process h fn (WhoCalls n) =
1074+process fn (WhoCalls n) =
10411075 do calls <- whoCalls n
10421076 ist <- getIState
1043− ihRenderResult h . vsep $
1077+ iRenderResult . vsep $
10441078 map (\(n, ns) ->
10451079 text "Callers of" <+> prettyName True True [] n <$>
10461080 indent 1 (vsep (map ((text "*" <+>) . align . prettyName True True []) ns)))
10471081 calls
10481082
1049−process h fn (CallsWho n) =
1083+process fn (CallsWho n) =
10501084 do calls <- callsWho n
10511085 ist <- getIState
1052− ihRenderResult h . vsep $
1086+ iRenderResult . vsep $
10531087 map (\(n, ns) ->
10541088 prettyName True True [] n <+> text "calls:" <$>
10551089 indent 1 (vsep (map ((text "*" <+>) . align . prettyName True True []) ns)))
10561090 calls
10571091-- IdrisDoc
1058−process h fn (MakeDoc s) =
1092+process fn (MakeDoc s) =
10591093 do istate <- getIState
10601094 let names = words s
10611095 parse n | Success x <- runparser name istate fn n = Right x
@@ -1112,8 +1146,8 @@ idris opts = do res <- runErrorT $ execStateT totalMain idrisInit
11121146 [] -> return ()
11131147
11141148
1115−loadInputs :: Handle -> [FilePath] -> Maybe Int -> Idris ()
1116−loadInputs h inputs toline -- furthest line to read in input source files
1149+loadInputs :: [FilePath] -> Maybe Int -> Idris ()
1150+loadInputs inputs toline -- furthest line to read in input source files
11171151 = idrisCatch
11181152 (do ist <- getIState
11191153 -- if we're in --check and not outputting anything, don't bother
@@ -1165,10 +1199,10 @@ loadInputs h inputs toline -- furthest line to read in input source files
11651199 (\e -> do i <- getIState
11661200 case e of
11671201 At f e' -> do setErrSpan f
1168− ihWarn stdout f $ pprintErr i e'
1202+ iWarn f $ pprintErr i e'
11691203 ProgramLineComment -> return () -- fail elsewhere
11701204 _ -> do setErrSpan emptyFC -- FIXME! Propagate it
1171− ihWarn stdout emptyFC $ pprintErr i e)
1205+ iWarn emptyFC $ pprintErr i e)
11721206 where -- load all files, stop if any fail
11731207 tryLoad :: Bool -> [IFileType] -> Idris ()
11741208 tryLoad keepstate [] = warnTotality >> return ()
@@ -1185,7 +1219,7 @@ loadInputs h inputs toline -- furthest line to read in input source files
11851219 then Just l
11861220 else Nothing
11871221 _ -> Nothing
1188− loadFromIFile h f maxline
1222+ loadFromIFile f maxline
11891223 inew <- getIState
11901224 -- FIXME: Save these in IBC to avoid this hack! Need to
11911225 -- preserve it all from source inputs
@@ -1233,7 +1267,7 @@ idrisMain opts =
12331267 do let inputs = opt getFile opts
12341268 let quiet = Quiet `elem` opts
12351269 let nobanner = NoBanner `elem` opts
1236− let idesl = Ideslave `elem` opts
1270+ let idesl = Ideslave `elem` opts || IdeslaveSocket `elem` opts
12371271 let runrepl = not (NoREPL `elem` opts)
12381272 let verbose = runrepl || Verbose `elem` opts
12391273 let output = opt getOutput opts
@@ -1270,7 +1304,6 @@ idrisMain opts =
12701304 mapM_ addLangExt (opt getLanguageExt opts)
12711305 setREPL runrepl
12721306 setQuiet (quiet || isJust script || not (null immediate))
1273− setIdeSlave idesl
12741307 setVerbose verbose
12751308 setCmdLine opts
12761309 setOutputTy outty
@@ -1296,9 +1329,9 @@ idrisMain opts =
12961329 addPkgDir "base"
12971330 mapM_ addPkgDir pkgdirs
12981331 elabPrims
1299− when (not (NoBuiltins `elem` opts)) $ do x <- loadModule stdout "Builtins"
1332+ when (not (NoBuiltins `elem` opts)) $ do x <- loadModule "Builtins"
13001333 return ()
1301− when (not (NoPrelude `elem` opts)) $ do x <- loadModule stdout "Prelude"
1334+ when (not (NoPrelude `elem` opts)) $ do x <- loadModule "Prelude"
13021335 return ()
13031336
13041337 when (runrepl && not idesl) initScript
@@ -1314,14 +1347,14 @@ idrisMain opts =
13141347 iputStrLn banner
13151348
13161349 orig <- getIState
1317− loadInputs stdout inputs Nothing
1350+ when (not idesl) $ loadInputs inputs Nothing
13181351
13191352 runIO $ hSetBuffering stdout LineBuffering
13201353
13211354 ok <- noErrors
13221355 when ok $ case output of
13231356 [] -> return ()
1324− (o:_) -> idrisCatch (process stdout "" (Compile cgn o))
1357+ (o:_) -> idrisCatch (process "" (Compile cgn o))
13251358 (\e -> do ist <- getIState ; iputStrLn $ pshow ist e)
13261359
13271360 case immediate of
@@ -1332,7 +1365,7 @@ idrisMain opts =
13321365 case parseExpr ist str of
13331366 Failure err -> do iputStrLn $ show (fixColour c err)
13341367 runIO $ exitWith (ExitFailure 1)
1335− Success e -> process stdout "" (Eval e))
1368+ Success e -> process "" (Eval e))
13361369 exprs
13371370 runIO $ exitWith ExitSuccess
13381371
@@ -1354,7 +1387,8 @@ idrisMain opts =
13541387-- clearOrigPats
13551388 startServer orig inputs
13561389 runInputT (replSettings (Just historyFile)) $ repl orig inputs
1357− when (idesl) $ ideslaveStart orig inputs
1390+ let idesock = IdeslaveSocket `elem` opts
1391+ when (idesl) $ ideslaveStart idesock orig inputs
13581392 ok <- noErrors
13591393 when (not ok) $ runIO (exitWith (ExitFailure 1))
13601394 where
@@ -1376,7 +1410,7 @@ execScript expr = do i <- getIState
13761410 Failure err -> do iputStrLn $ show (fixColour c err)
13771411 runIO $ exitWith (ExitFailure 1)
13781412 Success term -> do ctxt <- getContext
1379− (tm, _) <- elabVal toplevel ERHS term
1413+ (tm, _) <- elabVal recinfo ERHS term
13801414 res <- execute tm
13811415 runIO $ exitWith ExitSuccess
13821416
@@ -1416,7 +1450,7 @@ initScript = do script <- getInitScript
14161450 Success Edit -> iPrintError "Init scripts cannot invoke the editor"
14171451 Success Proofs -> proofs i
14181452 Success Quit -> iPrintError "Init scripts cannot quit Idris"
1419− Success cmd -> process stdout [] cmd
1453+ Success cmd -> process [] cmd
14201454
14211455getFile :: Opt -> Maybe String
14221456getFile (Filename str) = Just str
src/Idris/TypeSearch.hs+8−10
@@ -28,20 +28,18 @@ import Idris.Core.TT hiding (score)
2828import Idris.Core.Unify (match_unify)
2929import Idris.Delaborate (delabTy)
3030import Idris.Docstrings (noDocs, overview)
31−import Idris.ElabDecls (elabType')
32−import Idris.Output (ihRenderOutput, ihPrintResult, ihRenderResult)
33−
34−import System.IO (Handle)
31+import Idris.Elab.Type (elabType)
32+import Idris.Output (iRenderOutput, iPrintResult, iRenderResult)
3533
3634import Util.Pretty (text, char, vsep, (<>), Doc)
3735
38−searchByType :: Handle -> PTerm -> Idris ()
39−searchByType h pterm = do
36+searchByType :: PTerm -> Idris ()
37+searchByType pterm = do
4038 pterm' <- addUsingConstraints syn emptyFC pterm
4139 pterm'' <- implicit toplevel syn n pterm'
4240 i <- getIState
4341 let pterm''' = addImpl i pterm''
44− ty <- elabType' False toplevel syn (fst noDocs) (snd noDocs) emptyFC [] n pterm'
42+ ty <- elabType toplevel syn (fst noDocs) (snd noDocs) emptyFC [] n pterm'
4543 putIState i -- don't actually make any changes
4644 let names = searchUsing searchPred i ty
4745 let names' = take numLimit $ names
@@ -50,9 +48,9 @@ searchByType h pterm = do
5048 displayScore score <> char ' ' <> prettyDocumentedIst i docInfo
5149 | (n, score) <- names']
5250 case idris_outputmode i of
53− RawOutput -> do mapM_ (ihRenderOutput h) docs
54− ihPrintResult h ""
55− IdeSlave n -> ihRenderResult h (vsep docs)
51+ RawOutput _ -> do mapM_ iRenderOutput docs
52+ iPrintResult ""
53+ IdeSlave n h -> iRenderResult (vsep docs)
5654 where
5755 numLimit = 50
5856 syn = defaultSyntax { implicitAllowed = True } -- syntax
src/Pkg/Package.hs+1−1
@@ -144,7 +144,7 @@ documentPkg fp =
144144 setCurrentDirectory $ pkgDir
145145 let run l = runErrorT . (execStateT l)
146146 load [] = return ()
147− load (f:fs) = do loadModule stdout f; load fs
147+ load (f:fs) = do loadModule f; load fs
148148 loader = do idrisMain opts; load fs
149149 idrisInstance <- run loader idrisInit
150150 setCurrentDirectory cd
src/Util/Net.hs+15−2
@@ -1,6 +1,6 @@
1−module Util.Net (listenOnLocalhost) where
1+module Util.Net (listenOnLocalhost, listenOnLocalhostAnyPort) where
22
3−import Network
3+import Network hiding (socketPort)
44import Network.Socket hiding (sClose, PortNumber)
55import Network.BSD (getProtocolNumber)
66import Control.Exception (bracketOnError)
@@ -20,3 +20,16 @@ listenOnLocalhost (PortNumber port) = do
2020 return sock
2121 )
2222
23+listenOnLocalhostAnyPort = do
24+ proto <- getProtocolNumber "tcp"
25+ localhost <- inet_addr "127.0.0.1"
26+ bracketOnError
27+ (socket AF_INET Stream proto)
28+ (sClose)
29+ (\sock -> do
30+ setSocketOption sock ReuseAddr 1
31+ bindSocket sock (SockAddrInet aNY_PORT localhost)
32+ listen sock maxListenQueue
33+ port <- socketPort sock
34+ return (sock, port)
35+ )
test/proof007/DefaultArgUnknownName.idr+7−1
@@ -1,4 +1,10 @@
11module DefaultArgUnknownName
22
3+-- FIXME: What is the expected behaviour here? Should the type declaration
4+-- not compile?
35funWithBadDefArg : { default sadgjhsag arg : () } -> ()
4−funWithBadDefArg : _ = ()
6+funWithBadDefArg = ()
7+
8+test : ()
9+test = funWithBadDefArg
10+
test/proof007/expected+3−2
@@ -1,2 +1,3 @@
1−DefaultArgUnknownName.idr:3:18:When elaborating type of DefaultArgUnknownName.funWithBadDefArg:
2−Can't infer type for sadgjhsag
1+DefaultArgUnknownName.idr:5:30:When elaborating right hand side of test:
2+When elaborating argument arg to function DefaultArgUnknownName.funWithBadDefArg:
3+ No such variable sadgjhsag
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+