Skip to content

Commit 9f43e04

Browse files
committed
Add forEach source loop helper lemmas
1 parent 2103347 commit 9f43e04

3 files changed

Lines changed: 104 additions & 2 deletions

File tree

Compiler/Proofs/IRGeneration/SourceSemantics.lean

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,108 @@ def execForEachLoop
563563
| .return value next => .return value next
564564
| .revert => .revert
565565

566+
@[simp] theorem execForEachLoop_zero
567+
(varName : String)
568+
(runBody : RuntimeState → StmtResult)
569+
(state : RuntimeState)
570+
(index : Nat) :
571+
execForEachLoop varName runBody state index 0 = .continue state := rfl
572+
573+
theorem execForEachLoop_succ
574+
(varName : String)
575+
(runBody : RuntimeState → StmtResult)
576+
(state : RuntimeState)
577+
(index remaining : Nat) :
578+
execForEachLoop varName runBody state index (remaining + 1) =
579+
let loopState :=
580+
{ state with bindings := bindValue state.bindings varName (wordNormalize index) }
581+
match runBody loopState with
582+
| .continue next => execForEachLoop varName runBody next (index + 1) remaining
583+
| .stop next => .stop next
584+
| .return value next => .return value next
585+
| .revert => .revert := rfl
586+
587+
@[simp] theorem lookupBinding?_bindValue_same
588+
(bindings : List (String × Nat))
589+
(name : String)
590+
(value : Nat) :
591+
lookupBinding? (bindValue bindings name value) name = some value := by
592+
simp [lookupBinding?, bindValue]
593+
594+
@[simp] theorem lookupValue_bindValue_same
595+
(bindings : List (String × Nat))
596+
(name : String)
597+
(value : Nat) :
598+
lookupValue (bindValue bindings name value) name = value := by
599+
simp [lookupValue, bindValue]
600+
601+
@[simp] theorem execForEachLoop_boundState_lookupBinding?
602+
(varName : String)
603+
(state : RuntimeState)
604+
(index : Nat) :
605+
lookupBinding?
606+
(bindValue state.bindings varName (wordNormalize index))
607+
varName =
608+
some (wordNormalize index) := by
609+
simp
610+
611+
@[simp] theorem execForEachLoop_boundState_lookupValue
612+
(varName : String)
613+
(state : RuntimeState)
614+
(index : Nat) :
615+
lookupValue
616+
(bindValue state.bindings varName (wordNormalize index))
617+
varName =
618+
wordNormalize index := by
619+
simp
620+
621+
theorem execForEachLoop_zero_continue_state
622+
{varName : String}
623+
{runBody : RuntimeState → StmtResult}
624+
{state final : RuntimeState}
625+
{index : Nat}
626+
(hloop : execForEachLoop varName runBody state index 0 = .continue final) :
627+
final = state := by
628+
simpa [execForEachLoop] using hloop.symm
629+
630+
theorem execForEachLoop_succ_continue_iff
631+
{varName : String}
632+
{runBody : RuntimeState → StmtResult}
633+
{state final : RuntimeState}
634+
{index remaining : Nat} :
635+
execForEachLoop varName runBody state index (remaining + 1) = .continue final ↔
636+
∃ next,
637+
runBody
638+
{ state with
639+
bindings := bindValue state.bindings varName (wordNormalize index) } =
640+
.continue next ∧
641+
execForEachLoop varName runBody next (index + 1) remaining =
642+
.continue final := by
643+
simp only [execForEachLoop]
644+
cases hbody :
645+
runBody
646+
{ state with
647+
bindings := bindValue state.bindings varName (wordNormalize index) } <;>
648+
simp [hbody]
649+
650+
theorem execForEachLoop_succ_continue
651+
{varName : String}
652+
{runBody : RuntimeState → StmtResult}
653+
{state next final : RuntimeState}
654+
{index remaining : Nat}
655+
(hbody :
656+
runBody
657+
{ state with
658+
bindings := bindValue state.bindings varName (wordNormalize index) } =
659+
.continue next)
660+
(hloop :
661+
execForEachLoop varName runBody next (index + 1) remaining =
662+
.continue final) :
663+
execForEachLoop varName runBody state index (remaining + 1) =
664+
.continue final := by
665+
rw [execForEachLoop_succ]
666+
simpa only [hbody] using hloop
667+
566668
theorem execForEachLoop_congr
567669
{varName : String}
568670
{runBodyA runBodyB : RuntimeState → StmtResult}

artifacts/interpreter_feature_matrix.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@
535535
"SpecInterpreter_basic": "unsupported",
536536
"SpecInterpreter_fuel": "supported",
537537
"IRInterpreter": "supported",
538-
"proof_status": "proved"
538+
"proof_status": "partial"
539539
},
540540
{
541541
"feature": "emit",

docs/INTERPRETER_FEATURE_MATRIX.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ Legend: **ok** = supported, **0** = returns 0 (not modeled), **del** = delegated
100100
| Return (storage words) | `Stmt.returnStorageWords` | ok | ok | -- | proved |
101101
| Stop | `Stmt.stop` | ok | ok | ok | proved |
102102
| If/else | `Stmt.ite` | ok | ok | ok | proved |
103-
| For-each loop | `Stmt.forEach` | **rev** | ok | ok | proved |
103+
| For-each loop | `Stmt.forEach` | **rev** | ok | ok | partial |
104104
| Event emission | `Stmt.emit` | ok | ok | -- | proved |
105105
| Internal call (stmt) | `Stmt.internalCall` | **rev** | ok | -- | proved |
106106
| Internal call assign | `Stmt.internalCallAssign` | **rev** | ok | -- | proved |

0 commit comments

Comments
 (0)