@@ -109,28 +109,41 @@ theorem isInt_add {α} [Ring α] : {a b : α} → {a' b' c : ℤ} →
109
109
IsInt a a' → IsInt b b' → Int.add a' b' = c → IsInt (a + b) c
110
110
| _, _, _, _, _, ⟨rfl⟩, ⟨rfl⟩, rfl => ⟨(Int.cast_add ..).symm⟩
111
111
112
+ instance : MonadLift Option MetaM where
113
+ monadLift
114
+ | none => failure
115
+ | some e => pure e
116
+
112
117
/-- The `norm_num` extension which identifies expressions of the form `a + b`,
113
118
such that `norm_num` successfully recognises both `a` and `b`. -/
114
119
@[norm_num _ + _, Add.add _ _] def evalAdd : NormNumExt where eval {u α} e := do
115
120
let .app (.app f (a : Q($α))) (b : Q($α)) ← withReducible (whnf e) | failure
116
121
let ra ← derive a; let rb ← derive b
117
- let intArm (rα : Q(Ring $α)) := do
118
- let ⟨za, na, pa⟩ ← ra.toInt; let ⟨zb, nb, pb⟩ ← rb.toInt
119
- let zc := za + zb
120
- have c := mkRawIntLit zc
121
- let r : Q(Int.add $na $nb = $c) := (q(Eq.refl $c) : Expr)
122
- return (.isInt rα zc q(isInt_add $pa $pb $r) : Result q($a + $b))
123
122
match ra, rb with
124
- | .isNat _ na pa , .isNat sα nb pb =>
125
- have pa : Q(IsNat $a $na) := pa
123
+ | .isNat _ .. , .isNat _ .. | .isNat _ .., .isNegNat _ ..
124
+ | .isNegNat _ .., .isNat _ .. | .isNegNat _ .., .isNegNat _ .. =>
126
125
guard <|← withNewMCtxDepth <| isDefEq f q(HAdd.hAdd (α := $α))
127
- have c : Q(ℕ) := mkRawNatLit (na.natLit! + nb.natLit!)
128
- let r : Q(Nat.add $na $nb = $c) := (q(Eq.refl $c) : Expr)
129
- return (.isNat sα c q(isNat_add $pa $pb $r) : Result q($a + $b))
130
- | .isNat _ .., .isNegNat rα ..
131
- | .isNegNat rα .., .isNat _ ..
132
- | .isNegNat _ .., .isNegNat rα .. => intArm rα
133
126
| _, _ => failure
127
+ let rec
128
+ /-- Main part of `evalAdd`. -/
129
+ core : Option (Result e) := do
130
+ let intArm (rα : Q(Ring $α)) := do
131
+ let ⟨za, na, pa⟩ ← ra.toInt; let ⟨zb, nb, pb⟩ ← rb.toInt
132
+ let zc := za + zb
133
+ have c := mkRawIntLit zc
134
+ let r : Q(Int.add $na $nb = $c) := (q(Eq.refl $c) : Expr)
135
+ return (.isInt rα zc q(isInt_add $pa $pb $r) : Result q($a + $b))
136
+ match ra, rb with
137
+ | .isNat _ na pa, .isNat sα nb pb =>
138
+ have pa : Q(IsNat $a $na) := pa
139
+ have c : Q(ℕ) := mkRawNatLit (na.natLit! + nb.natLit!)
140
+ let r : Q(Nat.add $na $nb = $c) := (q(Eq.refl $c) : Expr)
141
+ return (.isNat sα c q(isNat_add $pa $pb $r) : Result q($a + $b))
142
+ | .isNat _ .., .isNegNat rα ..
143
+ | .isNegNat rα .., .isNat _ ..
144
+ | .isNegNat _ .., .isNegNat rα .. => intArm rα
145
+ | _, _ => failure
146
+ core
134
147
135
148
theorem isInt_neg {α} [Ring α] : {a : α} → {a' b : ℤ} →
136
149
IsInt a a' → Int.neg a' = b → IsInt (-a) b
@@ -177,24 +190,31 @@ such that `norm_num` successfully recognises both `a` and `b`. -/
177
190
@[norm_num _ * _, Mul.mul _ _] def evalMul : NormNumExt where eval {u α} e := do
178
191
let .app (.app f (a : Q($α))) (b : Q($α)) ← withReducible (whnf e) | failure
179
192
let ra ← derive a; let rb ← derive b
180
- let intArm (rα : Q(Ring $α)) := do
181
- guard <|← withNewMCtxDepth <| isDefEq f q(HMul.hMul (α := $α))
182
- let ⟨za, na, pa⟩ ← ra.toInt; let ⟨zb, nb, pb⟩ ← rb.toInt
183
- let zc := za * zb
184
- have c := mkRawIntLit zc
185
- let r : Q(Int.mul $na $nb = $c) := (q(Eq.refl $c) : Expr)
186
- return (.isInt rα zc q(isInt_mul $pa $pb $r) : Result q($a * $b))
187
193
match ra, rb with
188
- | .isNat _ na pa , .isNat sα nb pb =>
189
- have pa : Q(IsNat $a $na) := pa
194
+ | .isNat _ .. , .isNat _ .. | .isNat _ .., .isNegNat _ ..
195
+ | .isNegNat _ .., .isNat _ .. | .isNegNat _ .., .isNegNat _ .. =>
190
196
guard <|← withNewMCtxDepth <| isDefEq f q(HMul.hMul (α := $α))
191
- have c : Q(ℕ) := mkRawNatLit (na.natLit! * nb.natLit!)
192
- let r : Q(Nat.mul $na $nb = $c) := (q(Eq.refl $c) : Expr)
193
- return (.isNat sα c q(isNat_mul $pa $pb $r) : Result q($a * $b))
194
- | .isNat _ .., .isNegNat rα ..
195
- | .isNegNat rα .., .isNat _ ..
196
- | .isNegNat _ .., .isNegNat rα .. => intArm rα
197
197
| _, _ => failure
198
+ let rec
199
+ /-- Main part of `evalMul`. -/
200
+ core : Option (Result e) := do
201
+ let intArm (rα : Q(Ring $α)) := do
202
+ let ⟨za, na, pa⟩ ← ra.toInt; let ⟨zb, nb, pb⟩ ← rb.toInt
203
+ let zc := za * zb
204
+ have c := mkRawIntLit zc
205
+ let r : Q(Int.mul $na $nb = $c) := (q(Eq.refl $c) : Expr)
206
+ return (.isInt rα zc q(isInt_mul $pa $pb $r) : Result q($a * $b))
207
+ match ra, rb with
208
+ | .isNat _ na pa, .isNat sα nb pb =>
209
+ have pa : Q(IsNat $a $na) := pa
210
+ have c : Q(ℕ) := mkRawNatLit (na.natLit! * nb.natLit!)
211
+ let r : Q(Nat.mul $na $nb = $c) := (q(Eq.refl $c) : Expr)
212
+ return (.isNat sα c q(isNat_mul $pa $pb $r) : Result q($a * $b))
213
+ | .isNat _ .., .isNegNat rα ..
214
+ | .isNegNat rα .., .isNat _ ..
215
+ | .isNegNat _ .., .isNegNat rα .. => intArm rα
216
+ | _, _ => failure
217
+ core
198
218
199
219
theorem isNat_pow {α} [Semiring α] : {a : α} → {b a' b' c : ℕ} →
200
220
IsNat a a' → IsNat b b' → Nat.pow a' b' = c → IsNat (a ^ b) c
@@ -212,17 +232,23 @@ def evalPow : NormNumExt where eval {u α} e := do
212
232
let ⟨nb, pb⟩ ← deriveNat b q(instSemiringNat)
213
233
let ra ← derive a
214
234
match ra with
215
- | .isNat sα na pa =>
235
+ | .isNat _ .. | .isNegNat _ .. =>
216
236
guard <|← withDefault <| withNewMCtxDepth <| isDefEq f q(HPow.hPow (α := $α))
217
- have c : Q(ℕ) := mkRawNatLit (na.natLit! ^ nb.natLit!)
218
- let r : Q(Nat.pow $na $nb = $c) := (q(Eq.refl $c) : Expr)
219
- let pb : Q(IsNat $b $nb) := pb
220
- return (.isNat sα c q(isNat_pow $pa $pb $r) : Result q($a ^ $b))
221
- | .isNegNat rα .. =>
222
- guard <|← withDefault <| withNewMCtxDepth <| isDefEq f q(HPow.hPow (α := $α))
223
- let ⟨za, na, pa⟩ ← ra.toInt
224
- let zc := za ^ nb.natLit!
225
- let c := mkRawIntLit zc
226
- let r : Q(Int.pow $na $nb = $c) := (q(Eq.refl $c) : Expr)
227
- return (.isInt rα zc (z := c) q(isInt_pow $pa $pb $r) : Result q($a ^ $b))
228
237
| _ => failure
238
+ let rec
239
+ /-- Main part of `evalPow`. -/
240
+ core : Option (Result e) := do
241
+ match ra with
242
+ | .isNat sα na pa =>
243
+ have c : Q(ℕ) := mkRawNatLit (na.natLit! ^ nb.natLit!)
244
+ let r : Q(Nat.pow $na $nb = $c) := (q(Eq.refl $c) : Expr)
245
+ let pb : Q(IsNat $b $nb) := pb
246
+ return (.isNat sα c q(isNat_pow $pa $pb $r) : Result q($a ^ $b))
247
+ | .isNegNat rα .. =>
248
+ let ⟨za, na, pa⟩ ← ra.toInt
249
+ let zc := za ^ nb.natLit!
250
+ let c := mkRawIntLit zc
251
+ let r : Q(Int.pow $na $nb = $c) := (q(Eq.refl $c) : Expr)
252
+ return (.isInt rα zc (z := c) q(isInt_pow $pa $pb $r) : Result q($a ^ $b))
253
+ | _ => failure
254
+ core
0 commit comments