@@ -16,17 +16,6 @@ Based on <http://www.cs.ru.nl/~freek/courses/tt-2014/read/10.1.1.61.3041.pdf> .
16
16
17
17
open Lean Parser.Tactic Elab Command Elab.Tactic Meta
18
18
19
- open Expr in
20
- private def getAppFnAndArgsAux : Expr → Array Expr → Nat → Option (Name × Array Expr)
21
- | app f a _, as, i => getAppFnAndArgsAux f (as.set! i a) (i-1 )
22
- | const n _ _, as, i => some (n,as)
23
- | _, as, _ => none
24
-
25
- def Lean.Expr.getAppFnAndArgs (e : Expr) : Option (Name × Array Expr) :=
26
- let dummy := mkSort levelZero
27
- let nargs := e.getAppNumArgs
28
- getAppFnAndArgsAux e (mkArray nargs dummy) (nargs-1 )
29
-
30
19
namespace Tactic
31
20
namespace Ring
32
21
@@ -41,10 +30,9 @@ structure State :=
41
30
42
31
/-- The monad that `ring` works in. This is a reader monad containing a cache and
43
32
the list of atoms-up-to-defeq encountered thus far, used for atom sorting. -/
44
- abbrev RingM := ReaderT Cache $ StateRefT State TacticM
33
+ abbrev RingM := ReaderT Cache $ StateRefT State MetaM
45
34
46
- def run (e : Expr) {α} (m : RingM α): TacticM α := do
47
- let ty ← inferType e
35
+ def RingM.run (ty : Expr) (m : RingM α) : MetaM α := do
48
36
let u ← getLevel ty
49
37
(m {α := ty, univ := u}).run' {}
50
38
@@ -115,7 +103,7 @@ def xadd' (a : HornerExpr) (x : Expr × ℕ) (n : Expr × ℕ) (b : HornerExpr)
115
103
def reflConv (e : HornerExpr) : RingM (HornerExpr × Expr) := do (e, ← mkEqRefl e)
116
104
117
105
/-- Pretty printer for `horner_expr`. -/
118
- def pp : HornerExpr → TacticM Format
106
+ def pp : HornerExpr → MetaM Format
119
107
| (const e c) => do
120
108
let pe ← PrettyPrinter.ppExpr Name.anonymous [] e
121
109
return "[" ++ pe ++ ", " ++ toString c ++ "]"
@@ -343,27 +331,27 @@ partial def evalPow : HornerExpr → Expr × ℕ → RingM (HornerExpr × Expr)
343
331
| e, (_, 0 ) => do
344
332
let α1 ← mkAppOptM ``OfNat.ofNat #[(← read).α, mkRawNatLit 1 , none]
345
333
let p ← mkAppM ``pow_zero #[e]
346
- return (const α1 1 , p)
334
+ (const α1 1 , p)
347
335
| e, (_, 1 ) => do
348
336
let p ← mkAppM ``pow_one #[e]
349
- return (e, p)
350
- | ( const e coeff) , (e₂, m) => do
337
+ (e, p)
338
+ | const e coeff, (e₂, m) => do
351
339
let (e', p) ← NormNum.eval $ ← mkAppM ``HPow.hPow #[e, e₂]
352
- return (const e' (coeff ^ m), p)
340
+ (const e' (coeff ^ m), p)
353
341
| he@(xadd e a x n b), m =>
354
342
match b.e.numeral? with
355
343
| some 0 => do
356
344
let n' ← mkRawNatLit (n.2 * m.2 )
357
345
let h₁ ← mkEqRefl n'
358
346
let (a', h₂) ← evalPow a m
359
347
let α0 ← mkAppOptM ``OfNat.ofNat #[(← read).α, mkRawNatLit 0 , none]
360
- return (← xadd' a' x (n', n.2 * m.2 ) (const α0 0 ),
348
+ (← xadd' a' x (n', n.2 * m.2 ) (const α0 0 ),
361
349
← mkAppM ``horner_pow #[a, x.1 , n.1 , m.1 , n', a', h₁, h₂])
362
350
| _ => do
363
351
let e₂ ← mkRawNatLit (m.2 - 1 )
364
352
let (tl, hl) ← evalPow he (e₂, m.2-1 )
365
353
let (t, p₂) ← evalMul tl he
366
- return (t, ← mkAppM ``pow_succ_eq #[e, e₂, tl, t, hl, p₂])
354
+ (t, ← mkAppM ``pow_succ_eq #[e, e₂, tl, t, hl, p₂])
367
355
368
356
369
357
theorem horner_atom {α} [CommSemiring α] (x : α) : x = horner 1 x 1 0 := by
@@ -374,8 +362,7 @@ def evalAtom (e : Expr) : RingM (HornerExpr × Expr) := do
374
362
let i ← addAtom e
375
363
let zero ← const (← mkAppOptM ``OfNat.ofNat #[(← read).α, mkRawNatLit 0 , none]) 0
376
364
let one ← const (← mkAppOptM ``OfNat.ofNat #[(← read).α, mkRawNatLit 1 , none]) 1
377
- return (← xadd' one (e,i) (mkRawNatLit 1 ,1 ) zero, ← mkAppM ``horner_atom #[e])
378
-
365
+ (← xadd' one (e,i) (mkRawNatLit 1 ,1 ) zero, ← mkAppM ``horner_atom #[e])
379
366
380
367
theorem subst_into_add {α} [Add α] (l r tl tr t)
381
368
(prl : (l : α) = tl) (prr : r = tr) (prt : tl + tr = t) : l + r = t :=
@@ -390,20 +377,20 @@ theorem subst_into_pow {α} [Monoid α] (l r tl tr t)
390
377
by rw [prl, prr, prt]
391
378
392
379
partial def eval (e : Expr) : RingM (HornerExpr × Expr) :=
393
- match e.getAppFnAndArgs with
394
- | some (``HAdd.hAdd, #[_,_,_,_,e₁,e₂]) => do
380
+ match e.getAppFnArgs with
381
+ | (``HAdd.hAdd, #[_,_,_,_,e₁,e₂]) => do
395
382
let (e₁', p₁) ← eval e₁
396
383
let (e₂', p₂) ← eval e₂
397
384
let (e', p') ← evalAdd e₁' e₂'
398
385
let p ← mkAppM ``subst_into_add #[e₁, e₂, e₁', e₂', e', p₁, p₂, p']
399
386
(e',p)
400
- | some (``HMul.hMul, #[_,_,_,_,e₁,e₂]) => do
387
+ | (``HMul.hMul, #[_,_,_,_,e₁,e₂]) => do
401
388
let (e₁', p₁) ← eval e₁
402
389
let (e₂', p₂) ← eval e₂
403
390
let (e', p') ← evalMul e₁' e₂'
404
391
let p ← mkAppM ``subst_into_mul #[e₁, e₂, e₁', e₂', e', p₁, p₂, p']
405
392
return (e', p)
406
- | some (``HPow.hPow, #[_,_,_,P,e₁,e₂]) => do
393
+ | (``HPow.hPow, #[_,_,_,P,e₁,e₂]) => do
407
394
-- let (e₂', p₂) ← lift $ norm_num.derive e₂ <|> refl_conv e₂,
408
395
let (e₂', p₂) ← (e₂, ← mkEqRefl e₂)
409
396
match e₂'.numeral?, P.getAppFn with
@@ -412,24 +399,21 @@ partial def eval (e : Expr) : RingM (HornerExpr × Expr) :=
412
399
let (e', p') ← evalPow e₁' (e₂, k)
413
400
let p ← mkAppM ``subst_into_pow #[e₁, e₂, e₁', e₂', e', p₁, p₂, p']
414
401
return (e', p)
415
- | _, _ => do ← evalAtom e
416
- evalAtom e
402
+ | _, _ => evalAtom e
417
403
| _ =>
418
404
match e.numeral? with
419
405
| some n => (const e n).reflConv
420
- | _ => (evalAtom e)
421
-
406
+ | _ => evalAtom e
422
407
423
408
elab "ring" : tactic => do
424
409
let g ← getMainTarget
425
- match g.getAppFnAndArgs with
426
- | some (`Eq, #[ty, e₁, e₂]) =>
427
- let ((e₁', p₁), (e₂', p₂)) ← run e₁ $ Prod.mk <$> eval e₁ <*> eval e₂
428
- if ( ← isDefEq e₁' e₂') then
410
+ match g.getAppFnArgs with
411
+ | (`Eq, #[ty, e₁, e₂]) =>
412
+ let ((e₁', p₁), (e₂', p₂)) ← RingM. run ty $ do (← eval e₁, ← eval e₂)
413
+ if ← isDefEq e₁' e₂' then
429
414
let p ← mkEqTrans p₁ (← mkEqSymm p₂)
430
415
ensureHasNoMVars p
431
416
assignExprMVar (← getMainGoal) p
432
-
433
417
replaceMainGoal []
434
418
else
435
419
throwError "failed \n {← e₁'.pp}\n {← e₂'.pp}"
0 commit comments