@@ -3,6 +3,7 @@ import Juvix.Core.Main.Semantics.Eval
3
3
import Juvix.Core.Main.Semantics.Eval.Indexed
4
4
import Juvix.Utils
5
5
import Mathlib.Tactic.Linarith
6
+ import Mathlib.Data.List.Forall2
6
7
import Aesop
7
8
8
9
namespace Juvix.Core.Main
@@ -13,9 +14,7 @@ def Value.Approx.Indexed (n : Nat) (v₁ v₂ : Value) : Prop :=
13
14
(∃ ctr_name args_rev args_rev',
14
15
v₁ = Value.constr_app ctr_name args_rev ∧
15
16
v₂ = Value.constr_app ctr_name args_rev' ∧
16
- args_rev.length = args_rev'.length ∧
17
- (∀ k < n, ∀ p ∈ List.zip args_rev args_rev',
18
- Value.Approx.Indexed k (Prod.fst p) (Prod.snd p))) ∨
17
+ (∀ k < n, List.Forall₂ (Value.Approx.Indexed k) args_rev args_rev')) ∨
19
18
(∃ env₁ body₁ env₂ body₂,
20
19
v₁ = Value.closure env₁ body₁ ∧
21
20
v₂ = Value.closure env₂ body₂ ∧
@@ -29,11 +28,24 @@ def Value.Approx.Indexed (n : Nat) (v₁ v₂ : Value) : Prop :=
29
28
30
29
notation :40 v:40 " ≲(" n:40 ") " v':40 => Value.Approx.Indexed n v v'
31
30
31
+ notation :40 args₁:40 " ≲ₐ(" n:40 ") " args₂:40 => List.Forall₂ (Value.Approx.Indexed n) args₁ args₂
32
+
32
33
def Value.Approx (v v' : Value) : Prop :=
33
34
∀ n, v ≲(n) v'
34
35
35
36
notation :40 v:40 " ≲ " v':40 => Value.Approx v v'
36
37
38
+ notation :40 args₁:40 " ≲ₐ " args₂:40 => List.Forall₂ Value.Approx args₁ args₂
39
+
40
+ def Object.Value.Approx.Indexed (n : Nat) : Object → Object → Prop
41
+ | Object.value v₁, Object.value v₂ => v₁ ≲(n) v₂
42
+ | _, _ => False
43
+
44
+ def Env.Approx.Indexed (n : Nat) : (env₁ env₂ : Env) → Prop :=
45
+ List.Forall₂ (Object.Value.Approx.Indexed n)
46
+
47
+ notation :40 env₁:40 " ≲ₑ(" n:40 ") " env₂:40 => Env.Approx.Indexed n env₁ env₂
48
+
37
49
def Expr.Approx (env₁ env₂ : Env) (e₁ e₂ : Expr) : Prop :=
38
50
(∀ v₁, env₁ ⊢ e₁ ↦ v₁ → ∃ v₂, env₂ ⊢ e₂ ↦ v₂ ∧ v₁ ≲ v₂)
39
51
@@ -56,10 +68,9 @@ lemma Value.Approx.Indexed.const {n c} : Value.const c ≲(n) Value.const c := b
56
68
57
69
@[aesop unsafe apply]
58
70
lemma Value.Approx.Indexed.constr_app {n ctr_name args_rev args_rev'} :
59
- args_rev.length = args_rev'.length →
60
- (∀ k < n, ∀ p ∈ List.zip args_rev args_rev', p.1 ≲(k) p.2 ) →
71
+ (∀ k < n, args_rev ≲ₐ(k) args_rev') →
61
72
Value.constr_app ctr_name args_rev ≲(n) Value.constr_app ctr_name args_rev' := by
62
- intro hlen h
73
+ intro h
63
74
unfold Value.Approx.Indexed
64
75
simp only [reduceCtorEq, and_self, exists_const, constr_app.injEq, Prod.forall, exists_and_left,
65
76
false_and, or_false, false_or]
@@ -90,8 +101,7 @@ inductive Value.Approx.Indexed.Inversion (n : Nat) : Value → Value → Prop wh
90
101
| unit : Value.Approx.Indexed.Inversion n Value.unit Value.unit
91
102
| const {c} : Value.Approx.Indexed.Inversion n (Value.const c) (Value.const c)
92
103
| constr_app {ctr_name args_rev args_rev'} :
93
- args_rev.length = args_rev'.length →
94
- (∀ k < n, ∀ p ∈ List.zip args_rev args_rev', p.1 ≲(k) p.2 ) →
104
+ (∀ k < n, args_rev ≲ₐ(k) args_rev') →
95
105
Value.Approx.Indexed.Inversion n (Value.constr_app ctr_name args_rev) (Value.constr_app ctr_name args_rev')
96
106
| closure {env₁ body₁ env₂ body₂} :
97
107
(∀ n₁ n₂, n₁ + n₂ < n →
@@ -111,14 +121,14 @@ lemma Value.Approx.Indexed.invert {n v v'} :
111
121
rcases h with
112
122
⟨h₁, h₂⟩ |
113
123
⟨c, h₁, h₂⟩ |
114
- ⟨ctr_name, args_rev, args_rev', h₁, h₂, hlen, hargs⟩ |
124
+ ⟨ctr_name, args_rev, args_rev', h₁, h₂, hargs⟩ |
115
125
⟨env₁, body₁, env₂, body₂, h₁, h₂, h⟩
116
126
· subst h₁ h₂
117
127
exact Value.Approx.Indexed.Inversion.unit
118
128
· subst h₁ h₂
119
129
exact Value.Approx.Indexed.Inversion.const
120
130
· subst h₁ h₂
121
- exact Value.Approx.Indexed.Inversion.constr_app hlen hargs
131
+ exact Value.Approx.Indexed.Inversion.constr_app hargs
122
132
· subst h₁ h₂
123
133
exact Value.Approx.Indexed.Inversion.closure h
124
134
@@ -138,9 +148,8 @@ lemma Value.Approx.Indexed.anti_monotone {n n' v₁ v₂} (h : v₁ ≲(n) v₂)
138
148
exact Value.Approx.Indexed.unit
139
149
case const =>
140
150
exact Value.Approx.Indexed.const
141
- case constr_app ctr_name args_rev args_rev' hlen hargs =>
151
+ case constr_app ctr_name args_rev args_rev' hargs =>
142
152
apply Value.Approx.Indexed.constr_app
143
- · assumption
144
153
· intros
145
154
have : k = 0 := by linarith
146
155
subst k
@@ -158,12 +167,11 @@ lemma Value.Approx.Indexed.anti_monotone {n n' v₁ v₂} (h : v₁ ≲(n) v₂)
158
167
exact Value.Approx.Indexed.unit
159
168
case const =>
160
169
exact Value.Approx.Indexed.const
161
- case constr_app ctr_name args_rev args_rev' hlen hargs =>
170
+ case constr_app ctr_name args_rev args_rev' hargs =>
162
171
apply Value.Approx.Indexed.constr_app
163
- · assumption
164
- · intros k' hk' p hp
165
- have h : k' ≤ n := by linarith
166
- aesop
172
+ · intros k' hk'
173
+ have : k' < n + 1 := by linarith
174
+ simp_all only
167
175
case closure env₁ body₁ env₂ body₂ ch =>
168
176
apply Value.Approx.Indexed.closure
169
177
· intro n₁ n₂ hn a₁ a₂ v₁ happrox heval
@@ -189,7 +197,6 @@ lemma Value.Approx.Indexed.refl {n} v : v ≲(n) v := by
189
197
exact Value.Approx.Indexed.const
190
198
case constr_app ctr_name args_rev =>
191
199
apply Value.Approx.Indexed.constr_app
192
- · rfl
193
200
· intros
194
201
have : k = 0 := by linarith
195
202
subst k
@@ -209,12 +216,11 @@ lemma Value.Approx.Indexed.refl {n} v : v ≲(n) v := by
209
216
exact Value.Approx.Indexed.const
210
217
case constr_app ctr_name args_rev =>
211
218
apply Value.Approx.Indexed.constr_app
212
- · rfl
213
- · intros k' hk' p hp
214
- have h : p.fst = p.snd := Utils.zip_refl_eq args_rev p hp
215
- rw [h]
219
+ · intros k' hk'
216
220
have : k' ≤ n := by linarith
217
- aesop
221
+ rw [List.forall₂_same]
222
+ intros
223
+ simp_all only
218
224
case closure env body =>
219
225
apply Value.Approx.Indexed.closure
220
226
· intros k' hk' va₁ va₂ v₁ happrox heval
@@ -239,10 +245,10 @@ lemma Value.Approx.Indexed.trans {n v₁ v₂ v₃} : v₁ ≲(n) v₂ → v₂
239
245
invert h₂
240
246
case const =>
241
247
exact Value.Approx.Indexed.const
242
- case constr_app ctr_name args_rev₁ args_rev₁' hlen₁ ch₁ =>
248
+ case constr_app ctr_name args_rev₁ args_rev₁' ch₁ =>
243
249
cases h₂.invert
244
- case constr_app args_rev₂ hlen₂ ch₂ =>
245
- apply Value.Approx.Indexed.constr_app <;> aesop
250
+ case constr_app args_rev₂ ch₂ =>
251
+ apply Value.Approx.Indexed.constr_app; aesop
246
252
case closure env₁ body₁ env₁' body₁' ch₁ =>
247
253
cases h₂.invert
248
254
case closure env₂ body₂ ch₂ =>
@@ -262,15 +268,18 @@ lemma Value.Approx.Indexed.trans {n v₁ v₂ v₃} : v₁ ≲(n) v₂ → v₂
262
268
invert h₂
263
269
case const =>
264
270
exact Value.Approx.Indexed.const
265
- case constr_app ctr_name args_rev args_rev' hlen₁ ch₁ =>
271
+ case constr_app ctr_name args_rev args_rev' ch₁ =>
266
272
invert h₂
267
- case constr_app args_rev'' hlen₂ ch₂ =>
273
+ case constr_app args_rev'' ch₂ =>
268
274
apply Value.Approx.Indexed.constr_app
269
- · aesop
270
- · intro k' hk' p hp
271
- obtain ⟨p₁, hp₁, p₂, hp₂, h₁, h₂, h₃⟩ := Utils.zip_ex_mid3 args_rev args_rev' args_rev'' p hlen₁ hlen₂ hp
272
- have : k' ≤ n := by linarith
273
- aesop
275
+ · intro k' hk'
276
+ have hk' : k' ≤ n := by linarith
277
+ apply Utils.forall₂_trans
278
+ · unfold Transitive
279
+ intro v₁ v₂ v₃
280
+ exact ih k' hk'
281
+ · aesop
282
+ · aesop
274
283
case closure env₁ body₁ env₂ body₂ ch₁ =>
275
284
invert h₂
276
285
case closure env₃ body₃ ch₂ =>
@@ -362,10 +371,12 @@ lemma Value.Approx.const_right {v c} : Value.const c ≲ v ↔ v = Value.const c
362
371
363
372
@[aesop unsafe apply]
364
373
lemma Value.Approx.constr_app {ctr_name args_rev args_rev'} :
365
- args_rev.length = args_rev'.length →
366
- (∀ p ∈ List.zip args_rev args_rev', Prod.fst p ≲ Prod.snd p) →
374
+ args_rev ≲ₐ args_rev' →
367
375
Value.constr_app ctr_name args_rev ≲ Value.constr_app ctr_name args_rev' := by
368
- intro hlen h n
376
+ intro h n
377
+ apply Value.Approx.Indexed.constr_app
378
+ intro k hk
379
+ rw [List.forall₂_iff_zip] at *
369
380
aesop
370
381
371
382
lemma Value.Approx.closure {env₁ body₁ env₂ body₂} :
@@ -379,37 +390,38 @@ lemma Value.Approx.closure {env₁ body₁ env₂ body₂} :
379
390
@[aesop safe destruct]
380
391
lemma Value.Approx.constr_app_inv {ctr_name args_rev args_rev'} :
381
392
Value.constr_app ctr_name args_rev ≲ Value.constr_app ctr_name args_rev' →
382
- (∀ p ∈ List.zip args_rev args_rev', Prod.fst p ≲ Prod.snd p) ∧
383
- args_rev.length = args_rev'.length := by
393
+ args_rev ≲ₐ args_rev' := by
394
+ rw [List.forall₂_iff_zip]
384
395
intro h
385
396
constructor
386
397
case left =>
387
- intros p hp n
388
- invert (h (n + 1 ))
389
- aesop
398
+ invert (h 1 )
399
+ case constr_app hargs =>
400
+ specialize (hargs 0 _)
401
+ · linarith
402
+ · exact List.Forall₂.length_eq hargs
390
403
case right =>
391
- invert (h 0 )
392
- aesop
404
+ intros v₁ v₂ hv n
405
+ invert (h (n + 1 ))
406
+ case constr_app hargs =>
407
+ specialize (hargs n _)
408
+ · linarith
409
+ · rw [List.forall₂_iff_zip] at hargs
410
+ aesop
393
411
394
412
lemma Value.Approx.constr_app_inv_length {ctr_name args_rev args_rev'} :
395
413
Value.constr_app ctr_name args_rev ≲ Value.constr_app ctr_name args_rev' →
396
414
args_rev.length = args_rev'.length := by
397
415
intro h
398
- exact (Value.Approx.constr_app_inv h).right
399
-
400
- lemma Value.Approx.constr_app_inv_args {ctr_name args_rev args_rev'} :
401
- Value.constr_app ctr_name args_rev ≲ Value.constr_app ctr_name args_rev' →
402
- ∀ p ∈ List.zip args_rev args_rev', Prod.fst p ≲ Prod.snd p := by
403
- intro h
404
- exact (Value.Approx.constr_app_inv h).left
416
+ have := Value.Approx.constr_app_inv h
417
+ exact List.Forall₂.length_eq this
405
418
406
419
@[aesop unsafe 90% destruct]
407
420
lemma Value.Approx.constr_app_inv_left {ctr_name args_rev' v} :
408
421
v ≲ Value.constr_app ctr_name args_rev' →
409
422
∃ args_rev,
410
423
v = Value.constr_app ctr_name args_rev ∧
411
- args_rev.length = args_rev'.length ∧
412
- ∀ p ∈ List.zip args_rev args_rev', Prod.fst p ≲ Prod.snd p := by
424
+ args_rev ≲ₐ args_rev' := by
413
425
intro h
414
426
invert (h 0 )
415
427
aesop
@@ -419,8 +431,7 @@ lemma Value.Approx.constr_app_inv_right {ctr_name args_rev v} :
419
431
Value.constr_app ctr_name args_rev ≲ v →
420
432
∃ args_rev',
421
433
v = Value.constr_app ctr_name args_rev' ∧
422
- args_rev.length = args_rev'.length ∧
423
- ∀ p ∈ List.zip args_rev args_rev', Prod.fst p ≲ Prod.snd p := by
434
+ args_rev ≲ₐ args_rev' := by
424
435
intro h
425
436
invert (h 0 )
426
437
aesop
@@ -475,8 +486,7 @@ inductive Value.Approx.Inversion : Value -> Value -> Prop where
475
486
| unit : Value.Approx.Inversion Value.unit Value.unit
476
487
| const {c} : Value.Approx.Inversion (Value.const c) (Value.const c)
477
488
| constr_app {ctr_name args_rev args_rev'} :
478
- args_rev.length = args_rev'.length →
479
- (∀ p ∈ List.zip args_rev args_rev', p.1 ≲ p.2 ) →
489
+ args_rev ≲ₐ args_rev' →
480
490
Value.Approx.Inversion (Value.constr_app ctr_name args_rev) (Value.constr_app ctr_name args_rev')
481
491
| closure {env₁ body₁ env₂ body₂} :
482
492
(∀ a₁ a₂, a₁ ≲ a₂ → body₁ ≲⟨a₁ ∷ env₁, a₂ ∷ env₂⟩ body₂) →
0 commit comments