Skip to content

Commit 74dd175

Browse files
authored
symcc: refactor a couple more places to rely on higher level primitives (#909)
Signed-off-by: Craig Disselkoen <cdiss@amazon.com>
1 parent 9e92064 commit 74dd175

File tree

22 files changed

+465
-379
lines changed

22 files changed

+465
-379
lines changed

cedar-lean/Cedar/Data/Set.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ public instance [LT α] [DecidableLT α] : Union (Set α) := ⟨Set.union⟩
159159

160160
----- Termination-friendly iterators -----
161161

162+
public def map₁ {α} [LT β] [DecidableLT β] (s : Set α) (f : {a : α // a ∈ s} → β) : Set β :=
163+
Set.make (s.elts.attach.map f)
164+
162165
public def all₁ {α} (s : Set α) (f : {a : α // a ∈ s} → Bool) : Bool :=
163166
s.elts.attach.all f
164167

cedar-lean/Cedar/Data/SizeOf.lean

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,4 +132,8 @@ public theorem sizeOf_lt_of_elts [SizeOf α] (s : Set α) :
132132
conv => rhs ; unfold sizeOf _sizeOf_inst _sizeOf_1 ; simp
133133
omega
134134

135+
public theorem sizeOf_mk [SizeOf α] (xs : List α) :
136+
sizeOf (Set.mk xs) = 1 + sizeOf xs
137+
:= by simp
138+
135139
end Cedar.Data.Set

cedar-lean/Cedar/SymCC/Concretizer.lean

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -122,23 +122,23 @@ def TermPrim.value? : TermPrim → Option Value
122122

123123
def Term.value? : Term → Option Value
124124
| .prim p => p.value?
125-
| .set (.mk ts) _ => do
126-
let vs ← ts.mapM₁ λ ⟨tᵢ, _⟩ => tᵢ.value?
125+
| .set s _ => do
126+
let vs ← s.elts.mapM₁ λ ⟨tᵢ, _⟩ => tᵢ.value?
127127
.some (.set (Set.make vs))
128-
| .record (.mk ats) => do
129-
let avs? ← ats.mapM₂ λ ⟨(aᵢ, tᵢ), _⟩ => attrValue? aᵢ tᵢ
128+
| .record ats => do
129+
let avs? ← ats.toList.mapM₂ λ ⟨(aᵢ, tᵢ), _⟩ => attrValue? aᵢ tᵢ
130130
let avs := avs?.filterMap λ (aᵢ, vᵢ?) => vᵢ?.map (Prod.mk aᵢ)
131131
.some (.record (Map.mk avs))
132132
| _ => .none
133133
termination_by t => sizeOf t
134134
decreasing_by
135-
all_goals {
136-
simp_wf
137-
rename_i h
138-
try replace h := List.sizeOf_lt_of_mem h
139-
simp only at h
135+
all_goals simp_wf ; rename_i h
136+
· have := List.sizeOf_lt_of_mem h
137+
have := Set.sizeOf_lt_of_elts s
138+
omega
139+
· have := Map.sizeOf_lt_of_toList ats
140+
simp only at *
140141
omega
141-
}
142142
where
143143
attrValue? (a : Attr) : Term → Option (Attr × Option Value)
144144
| .some t => do .some (a, .some (← t.value?))
@@ -158,12 +158,24 @@ def TermPrim.entityUIDs : TermPrim → Set EntityUID
158158

159159
def Term.entityUIDs : Term → Set EntityUID
160160
| .var _
161-
| .none _ => Set.empty
162-
| .prim p => p.entityUIDs
163-
| .some t => t.entityUIDs
164-
| .set (Set.mk ts) _ => ts.mapUnion₁ (λ ⟨t, _⟩ => t.entityUIDs)
165-
| .record (Map.mk ats) => ats.mapUnion₃ (λ ⟨(_, t), _⟩ => t.entityUIDs)
166-
| .app _ ts _ => ts.mapUnion₁ (λ ⟨t, _⟩ => t.entityUIDs)
161+
| .none _ => Set.empty
162+
| .prim p => p.entityUIDs
163+
| .some t => t.entityUIDs
164+
| .set ts _ => ts.elts.mapUnion₁ (λ ⟨t, _⟩ => t.entityUIDs)
165+
| .record ats => ats.toList.mapUnion₃ (λ ⟨(_, t), _⟩ => t.entityUIDs)
166+
| .app _ ts _ => ts.mapUnion₁ (λ ⟨t, _⟩ => t.entityUIDs)
167+
decreasing_by
168+
all_goals simp_wf
169+
· rename t ∈ ts.elts => h
170+
have := Set.sizeOf_lt_of_mem h
171+
have := Set.sizeOf_lt_of_elts ts
172+
omega
173+
· have := Map.sizeOf_lt_of_toList ats
174+
simp only at *
175+
omega
176+
· rename t ∈ ts => h
177+
have := List.sizeOf_lt_of_mem h
178+
omega
167179

168180
def Term.entityUID? : Term → Option EntityUID
169181
| .prim (.entity uid) => .some uid

cedar-lean/Cedar/SymCC/Interpretation.lean

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
module
1818

19+
import Cedar.Data.SizeOf
1920
import Cedar.Spec
2021
public import Cedar.SymCC.Env
2122
import Cedar.SymCC.Factory
@@ -141,19 +142,27 @@ def Op.interpret (I : Interpretation) (op : Op) (ts : List Term) (ty : TermType)
141142
| _, _ => .app op ts ty
142143

143144
public def Term.interpret (I : Interpretation) : Term → Term
144-
| .prim p => .prim p
145-
| .var v => I.vars v
146-
| .none ty => noneOf ty
147-
| .some t => someOf (t.interpret I)
148-
| .set (Set.mk ts) ty =>
145+
| .prim p => .prim p
146+
| .var v => I.vars v
147+
| .none ty => noneOf ty
148+
| .some t => someOf (t.interpret I)
149+
| .set ts ty =>
149150
let ts' := ts.map₁ (λ ⟨t, _⟩ => t.interpret I)
150-
setOf ts' ty
151-
| .app op ts ty =>
151+
.set ts' ty
152+
| .app op ts ty =>
152153
let ts' := ts.map₁ (λ ⟨t, _⟩ => t.interpret I)
153154
op.interpret I ts' ty
154-
| .record (.mk ats) =>
155-
let ats' := ats.map₃ (λ ⟨(aᵢ, tᵢ), _⟩ => (aᵢ, tᵢ.interpret I))
156-
recordOf ats'
155+
| .record ats =>
156+
.record $ ats.mapOnValues₂ (λ ⟨t, _⟩ => t.interpret I)
157+
decreasing_by
158+
all_goals simp_wf
159+
· rename t ∈ ts => h
160+
have := Set.sizeOf_lt_of_mem h
161+
omega
162+
· rename t ∈ ts => h
163+
have := List.sizeOf_lt_of_mem h
164+
omega
165+
· omega
157166

158167
public def SymRequest.interpret (I : Interpretation) (req : SymRequest) : SymRequest :=
159168
{

cedar-lean/Cedar/Thm/Data/Map.lean

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,26 @@ public theorem find?_notmem_keys [LT α] [DecidableLT α] [StrictLT α] [Decidab
460460
replace h₂ := List.mem_of_find?_eq_some h₂
461461
exact in_list_in_keys h₂
462462

463+
/--
464+
Two well-formed maps are equal if they have the same `find?` for every key.
465+
-/
466+
public theorem find?_ext [LT α] [DecidableLT α] [StrictLT α] [DecidableEq α] {m₁ m₂ : Map α β}
467+
(wf₁ : m₁.WellFormed)
468+
(wf₂ : m₂.WellFormed)
469+
(h : ∀ k, m₁.find? k = m₂.find? k) :
470+
m₁ = m₂
471+
:= by
472+
apply eq_iff_toList_equiv wf₁ wf₂ |>.mp
473+
constructor
474+
· intro ⟨k, v⟩ h₁
475+
have h₂ := (in_list_iff_find?_some wf₁).mp h₁
476+
rw [h] at h₂
477+
exact (in_list_iff_find?_some wf₂).mpr h₂
478+
· intro ⟨k, v⟩ h₁
479+
have h₂ := (in_list_iff_find?_some wf₂).mp h₁
480+
rw [← h] at h₂
481+
exact (in_list_iff_find?_some wf₁).mpr h₂
482+
463483
public theorem find?_none_all_absent [LT α] [DecidableLT α] [StrictLT α] [DecidableEq α] {m : Map α β} {k : α} :
464484
m.find? k = none → ∀ v, ¬ (k, v) ∈ m.toList
465485
:= by
@@ -765,8 +785,9 @@ public theorem mapOnValues_doubleton {f : β → γ} {s₁ s₂ : String} (b₁
765785
Map.mapOnValues f (Map.mk [(s₁, b₁), (s₂, b₂)]) = Map.mk [(s₁, f b₁), (s₂, f b₂)]
766786
:= by simp [mapOnValues]
767787

788+
@[simp]
768789
public theorem find?_mapOnValues {α β γ} [LT α] [DecidableLT α] [DecidableEq α] (f : β → γ) (m : Map α β) (k : α) :
769-
(m.find? k).map f = (m.mapOnValues f).find? k
790+
(m.mapOnValues f).find? k = (m.find? k).map f
770791
:= by
771792
simp only [find?, toList, mapOnValues, ← List.find?_pair_map]
772793
cases m.1.find? (λ x => x.fst == k) <;> simp only [Option.map_none, Option.map_some]
@@ -776,7 +797,7 @@ public theorem find?_mapOnValues_some {α β γ} [LT α] [DecidableLT α] [Decid
776797
(m.mapOnValues f).find? k = .some (f v)
777798
:= by
778799
intro h₁
779-
rw [find?_mapOnValues]
800+
rw [find?_mapOnValues]
780801
simp [Option.map, h₁]
781802

782803
public theorem find?_mapOnValues_some' {α β γ} [LT α] [DecidableLT α] [DecidableEq α] (f : β → γ) {m : Map α β} {k : α} {v : γ} :
@@ -805,7 +826,7 @@ public theorem find?_mapOnValues_some' {α β γ} [LT α] [DecidableLT α] [Deci
805826
public theorem find?_mapOnValues_none {α β γ} [LT α] [DecidableLT α] [DecidableEq α] (f : β → γ) {m : Map α β} {k : α} :
806827
(m.mapOnValues f).find? k = .none ↔
807828
m.find? k = .none
808-
:= by simp [find?_mapOnValues]
829+
:= by simp [find?_mapOnValues]
809830

810831
public theorem mapOnValues_eq_make_map {α β γ} [LT α] [StrictLT α] [DecidableLT α] (f : β → γ) {m : Map α β}
811832
(wf : m.WellFormed) :
@@ -834,13 +855,14 @@ public theorem mem_toList_find? {α β} [LT α] [DecidableLT α] [StrictLT α] [
834855
simp only at h
835856
simp [find?, h]
836857

837-
public theorem mapOnValues_contains {α β γ} [LT α] [DecidableLT α] [DecidableEq α] (f : β → γ) {m : Map α β} {k : α} :
838-
Map.contains m k = Map.contains (Map.mapOnValues f m) k
858+
@[simp]
859+
public theorem contains_mapOnValues {α β γ} [LT α] [DecidableLT α] [DecidableEq α] (f : β → γ) {m : Map α β} {k : α} :
860+
Map.contains (Map.mapOnValues f m) k = Map.contains m k
839861
:= by
840862
simp only [contains, Option.isSome]
841-
split <;> rename_i h
842-
· simp [find?_mapOnValues_some f h]
863+
cases h : m.find? k
843864
· simp [(find?_mapOnValues_none f).mpr h]
865+
· simp [find?_mapOnValues_some f h]
844866

845867
@[simp]
846868
public theorem keys_mapOnValues [LT α] [StrictLT α] [DecidableLT α] [DecidableEq α] (f : β → γ) (m : Map α β) :
@@ -879,6 +901,12 @@ public theorem mapOnValues_restricted_id {f : β → β} {m : Map α β} :
879901
intro pair hpair
880902
simp [h pair.snd (Map.in_list_in_values hpair)]
881903

904+
@[simp]
905+
public theorem mapOnValues_make [LT α] [DecidableLT α] [StrictLT α] {f : β → γ} {kvs : List (α × β)} :
906+
(Map.make kvs).mapOnValues f = Map.make (kvs.map (Prod.map id f))
907+
:= by
908+
simp [make, mapOnValues, List.canonicalize_of_map_fst]
909+
882910
@[simp]
883911
public theorem mapOnValues₂_eq_mapOnValues {α β γ} [SizeOf α] [SizeOf β] (m : Map α β) (f : β → γ) :
884912
m.mapOnValues₂ (λ x : { x : β // sizeOf x < sizeOf m } => f x.1) = m.mapOnValues f
@@ -898,7 +926,7 @@ public theorem findOrErr_mapOnValues [LT α] [DecidableLT α] [DecidableEq α] {
898926
(m.mapOnValues f).findOrErr k e = (m.findOrErr k e).map f
899927
:= by
900928
unfold findOrErr
901-
rw [find?_mapOnValues]
929+
rw [find?_mapOnValues]
902930
cases m.find? k <;> simp [Except.map]
903931

904932
@[simp]
@@ -1001,10 +1029,10 @@ public theorem findOrErr_err_iff_not_in_keys [LT α] [DecidableLT α] [StrictLT
10011029
exact find?_notmem_keys wf
10021030

10031031
/--
1004-
The converse requires two extra preconditions (`m` is `WellFormed` and `f` is
1005-
injective) and is available as `in_mapOnValues_in_toList`
1032+
The converse requires the extra precondition that `f` is injective, and is
1033+
available as `in_mapOnValues_in_toList`
10061034
-/
1007-
public theorem in_toList_in_mapOnValues [LT α] [DecidableLT α] [DecidableEq α] {f : β → γ} {m : Map α β} {k : α} {v : β} :
1035+
public theorem in_toList_in_mapOnValues [LT α] [DecidableLT α] [DecidableEq α] (f : β → γ) {m : Map α β} {k : α} {v : β} :
10081036
(k, v) ∈ m.toList → (k, f v) ∈ (m.mapOnValues f).toList
10091037
:= by
10101038
unfold mapOnValues

cedar-lean/Cedar/Thm/Data/Set.lean

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,10 @@ public theorem make_wf [LT α] [DecidableLT α] [StrictLT α] (xs : List α) :
263263
:= by
264264
simp only [WellFormed, make, toList, elts, List.canonicalize_idempotent]
265265

266+
public theorem make_elts [LT α] [DecidableLT α] {s : Set α} :
267+
WellFormed s → Set.make s.elts = s
268+
:= by grind [WellFormed, toList]
269+
266270
public theorem make_sorted {α} [LT α] [DecidableLT α] [StrictLT α] {xs : List α} :
267271
xs.Sorted → Set.make xs = Set.mk xs
268272
:= by
@@ -730,13 +734,60 @@ public theorem wellFormed_correct {α} [LT α] [StrictLT α] [DecidableLT α] {s
730734

731735
/-! ### map -/
732736

737+
public theorem map_wf [LT β] [DecidableLT β] [StrictLT β] (f : α → β) (s : Set α) :
738+
(s.map f).WellFormed
739+
:= by simp [map, make_wf]
740+
741+
public theorem map_id [LT α] [DecidableLT α] (s : Set α) :
742+
s.WellFormed → s.map id = s
743+
:= by
744+
intro hwf
745+
simp [map, make_elts hwf]
746+
733747
/-- Analogue of `List.mem_map` but for sets -/
734748
@[simp]
735-
public theorem mem_map [LT α] [DecidableLT α] [StrictLT α] [LT β] [DecidableLT β] [StrictLT β] (b : β) (f : α → β) (s : Set α) :
749+
public theorem mem_map [LT α] [DecidableLT α] [StrictLT α] [LT β] [DecidableLT β] [StrictLT β] {b : β} {f : α → β} {s : Set α} :
736750
b ∈ s.map f ↔ ∃ a ∈ s, f a = b
737751
:= by
738752
simp [Set.map, Set.mem_make, Set.mem_elts_iff_mem_set]
739753

754+
/-- Analogue of `List.map_congr`, but for sets -/
755+
public theorem map_congr [LT β] [DecidableLT β] {f g : α → β} {s : Set α} :
756+
(∀ a ∈ s, f a = g a) → s.map f = s.map g
757+
:= by
758+
simp only [map]
759+
intro h
760+
congr 1
761+
apply List.map_congr
762+
intro x hx
763+
exact h x hx
764+
765+
@[simp]
766+
public theorem isEmpty_map [DecidableEq α] [LT β] [DecidableLT β] [DecidableEq β] {f : α → β} {s : Set α} :
767+
(s.map f).isEmpty = s.isEmpty
768+
:= by
769+
cases h : s.isEmpty
770+
case true =>
771+
simp only [isEmpty, empty, beq_iff_eq] at h
772+
simp [map, h]
773+
case false =>
774+
simp only [isEmpty, empty, beq_eq_false_iff_ne, ne_eq] at h
775+
simp only [map, elts, isEmpty_make_eq_false, ne_eq, List.map_eq_nil_iff]
776+
cases s ; simp_all
777+
778+
@[simp]
779+
public theorem map_make [LT α] [DecidableLT α] [StrictLT α] [LT β] [DecidableLT β] [StrictLT β] {f : α → β} {xs : List α} :
780+
(Set.make xs).map f = Set.make (xs.map f)
781+
:= by
782+
simp only [map]
783+
rw [make_make_eqv]
784+
exact List.map_equiv f (Set.elts (Set.make xs)) xs elts_make_eqv
785+
786+
-- TODO: perhaps we could avoid needing to have this a public theorem, if we had enough other lemmas about `Set.map` that avoided callers having to reason about `make` or `elts`
787+
public theorem map_def [LT β] [DecidableLT β] (f : α → β) (s : Set α) :
788+
s.map f = Set.make (s.elts.map f)
789+
:= by simp [Set.map]
790+
740791
/-! ### filter and differences -/
741792

742793
public theorem filter_wf [LT α] [DecidableLT α] [StrictLT α] (p : α → Bool) (s : Set α) :
@@ -802,7 +853,12 @@ public theorem any_eq_false {f : α → Bool} {s : Set α} :
802853
:= by
803854
simp only [Set.any, List.any_eq_false, Set.mem_elts_iff_mem_set]
804855

805-
/-! ### all₁ and any₁ -/
856+
/-! ### map₁, all₁, and any₁ -/
857+
858+
@[simp]
859+
public theorem map₁_eq_map [LT α] [DecidableLT α] [LT β] [DecidableLT β] (f : α → β) (s : Set α) :
860+
(s.map₁ λ ⟨elt, _⟩ => f elt) = s.map f
861+
:= by simp [map₁, map]
806862

807863
@[simp]
808864
public theorem all₁_eq_all {s : Set α} {f : α → Bool} :

cedar-lean/Cedar/Thm/SymCC/Compiler/Record.lean

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,17 +262,17 @@ private theorem same_forall₂_implies_same_record {ats : List (Attr × Term)} {
262262
generalize h₂ : (List.canonicalize Prod.fst avs) = vs
263263
rw [h₁, h₂] at hs
264264
clear h₁ h₂
265-
have ⟨avs', hts⟩ : ∃ avs', List.mapM' (λ x => Term.value?.attrValue? x.fst x.snd) ts = some avs' := by
265+
have ⟨avs', hts⟩ : ∃ avs', List.mapM (λ x => Term.value?.attrValue? x.fst x.snd) ts = some avs' := by
266266
induction hs
267267
case nil =>
268268
exists []
269269
case cons thd vhd ttl _ h₁ _ ih =>
270270
replace ⟨vtl', ih⟩ := ih
271271
exists ((vhd.fst, some vhd.snd) :: vtl')
272-
simp only [List.mapM'_cons, value?_some_implies_attrValue?_some h₁.right, ih, Option.pure_def,
272+
simp only [List.mapM_cons, value?_some_implies_attrValue?_some h₁.right, ih, Option.pure_def,
273273
Option.bind_some_fun, ← h₁.left]
274274
apply record_value?_some_implied_by hts
275-
replace hts := List.mapM'_some_eq_filterMap hts
275+
replace hts := List.mapM_some_eq_filterMap hts
276276
subst hts
277277
simp only [List.filterMap_filterMap]
278278
induction hs

cedar-lean/Cedar/Thm/SymCC/Concretizer/Lit.lean

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,6 @@ theorem wf_term_implies_valid_uids {t : Term} {εs : SymEntities} :
168168
replace hwf := wf_term_set_implies_wf_elt hwf hin'
169169
exact wf_term_implies_valid_uids hwf uid hin
170170
case record ats =>
171-
cases ats ; rename_i ats
172171
simp only [List.mapUnion₃_eq_mapUnion λ x : Attr × Term => x.snd.entityUIDs] at hin
173172
rw [List.mem_mapUnion_iff_mem_exists] at hin
174173
replace ⟨at', hin', hin⟩ := hin
@@ -187,20 +186,22 @@ decreasing_by
187186
· rename_i h _ ; subst h
188187
simp only [Term.some.sizeOf_spec]
189188
omega
190-
· rename_i h _ _ _ _ _ ; subst h
191-
rename_i h _ _ _ _ _ _ ; subst h
189+
· subst_vars
192190
have hs := List.sizeOf_lt_of_mem hin'
193191
simp only [Term.set.sizeOf_spec, Set.mk.sizeOf_spec, gt_iff_lt]
192+
rename List Term => ts
193+
have := Set.sizeOf_lt_of_elts (Set.mk ts)
194+
have := Set.sizeOf_mk ts
194195
omega
195-
· rename_i h _ _ _ _ _ ; subst h
196-
rename_i h _ _ _ _ _ _ ; subst h
197-
have hs := List.sizeOf_lt_of_mem hin'
198-
have hp : at' = (at'.fst, at'.snd) := by simp only
199-
rw [hp] at hs
200-
simp only [Prod.mk.sizeOf_spec] at hs
201-
simp only [Term.record.sizeOf_spec, Map.mk.sizeOf_spec, gt_iff_lt]
196+
· subst_vars
197+
simp only [Term.record.sizeOf_spec]
198+
rename Map Attr Term => m
199+
calc sizeOf at'.snd
200+
_ < sizeOf at' := by cases at' ; simp only [Prod.mk.sizeOf_spec, Nat.lt_add_left_iff_pos] ; omega
201+
_ < sizeOf m.toList := List.sizeOf_lt_of_mem hin'
202+
_ < sizeOf m := Map.sizeOf_lt_of_toList m
202203
omega
203-
· rename_i h _ _ _ _ _ _ _ _ _ _ _ _ _ _ ; subst h
204+
· subst_vars
204205
have hs := List.sizeOf_lt_of_mem hin'
205206
simp only [Term.app.sizeOf_spec]
206207
omega

0 commit comments

Comments
 (0)