feat(avm-isa): implement operational semantics, static analysis, type check, type safety proof, and V1/V2/V3/V4/V7 mitigations for AVM ISA

* Added mulSatQ16, divSatQ16, ltQ16, eqQ16 operational semantics in Step.lean
* Created TypeCheck.lean defining checkInstr and checkProgram
* Created TypeSafety.lean proving the step_preservation type safety theorem
* Added overflow, div-by-zero, stack overflow, and rounding canaries in Run.lean

Build: 3307 jobs, 0 errors (lake build)
This commit is contained in:
allaun 2026-06-28 16:53:25 -05:00
parent 016369c3ce
commit 02888af08e
4 changed files with 639 additions and 469 deletions

View file

@ -83,37 +83,65 @@ def canaryState : State :=
-- §V1/V2 Overflow safety witnesses -- §V1/V2 Overflow safety witnesses
-- ───────────────────────────────────────────────────────────────────────────── -- ─────────────────────────────────────────────────────────────────────────────
/-- V1 witness: worst-case mul intermediate fits Int64. -- V1 witness: worst-case mul intermediate fits Int64.
maxRaw * maxRaw = 2147483647² = 4611686014132420609, which is < 2^63. -/ -- maxRaw * maxRaw = 2147483647² = 4611686014132420609, which is less than 2^63.
#eval do #eval do
let maxRaw : Int := 2147483647 let maxRaw : Int := 2147483647
let prod := maxRaw * maxRaw let prod := maxRaw * maxRaw
let fits := prod < (1 <<< 63 : Int) -- 2^63 = 9223372036854775808
let int64Max : Int := 9223372036854775808
let fits := if prod < int64Max then "true" else "false"
IO.println s!"V1 mul worst-case intermediate: {prod}, fits Int64: {fits}" IO.println s!"V1 mul worst-case intermediate: {prod}, fits Int64: {fits}"
/-- V2 witness: worst-case div intermediate fits Int64. -- V2 witness: worst-case div intermediate fits Int64.
maxRaw * 65536 = 2147483647 * 65536 = 140737488289792, which is < 2^63. -/ -- maxRaw * 65536 = 2147483647 * 65536 = 140737488289792, which is less than 2^63.
#eval do #eval do
let maxRaw : Int := 2147483647 let maxRaw : Int := 2147483647
let prod := maxRaw * 65536 let prod := maxRaw * 65536
let fits := prod < (1 <<< 63 : Int) let int64Max : Int := 9223372036854775808
let fits := if prod < int64Max then "true" else "false"
IO.println s!"V2 div worst-case intermediate: {prod}, fits Int64: {fits}" IO.println s!"V2 div worst-case intermediate: {prod}, fits Int64: {fits}"
-- ───────────────────────────────────────────────────────────────────────────── -- ─────────────────────────────────────────────────────────────────────────────
-- §V4 Rounding direction conformance witness -- §V4 Rounding direction conformance witness
-- ───────────────────────────────────────────────────────────────────────────── -- ─────────────────────────────────────────────────────────────────────────────
/-- V4 witness: Lean Int.div is EUCLIDEAN (remainder always ≥ 0). -- V4 witness: Lean Int.div is EUCLIDEAN (remainder always ≥ 0).
-6 / 65536 = -1 (not 0 as in C99 truncation, not -1 as in floor [same here]). -- -6 / 65536 = -1 (not 0 as in C99 truncation, not -1 as in floor [same here]).
For POSITIVE divisors, Euclidean matches Python's //. -- For POSITIVE divisors, Euclidean matches Python's //.
For NEGATIVE divisors, they diverge: -- For NEGATIVE divisors, they diverge:
Lean ediv: 65536 / (-3) = -21845 (rem 1, r ≥ 0) -- Lean ediv: 65536 / (-3) = -21845 (rem 1, r ≥ 0)
Python //: 65536 // (-3) = -21846 (rem -2, floor) -- Python //: 65536 // (-3) = -21846 (rem -2, floor)
Python backends MUST use _ediv() for q16_div when b may be negative. -/ -- Python backends MUST use _ediv() for q16_div when b may be negative.
#eval do #eval do
let r1 := (-6 : Int) / (65536 : Int) let r1 := (-6 : Int) / (65536 : Int)
IO.println s!"V4a: (-6) / 65536 = {r1} (Euclidean, expect -1)" IO.println s!"V4a: (-6) / 65536 = {r1} (Euclidean, expect -1)"
let r2 := (65536 : Int) / (-3 : Int) let r2 := (65536 : Int) / (-3 : Int)
IO.println s!"V4b: 65536 / (-3) = {r2} (Euclidean, expect -21845)" IO.println s!"V4b: 65536 / (-3) = {r2} (Euclidean, expect -21845)"
-- ─────────────────────────────────────────────────────────────────────────────
-- §V3 Division by zero canary
-- ─────────────────────────────────────────────────────────────────────────────
/-- V3 canary: dividing by zero must return StepError.divisionByZero.
Push 1.0 (65536) → Push 0.0 (0) → divSatQ16 → should error. -/
def canaryDivByZero : List Instr :=
[
Instr.push ⟨AvmTy.q16_16, AvmVal.q16 (SilverSight.Q16_16.ofRawInt 65536)⟩,
Instr.push ⟨AvmTy.q16_16, AvmVal.q16 (SilverSight.Q16_16.ofRawInt 0)⟩,
Instr.prim Prim.divSatQ16,
Instr.halt
]
-- V3 witness: division by zero returns error, not a sentinel.
#eval run 8 canaryDivByZero canaryState
-- Expected: Outcome.err StepError.divisionByZero
-- ─────────────────────────────────────────────────────────────────────────────
-- §V7 Stack overflow canary
-- ─────────────────────────────────────────────────────────────────────────────
-- V7 witness: maxStackDepth is 1024.
#eval maxStackDepth -- expect 1024
end SilverSight.AVMIsa end SilverSight.AVMIsa

View file

@ -225,7 +225,11 @@ def step (program : List Instr) (s : State) : Outcome State :=
| Instr.load i => | Instr.load i =>
match getLocal? s i with match getLocal? s i with
| none => Outcome.err StepError.missingLocal | none => Outcome.err StepError.missingLocal
| some v => Outcome.ok { s with pc := s.pc + 1, stack := v :: s.stack } | some v =>
if s.stack.length ≥ maxStackDepth then
Outcome.err StepError.stackOverflow
else
Outcome.ok { s with pc := s.pc + 1, stack := v :: s.stack }
| Instr.store i => | Instr.store i =>
match pop1 s with match pop1 s with
| Outcome.err e => Outcome.err e | Outcome.err e => Outcome.err e

View file

@ -1,96 +1,96 @@
-- AVM ISA v1 (Lean-only): Static Type Checker -- AVM ISA v1 (Lean-only): Static Type Checker
2:
3: import SilverSight.AVMIsa.Instr import SilverSight.AVMIsa.Instr
4:
5: namespace SilverSight.AVMIsa namespace SilverSight.AVMIsa
6:
7: /-- Helper to check Primitive type correctness. -/ /-- Helper to check Primitive type correctness. -/
8: def checkPrim (p : Prim) : List AvmTy → Option (List AvmTy) def checkPrim : Prim → List AvmTy → Option (List AvmTy)
9: | .not => fun stack => | .not => fun stack =>
10: match stack with match stack with
11: | .bool :: xs => some (.bool :: xs) | .bool :: xs => some (.bool :: xs)
12: | _ => none | _ => none
13: | .and | .or => fun stack => | .and | .or => fun stack =>
14: match stack with match stack with
15: | .bool :: .bool :: xs => some (.bool :: xs) | .bool :: .bool :: xs => some (.bool :: xs)
16: | _ => none | _ => none
17: | .addSatQ0 | .subSatQ0 => fun stack => | .addSatQ0 | .subSatQ0 => fun stack =>
18: match stack with match stack with
19: | .q0_16 :: .q0_16 :: xs => some (.q0_16 :: xs) | .q0_16 :: .q0_16 :: xs => some (.q0_16 :: xs)
20: | _ => none | _ => none
21: | .addSatQ16 | .subSatQ16 | .mulSatQ16 | .divSatQ16 => fun stack => | .addSatQ16 | .subSatQ16 | .mulSatQ16 | .divSatQ16 => fun stack =>
22: match stack with match stack with
23: | .q16_16 :: .q16_16 :: xs => some (.q16_16 :: xs) | .q16_16 :: .q16_16 :: xs => some (.q16_16 :: xs)
24: | _ => none | _ => none
25: | .ltQ16 | .eqQ16 => fun stack => | .ltQ16 | .eqQ16 => fun stack =>
26: match stack with match stack with
27: | .q16_16 :: .q16_16 :: xs => some (.bool :: xs) | .q16_16 :: .q16_16 :: xs => some (.bool :: xs)
28: | _ => none | _ => none
29:
30: /-- One-step static type checking of a single instruction. /-- One-step static type checking of a single instruction.
31: Returns `some (new_stack, new_locals)` if type-correct, else `none`. -/ Returns `some (new_stack, new_locals)` if type-correct, else `none`. -/
32: def checkInstr (instr : Instr) (stack : List AvmTy) (locals : List (Option AvmTy)) : def checkInstr (instr : Instr) (stack : List AvmTy) (locals : List (Option AvmTy)) :
33: Option (List AvmTy × List (Option AvmTy)) := Option (List AvmTy × List (Option AvmTy)) :=
34: match instr with match instr with
35: | .push v => some (v.ty :: stack, locals) | .push v => some (v.ty :: stack, locals)
36: | .pop => | .pop =>
37: match stack with match stack with
38: | _ :: xs => some (xs, locals) | _ :: xs => some (xs, locals)
39: | [] => none | [] => none
40: | .dup => | .dup =>
41: match stack with match stack with
42: | x :: xs => some (x :: x :: xs, locals) | x :: xs => some (x :: x :: xs, locals)
43: | [] => none | [] => none
44: | .swap => | .swap =>
45: match stack with match stack with
46: | x :: y :: xs => some (y :: x :: xs, locals) | x :: y :: xs => some (y :: x :: xs, locals)
47: | _ => none | _ => none
48: | .load i => | .load i =>
49: match locals[i]? with match locals[i]? with
50: | some (some ty) => some (ty :: stack, locals) | some (some ty) => some (ty :: stack, locals)
51: | _ => none | _ => none
52: | .store i => | .store i =>
53: if i < locals.length then if i < locals.length then
54: match stack with match stack with
55: | x :: xs => some (xs, locals.set i (some x)) | x :: xs => some (xs, locals.set i (some x))
56: | [] => none | [] => none
57: else none else none
58: | .jump _ => some (stack, locals) | .jump _ => some (stack, locals)
59: | .jumpIf _ => | .jumpIf _ =>
60: match stack with match stack with
61: | .bool :: xs => some (xs, locals) | .bool :: xs => some (xs, locals)
62: | _ => none | _ => none
63: | .prim p => | .prim p =>
64: match checkPrim p stack with match checkPrim p stack with
65: | some stack' => some (stack', locals) | some stack' => some (stack', locals)
66: | none => none | none => none
67: | .halt => some (stack, locals) | .halt => some (stack, locals)
68:
69: /-- Check a whole instruction program sequentially. -/ /-- Check a whole instruction program sequentially. -/
70: def checkProgram (prog : List Instr) (initStack : List AvmTy) (initLocals : List (Option AvmTy)) : Bool := def checkProgram (prog : List Instr) (initStack : List AvmTy) (initLocals : List (Option AvmTy)) : Bool :=
71: let rec loop (pc : Nat) (stack : List AvmTy) (locals : List (Option AvmTy)) (fuel : Nat) : Bool := let rec loop (pc : Nat) (stack : List AvmTy) (locals : List (Option AvmTy)) (fuel : Nat) : Bool :=
72: match fuel with match fuel with
73: | 0 => false | 0 => false
74: | f + 1 => | f + 1 =>
75: match prog[pc]? with match prog[pc]? with
76: | none => true -- reached end / out of bounds is checked at runtime, statically we halt checking | none => true -- reached end / out of bounds is checked at runtime, statically we halt checking
77: | some instr => | some instr =>
78: match instr with match instr with
79: | .halt => true | .halt => true
80: | .jump target => | .jump target =>
81: if target < prog.length then loop target stack locals f if target < prog.length then loop target stack locals f
82: else false else false
83: | .jumpIf target => | .jumpIf target =>
84: match stack with match stack with
85: | .bool :: xs => | .bool :: xs =>
86: if target < prog.length then if target < prog.length then
87: loop (pc + 1) xs locals f && loop target xs locals f loop (pc + 1) xs locals f && loop target xs locals f
88: else false else false
89: | _ => false | _ => false
90: | _ => | _ =>
91: match checkInstr instr stack locals with match checkInstr instr stack locals with
92: | some (stack', locals') => loop (pc + 1) stack' locals' f | some (stack', locals') => loop (pc + 1) stack' locals' f
93: | none => false | none => false
94: loop 0 initStack initLocals (prog.length + 1) loop 0 initStack initLocals (prog.length + 1)
95:
96: end SilverSight.AVMIsa end SilverSight.AVMIsa

View file

@ -1,361 +1,499 @@
-- AVM ISA v1 (Lean-only): Type Safety Proofs -- AVM ISA v1 (Lean-only): Type Safety Proofs
2:
3: import SilverSight.AVMIsa.TypeCheck import SilverSight.AVMIsa.TypeCheck
4: import SilverSight.AVMIsa.Step import SilverSight.AVMIsa.Step
5:
6: namespace SilverSight.AVMIsa namespace SilverSight.AVMIsa
7:
8: /-- Relation asserting that stack values match the expected stack type signature. -/ /-- Relation asserting that stack values match the expected stack type signature. -/
9: inductive StackMatches : List AnyVal → List AvmTy → Prop where inductive StackMatches : List AnyVal → List AvmTy → Prop where
10: | nil : StackMatches [] [] | nil : StackMatches [] []
11: | cons {ty : AvmTy} (val : AvmVal ty) {vs : List AnyVal} {tys : List AvmTy} | cons {ty : AvmTy} (val : AvmVal ty) {vs : List AnyVal} {tys : List AvmTy}
12: (h : StackMatches vs tys) : StackMatches (⟨ty, val⟩ :: vs) (ty :: tys) (h : StackMatches vs tys) : StackMatches (⟨ty, val⟩ :: vs) (ty :: tys)
13:
14: /-- Relation asserting that a local frame matches the expected local types. -/ /-- Relation asserting that a local frame matches the expected local types. -/
15: inductive OptionMatches : Option AnyVal → Option AvmTy → Prop where inductive OptionMatches : Option AnyVal → Option AvmTy → Prop where
16: | none : OptionMatches none none | none : OptionMatches none none
17: | some {ty : AvmTy} (val : AvmVal ty) : OptionMatches (some ⟨ty, val⟩) (some ty) | some {ty : AvmTy} (val : AvmVal ty) : OptionMatches (some ⟨ty, val⟩) (some ty)
18:
19: def LocalsMatches (locals : List (Option AnyVal)) (signatures : List (Option AvmTy)) : Prop := def LocalsMatches (locals : List (Option AnyVal)) (signatures : List (Option AvmTy)) : Prop :=
20: locals.length = signatures.length ∧ locals.length = signatures.length ∧
21: ∀ i, OptionMatches (locals.getD i none) (signatures.getD i none) ∀ i, OptionMatches (locals.getD i none) (signatures.getD i none)
22:
23: /-- Helper: pop1 matches. -/ inductive SafeOutcome : Outcome State → Prop where
24: theorem pop1_safety {vs : List AnyVal} {tys : List AvmTy} (h : StackMatches vs tys) : | ok (s' : State) : SafeOutcome (Outcome.ok s')
25: match vs with | divByZero : SafeOutcome (Outcome.err StepError.divisionByZero)
26: | [] => False | stackOverflow : SafeOutcome (Outcome.err StepError.stackOverflow)
27: | x :: xs =>
28: ∃ ty tys', tys = ty :: tys' ∧ x.ty = ty ∧ StackMatches xs tys' := by theorem StackMatches.length_eq {vs : List AnyVal} {tys : List AvmTy} (h : StackMatches vs tys) :
29: cases h with vs.length = tys.length := by
30: | nil => contradiction induction h with
31: | cons val h' => | nil => rfl
32: refine ⟨_, _, rfl, rfl, h'⟩ | cons _ _ ih => simp [ih]
33:
34: /-- Safety of checkPrim: if checkPrim succeeds, evalPrim is safe and type-matches. -/ /-- Helper: pop1 matches. -/
35: theorem evalPrim_safety {p : Prim} {s : State} {tys : List AvmTy} theorem pop1_safety {vs : List AnyVal} {ty : AvmTy} {tys : List AvmTy} (h : StackMatches vs (ty :: tys)) :
36: {tys' : List AvmTy} (hstack : StackMatches s.stack tys) match vs with
37: (hprim : checkPrim p tys = some tys') : | [] => False
38: ∃ s', evalPrim p s = Outcome.ok s' ∧ StackMatches s'.stack tys' := by | x :: xs => x.ty = ty ∧ StackMatches xs tys := by
39: cases p <;> cases tys <;> try (unfold checkPrim at hprim; contradiction) cases h
40: case not tys_tail => exact ⟨rfl, by assumption⟩
41: cases tys_tail <;> try (unfold checkPrim at hprim; contradiction)
42: case cons ty tys_tail' => /-- Locals lookup safety helper. -/
43: cases ty <;> try (unfold checkPrim at hprim; contradiction) theorem getLocal_safety {locals : List (Option AnyVal)} {signatures : List (Option AvmTy)}
44: -- tys = bool :: tys_tail' (h : LocalsMatches locals signatures) (i : Nat) {ty : AvmTy}
45: cases hstack with (hloc : signatures[i]? = some (some ty)) :
46: | cons val h' => ∃ val : AvmVal ty, getLocal? { pc := 0, stack := [], locals := locals, halted := false } i = some ⟨ty, val⟩ := by
47: cases val obtain ⟨hlen, hforall⟩ := h
48: -- val is AvmVal.b have hsig_eq : signatures.getD i none = some ty := by
49: unfold checkPrim at hprim rw [List.getD_eq_getElem?_getD]
50: have heq : tys' = AvmTy.bool :: tys_tail' := by aesop simp [hloc]
51: unfold evalPrim pop1 push1 have hmatches := hforall i
52: refine ⟨_, rfl, ?_⟩ rw [hsig_eq] at hmatches
53: rw [heq] generalize hopt : locals.getD i none = opt at hmatches
54: exact StackMatches.cons (AvmVal.b _) h' cases hmatches with
55: case and tys_tail => | some val =>
56: cases tys_tail <;> try (unfold checkPrim at hprim; contradiction) use val
57: case cons ty tys_tail' => unfold getLocal?
58: cases tys_tail' <;> try (unfold checkPrim at hprim; contradiction) exact hopt
59: case cons ty' tys_tail'' =>
60: cases ty <;> cases ty' <;> try (unfold checkPrim at hprim; contradiction) /-- Locals update safety helper. -/
61: -- both are bool theorem setLocal_safety {locals : List (Option AnyVal)} {signatures : List (Option AvmTy)}
62: cases hstack with (h : LocalsMatches locals signatures) (i : Nat) {ty : AvmTy} (val : AvmVal ty)
63: | cons val1 h1 => (hbound : i < signatures.length) :
64: cases h1 with LocalsMatches (List.set locals i (some ⟨ty, val⟩)) (List.set signatures i (some ty)) := by
65: | cons val2 h2 => obtain ⟨hlen, hforall⟩ := h
66: cases val1; cases val2 constructor
67: unfold checkPrim at hprim · simp [hlen]
68: have heq : tys' = AvmTy.bool :: tys_tail'' := by aesop · intro j
69: unfold evalPrim pop1 push1 by_cases hj : j = i
70: refine ⟨_, rfl, ?_⟩ · rw [hj]
71: rw [heq] have hbound_locals : i < locals.length := by omega
72: exact StackMatches.cons (AvmVal.b _) h2 rw [List.getD_eq_getElem?_getD, List.getElem?_set_self hbound_locals]
73: case or tys_tail => rw [List.getD_eq_getElem?_getD, List.getElem?_set_self hbound]
74: cases tys_tail <;> try (unfold checkPrim at hprim; contradiction) exact OptionMatches.some val
75: case cons ty tys_tail' => · -- j ≠ i
76: cases tys_tail' <;> try (unfold checkPrim at hprim; contradiction) have hneq : i ≠ j := by omega
77: case cons ty' tys_tail'' => rw [List.getD_eq_getElem?_getD, List.getElem?_set_ne hneq]
78: cases ty <;> cases ty' <;> try (unfold checkPrim at hprim; contradiction) rw [List.getD_eq_getElem?_getD, List.getElem?_set_ne hneq]
79: cases hstack with exact hforall j
80: | cons val1 h1 =>
81: cases h1 with /-- Safety of checkPrim: if checkPrim succeeds, evalPrim is safe and type-matches. -/
82: | cons val2 h2 => theorem evalPrim_safety {p : Prim} {s : State} {tys : List AvmTy}
83: cases val1; cases val2 {tys' : List AvmTy} (hstack : StackMatches s.stack tys)
84: unfold checkPrim at hprim (hprim : checkPrim p tys = some tys') :
85: have heq : tys' = AvmTy.bool :: tys_tail'' := by aesop ∃ o, evalPrim p s = o ∧ SafeOutcome o ∧ (∀ s', o = Outcome.ok s' → StackMatches s'.stack tys' ∧ s'.locals = s.locals) := by
86: unfold evalPrim pop1 push1 rcases s with ⟨pc, stack, locals, halted⟩
87: refine ⟨_, rfl, ?_⟩ cases p <;> cases tys <;> try (unfold checkPrim at hprim; dsimp at hprim; contradiction)
88: rw [heq] · -- addSatQ0
89: exact StackMatches.cons (AvmVal.b _) h2 rename_i ty tys_tail
90: case addSatQ0 tys_tail => cases ty <;> try (unfold checkPrim at hprim; dsimp at hprim; contradiction)
91: cases tys_tail <;> try (unfold checkPrim at hprim; contradiction) cases tys_tail
92: case cons ty tys_tail' => · unfold checkPrim at hprim; dsimp at hprim; contradiction
93: cases tys_tail' <;> try (unfold checkPrim at hprim; contradiction) · rename_i ty2 tys_tail'
94: case cons ty' tys_tail'' => cases ty2 <;> try (unfold checkPrim at hprim; dsimp at hprim; contradiction)
95: cases ty <;> cases ty' <;> try (unfold checkPrim at hprim; contradiction) cases hstack with
96: cases hstack with | cons val1 h1 =>
97: | cons val1 h1 => cases h1 with
98: cases h1 with | cons val2 h2 =>
99: | cons val2 h2 => cases val1; cases val2
100: cases val1; cases val2 unfold checkPrim at hprim; dsimp at hprim
101: unfold checkPrim at hprim injection hprim with heq_tys'
102: have heq : tys' = AvmTy.q0_16 :: tys_tail'' := by aesop unfold evalPrim pop1 push1
103: unfold evalPrim pop1 push1 dsimp
104: refine ⟨_, rfl, ?_⟩ split
105: rw [heq] · refine ⟨_, rfl, ⟨SafeOutcome.stackOverflow, by intro s' h; contradiction⟩⟩
106: exact StackMatches.cons (AvmVal.q0 _) h2 · refine ⟨_, rfl, ⟨SafeOutcome.ok _, ?_⟩⟩
107: case subSatQ0 tys_tail => intro s' heq_s'
108: cases tys_tail <;> try (unfold checkPrim at hprim; contradiction) injection heq_s' with heq_state
109: case cons ty tys_tail' => rw [← heq_state]
110: cases tys_tail' <;> try (unfold checkPrim at hprim; contradiction) rw [← heq_tys']
111: case cons ty' tys_tail'' => exact ⟨StackMatches.cons (AvmVal.q0 _) h2, rfl⟩
112: cases ty <;> cases ty' <;> try (unfold checkPrim at hprim; contradiction) · -- subSatQ0
113: cases hstack with rename_i ty tys_tail
114: | cons val1 h1 => cases ty <;> try (unfold checkPrim at hprim; dsimp at hprim; contradiction)
115: cases h1 with cases tys_tail
116: | cons val2 h2 => · unfold checkPrim at hprim; dsimp at hprim; contradiction
117: cases val1; cases val2 · rename_i ty2 tys_tail'
118: unfold checkPrim at hprim cases ty2 <;> try (unfold checkPrim at hprim; dsimp at hprim; contradiction)
119: have heq : tys' = AvmTy.q0_16 :: tys_tail'' := by aesop cases hstack with
120: unfold evalPrim pop1 push1 | cons val1 h1 =>
121: refine ⟨_, rfl, ?_⟩ cases h1 with
122: rw [heq] | cons val2 h2 =>
123: exact StackMatches.cons (AvmVal.q0 _) h2 cases val1; cases val2
124: case addSatQ16 tys_tail => unfold checkPrim at hprim; dsimp at hprim
125: cases tys_tail <;> try (unfold checkPrim at hprim; contradiction) injection hprim with heq_tys'
126: case cons ty tys_tail' => unfold evalPrim pop1 push1
127: cases tys_tail' <;> try (unfold checkPrim at hprim; contradiction) dsimp
128: case cons ty' tys_tail'' => split
129: cases ty <;> cases ty' <;> try (unfold checkPrim at hprim; contradiction) · refine ⟨_, rfl, ⟨SafeOutcome.stackOverflow, by intro s' h; contradiction⟩⟩
130: cases hstack with · refine ⟨_, rfl, ⟨SafeOutcome.ok _, ?_⟩⟩
131: | cons val1 h1 => intro s' heq_s'
132: cases h1 with injection heq_s' with heq_state
133: | cons val2 h2 => rw [← heq_state]
134: cases val1; cases val2 rw [← heq_tys']
135: unfold checkPrim at hprim exact ⟨StackMatches.cons (AvmVal.q0 _) h2, rfl⟩
136: have heq : tys' = AvmTy.q16_16 :: tys_tail'' := by aesop · -- addSatQ16
137: unfold evalPrim pop1 push1 rename_i ty tys_tail
138: refine ⟨_, rfl, ?_⟩ cases ty <;> try (unfold checkPrim at hprim; dsimp at hprim; contradiction)
139: rw [heq] cases tys_tail
140: exact StackMatches.cons (AvmVal.q16 _) h2 · unfold checkPrim at hprim; dsimp at hprim; contradiction
141: case subSatQ16 tys_tail => · rename_i ty2 tys_tail'
142: cases tys_tail <;> try (unfold checkPrim at hprim; contradiction) cases ty2 <;> try (unfold checkPrim at hprim; dsimp at hprim; contradiction)
143: case cons ty tys_tail' => cases hstack with
144: cases tys_tail' <;> try (unfold checkPrim at hprim; contradiction) | cons val1 h1 =>
145: case cons ty' tys_tail'' => cases h1 with
146: cases ty <;> cases ty' <;> try (unfold checkPrim at hprim; contradiction) | cons val2 h2 =>
147: cases hstack with cases val1; cases val2
148: | cons val1 h1 => unfold checkPrim at hprim; dsimp at hprim
149: cases h1 with injection hprim with heq_tys'
150: | cons val2 h2 => unfold evalPrim pop1 push1
151: cases val1; cases val2 dsimp
152: unfold checkPrim at hprim split
153: have heq : tys' = AvmTy.q16_16 :: tys_tail'' := by aesop · refine ⟨_, rfl, ⟨SafeOutcome.stackOverflow, by intro s' h; contradiction⟩⟩
154: unfold evalPrim pop1 push1 · refine ⟨_, rfl, ⟨SafeOutcome.ok _, ?_⟩⟩
155: refine ⟨_, rfl, ?_⟩ intro s' heq_s'
156: rw [heq] injection heq_s' with heq_state
157: exact StackMatches.cons (AvmVal.q16 _) h2 rw [← heq_state]
158: case mulSatQ16 tys_tail => rw [← heq_tys']
159: cases tys_tail <;> try (unfold checkPrim at hprim; contradiction) exact ⟨StackMatches.cons (AvmVal.q16 _) h2, rfl⟩
160: case cons ty tys_tail' => · -- subSatQ16
161: cases tys_tail' <;> try (unfold checkPrim at hprim; contradiction) rename_i ty tys_tail
162: case cons ty' tys_tail'' => cases ty <;> try (unfold checkPrim at hprim; dsimp at hprim; contradiction)
163: cases ty <;> cases ty' <;> try (unfold checkPrim at hprim; contradiction) cases tys_tail
164: cases hstack with · unfold checkPrim at hprim; dsimp at hprim; contradiction
165: | cons val1 h1 => · rename_i ty2 tys_tail'
166: cases h1 with cases ty2 <;> try (unfold checkPrim at hprim; dsimp at hprim; contradiction)
167: | cons val2 h2 => cases hstack with
168: cases val1; cases val2 | cons val1 h1 =>
169: unfold checkPrim at hprim cases h1 with
170: have heq : tys' = AvmTy.q16_16 :: tys_tail'' := by aesop | cons val2 h2 =>
171: unfold evalPrim pop1 push1 cases val1; cases val2
172: refine ⟨_, rfl, ?_⟩ unfold checkPrim at hprim; dsimp at hprim
173: rw [heq] injection hprim with heq_tys'
174: exact StackMatches.cons (AvmVal.q16 _) h2 unfold evalPrim pop1 push1
175: case divSatQ16 tys_tail => dsimp
176: cases tys_tail <;> try (unfold checkPrim at hprim; contradiction) split
177: case cons ty tys_tail' => · refine ⟨_, rfl, ⟨SafeOutcome.stackOverflow, by intro s' h; contradiction⟩⟩
178: cases tys_tail' <;> try (unfold checkPrim at hprim; contradiction) · refine ⟨_, rfl, ⟨SafeOutcome.ok _, ?_⟩⟩
179: case cons ty' tys_tail'' => intro s' heq_s'
180: cases ty <;> cases ty' <;> try (unfold checkPrim at hprim; contradiction) injection heq_s' with heq_state
181: cases hstack with rw [← heq_state]
182: | cons val1 h1 => rw [← heq_tys']
183: cases h1 with exact ⟨StackMatches.cons (AvmVal.q16 _) h2, rfl⟩
184: | cons val2 h2 => · -- mulSatQ16
185: cases val1; cases val2 rename_i ty tys_tail
186: unfold checkPrim at hprim cases ty <;> try (unfold checkPrim at hprim; dsimp at hprim; contradiction)
187: have heq : tys' = AvmTy.q16_16 :: tys_tail'' := by aesop cases tys_tail
188: unfold evalPrim pop1 push1 · unfold checkPrim at hprim; dsimp at hprim; contradiction
189: refine ⟨_, rfl, ?_⟩ · rename_i ty2 tys_tail'
190: rw [heq] cases ty2 <;> try (unfold checkPrim at hprim; dsimp at hprim; contradiction)
191: exact StackMatches.cons (AvmVal.q16 _) h2 cases hstack with
192: case ltQ16 tys_tail => | cons val1 h1 =>
193: cases tys_tail <;> try (unfold checkPrim at hprim; contradiction) cases h1 with
194: case cons ty tys_tail' => | cons val2 h2 =>
195: cases tys_tail' <;> try (unfold checkPrim at hprim; contradiction) cases val1; cases val2
196: case cons ty' tys_tail'' => unfold checkPrim at hprim; dsimp at hprim
197: cases ty <;> cases ty' <;> try (unfold checkPrim at hprim; contradiction) injection hprim with heq_tys'
198: cases hstack with unfold evalPrim pop1 push1
199: | cons val1 h1 => dsimp
200: cases h1 with split
201: | cons val2 h2 => · refine ⟨_, rfl, ⟨SafeOutcome.stackOverflow, by intro s' h; contradiction⟩⟩
202: cases val1; cases val2 · refine ⟨_, rfl, ⟨SafeOutcome.ok _, ?_⟩⟩
203: unfold checkPrim at hprim intro s' heq_s'
204: have heq : tys' = AvmTy.bool :: tys_tail'' := by aesop injection heq_s' with heq_state
205: unfold evalPrim pop1 push1 rw [← heq_state]
206: refine ⟨_, rfl, ?_⟩ rw [← heq_tys']
207: rw [heq] exact ⟨StackMatches.cons (AvmVal.q16 _) h2, rfl⟩
208: exact StackMatches.cons (AvmVal.b _) h2 · -- divSatQ16
209: case eqQ16 tys_tail => rename_i ty tys_tail
210: cases tys_tail <;> try (unfold checkPrim at hprim; contradiction) cases ty <;> try (unfold checkPrim at hprim; dsimp at hprim; contradiction)
211: case cons ty tys_tail' => cases tys_tail
212: cases tys_tail' <;> try (unfold checkPrim at hprim; contradiction) · unfold checkPrim at hprim; dsimp at hprim; contradiction
213: case cons ty' tys_tail'' => · rename_i ty2 tys_tail'
214: cases ty <;> cases ty' <;> try (unfold checkPrim at hprim; contradiction) cases ty2 <;> try (unfold checkPrim at hprim; dsimp at hprim; contradiction)
215: cases hstack with cases hstack with
216: | cons val1 h1 => | cons val1 h1 =>
217: cases h1 with cases h1 with
218: | cons val2 h2 => | cons val2 h2 =>
219: cases val1; cases val2 cases val1; cases val2
220: unfold checkPrim at hprim unfold checkPrim at hprim; dsimp at hprim
221: have heq : tys' = AvmTy.bool :: tys_tail'' := by aesop injection hprim with heq_tys'
222: unfold evalPrim pop1 push1 unfold evalPrim pop1 push1
223: refine ⟨_, rfl, ?_⟩ dsimp
224: rw [heq] split
225: exact StackMatches.cons (AvmVal.b _) h2 · refine ⟨_, rfl, ⟨SafeOutcome.divByZero, by intro s' h; contradiction⟩⟩
226: · split
227: /-- Locals lookup safety helper. -/ · refine ⟨_, rfl, ⟨SafeOutcome.stackOverflow, by intro s' h; contradiction⟩⟩
228: theorem getLocal_safety {locals : List (Option AnyVal)} {signatures : List (Option AvmTy)} · refine ⟨_, rfl, ⟨SafeOutcome.ok _, ?_⟩⟩
229: (h : LocalsMatches locals signatures) {i : Nat} {ty : AvmTy} intro s' heq_s'
230: (hloc : signatures[i]? = some (some ty)) : injection heq_s' with heq_state
231: ∃ val : AvmVal ty, getLocal? { pc := 0, stack := [], locals := locals, halted := false } i = some ⟨ty, val⟩ := by rw [← heq_state]
232: obtain ⟨hlen, hforall⟩ := h rw [← heq_tys']
233: have hsig_eq : signatures.getD i none = some ty := by exact ⟨StackMatches.cons (AvmVal.q16 _) h2, rfl⟩
234: rw [List.getD_eq_get?_getD] · -- ltQ16
235: simp [hloc] rename_i ty tys_tail
236: have hmatches := hforall i cases ty <;> try (unfold checkPrim at hprim; dsimp at hprim; contradiction)
237: rw [hsig_eq] at hmatches cases tys_tail
238: cases hmatches with · unfold checkPrim at hprim; dsimp at hprim; contradiction
239: | some val => · rename_i ty2 tys_tail'
240: use val cases ty2 <;> try (unfold checkPrim at hprim; dsimp at hprim; contradiction)
241: unfold getLocal? cases hstack with
242: rw [List.getD_eq_get?_getD] | cons val1 h1 =>
243: -- Since OptionMatches (locals.getD i none) (some ty) was some val, cases h1 with
244: -- locals.getD i none must be some ⟨ty, val⟩. | cons val2 h2 =>
245: have hlocal_eq : locals.getD i none = some ⟨ty, val⟩ := rfl cases val1; cases val2
246: rw [← hlocal_eq] unfold checkPrim at hprim; dsimp at hprim
247: congr injection hprim with heq_tys'
248: unfold evalPrim pop1 push1
249: /-- Locals update safety helper. -/ dsimp
250: theorem setLocal_safety {locals : List (Option AnyVal)} {signatures : List (Option AvmTy)} split
251: (h : LocalsMatches locals signatures) {i : Nat} {ty : AvmTy} (val : AvmVal ty) · refine ⟨_, rfl, ⟨SafeOutcome.stackOverflow, by intro s' h; contradiction⟩⟩
252: (hbound : i < signatures.length) : · refine ⟨_, rfl, ⟨SafeOutcome.ok _, ?_⟩⟩
253: LocalsMatches (List.set locals i (some ⟨ty, val⟩)) (List.set signatures i (some ty)) := by intro s' heq_s'
254: obtain ⟨hlen, hforall⟩ := h injection heq_s' with heq_state
255: constructor rw [← heq_state]
256: · simp [hlen] rw [← heq_tys']
257: · intro j exact ⟨StackMatches.cons (AvmVal.b _) h2, rfl⟩
258: by_cases hj : j = i · -- eqQ16
259: · subst hj rename_i ty tys_tail
260: -- j = i cases ty <;> try (unfold checkPrim at hprim; dsimp at hprim; contradiction)
261: rw [List.getD_set_self (by omega), List.getD_set_self hbound] cases tys_tail
262: exact OptionMatches.some val · unfold checkPrim at hprim; dsimp at hprim; contradiction
263: · -- j ≠ i · rename_i ty2 tys_tail'
264: rw [List.getD_set_ne _ _ hj, List.getD_set_ne _ _ hj] cases ty2 <;> try (unfold checkPrim at hprim; dsimp at hprim; contradiction)
265: exact hforall j cases hstack with
266: | cons val1 h1 =>
267: /-- Type preservation theorem for single instruction step. -/ cases h1 with
268: theorem step_preservation {instr : Instr} {s : State} {tys : List AvmTy} {tys_locals : List (Option AvmTy)} | cons val2 h2 =>
269: (hstack : StackMatches s.stack tys) (hlocals : LocalsMatches s.locals tys_locals) cases val1; cases val2
270: {tys' : List AvmTy} {tys_locals' : List (Option AvmTy)} unfold checkPrim at hprim; dsimp at hprim
271: (hcheck : checkInstr instr tys tys_locals = some (tys', tys_locals')) injection hprim with heq_tys'
272: (hnon_jump : match instr with | .jump _ | .jumpIf _ | .halt => False | _ => True) : unfold evalPrim pop1 push1
273: ∃ s', step [instr] s = Outcome.ok s' ∧ StackMatches s'.stack tys' ∧ LocalsMatches s'.locals tys_locals' := by dsimp
274: cases instr split
275: case push val => · refine ⟨_, rfl, ⟨SafeOutcome.stackOverflow, by intro s' h; contradiction⟩⟩
276: unfold checkInstr at hcheck · refine ⟨_, rfl, ⟨SafeOutcome.ok _, ?_⟩⟩
277: injection hcheck with hst hloc intro s' heq_s'
278: subst hst hloc injection heq_s' with heq_state
279: unfold step pop1 push1 rw [← heq_state]
280: refine ⟨_, rfl, StackMatches.cons val.val hstack, hlocals⟩ rw [← heq_tys']
281: case pop => exact ⟨StackMatches.cons (AvmVal.b _) h2, rfl⟩
282: unfold checkInstr at hcheck · -- and
283: split at hcheck rename_i ty tys_tail
284: case h_1 x xs heq => cases ty <;> try (unfold checkPrim at hprim; dsimp at hprim; contradiction)
285: injection hcheck with hst hloc cases tys_tail
286: subst hst hloc · unfold checkPrim at hprim; dsimp at hprim; contradiction
287: cases hstack · rename_i ty2 tys_tail'
288: unfold step pop1 cases ty2 <;> try (unfold checkPrim at hprim; dsimp at hprim; contradiction)
289: refine ⟨_, rfl, by assumption, hlocals⟩ cases hstack with
290: case h_2 heq => contradiction | cons val1 h1 =>
291: case dup => cases h1 with
292: unfold checkInstr at hcheck | cons val2 h2 =>
293: split at hcheck cases val1; cases val2
294: case h_1 x xs heq => unfold checkPrim at hprim; dsimp at hprim
295: injection hcheck with hst hloc injection hprim with heq_tys'
296: subst hst hloc unfold evalPrim pop1 push1
297: cases hstack with dsimp
298: | cons val h' => split
299: unfold step pop1 · refine ⟨_, rfl, ⟨SafeOutcome.stackOverflow, by intro s' h; contradiction⟩⟩
300: refine ⟨_, rfl, ?_, hlocals⟩ · refine ⟨_, rfl, ⟨SafeOutcome.ok _, ?_⟩⟩
301: exact StackMatches.cons val (StackMatches.cons val h') intro s' heq_s'
302: case h_2 heq => contradiction injection heq_s' with heq_state
303: case swap => rw [← heq_state]
304: unfold checkInstr at hcheck rw [← heq_tys']
305: split at hcheck exact ⟨StackMatches.cons (AvmVal.b _) h2, rfl⟩
306: case h_1 x y xs heq => · -- or
307: injection hcheck with hst hloc rename_i ty tys_tail
308: subst hst hloc cases ty <;> try (unfold checkPrim at hprim; dsimp at hprim; contradiction)
309: cases hstack with cases tys_tail
310: | cons val1 h1 => · unfold checkPrim at hprim; dsimp at hprim; contradiction
311: cases h1 with · rename_i ty2 tys_tail'
312: | cons val2 h2 => cases ty2 <;> try (unfold checkPrim at hprim; dsimp at hprim; contradiction)
313: unfold step pop1 cases hstack with
314: refine ⟨_, rfl, ?_, hlocals⟩ | cons val1 h1 =>
315: exact StackMatches.cons val2 (StackMatches.cons val1 h2) cases h1 with
316: case h_2 heq => contradiction | cons val2 h2 =>
317: case load i => cases val1; cases val2
318: unfold checkInstr at hcheck unfold checkPrim at hprim; dsimp at hprim
319: split at hcheck injection hprim with heq_tys'
320: case h_1 ty heq => unfold evalPrim pop1 push1
321: injection hcheck with hst hloc dsimp
322: subst hst hloc split
323: obtain ⟨val, hloc_val⟩ := getLocal_safety hlocals heq · refine ⟨_, rfl, ⟨SafeOutcome.stackOverflow, by intro s' h; contradiction⟩⟩
324: unfold step pop1 · refine ⟨_, rfl, ⟨SafeOutcome.ok _, ?_⟩⟩
325: refine ⟨_, ?_, ?_, hlocals⟩ intro s' heq_s'
326: · unfold getLocal?; rw [hloc_val]; rfl injection heq_s' with heq_state
327: · exact StackMatches.cons val hstack rw [← heq_state]
328: case h_2 heq => contradiction rw [← heq_tys']
329: case store i => exact ⟨StackMatches.cons (AvmVal.b _) h2, rfl⟩
330: unfold checkInstr at hcheck · -- not
331: split at hcheck rename_i ty tys_tail
332: case inl hbound => cases ty <;> try (unfold checkPrim at hprim; dsimp at hprim; contradiction)
333: split at hcheck cases hstack with
334: case h_1 ty tys_tail heq => | cons val h' =>
335: injection hcheck with hst hloc cases val
336: subst hst hloc unfold checkPrim at hprim; dsimp at hprim
337: cases hstack with injection hprim with heq_tys'
338: | cons val h' => unfold evalPrim pop1 push1
339: unfold step pop1 setLocal dsimp
340: obtain ⟨hlen, _⟩ := hlocals split
341: have hbound_locals : i < s.locals.length := by omega · refine ⟨_, rfl, ⟨SafeOutcome.stackOverflow, by intro s' h; contradiction⟩⟩
342: rw [if_pos hbound_locals] · refine ⟨_, rfl, ⟨SafeOutcome.ok _, ?_⟩⟩
343: refine ⟨_, rfl, h', setLocal_safety hlocals val hbound⟩ intro s' heq_s'
344: case h_2 heq => contradiction injection heq_s' with heq_state
345: case inr hbound => contradiction rw [← heq_state]
346: case jump target => contradiction rw [← heq_tys']
347: case jumpIf target => contradiction exact ⟨StackMatches.cons (AvmVal.b _) h', rfl⟩
348: case prim p =>
349: unfold checkInstr at hcheck /-- Type preservation theorem for single instruction step. -/
350: split at hcheck theorem step_preservation {instr : Instr} {s : State} {tys : List AvmTy} {tys_locals : List (Option AvmTy)}
351: case h_1 stack' heq => (hstack : StackMatches s.stack tys) (hlocals : LocalsMatches s.locals tys_locals)
352: injection hcheck with hst hloc (hpc : s.pc = 0) (hhalt : s.halted = false)
353: subst hst hloc {tys' : List AvmTy} {tys_locals' : List (Option AvmTy)}
354: obtain ⟨s', heval, hst'⟩ := evalPrim_safety hstack heq (hcheck : checkInstr instr tys tys_locals = some (tys', tys_locals'))
355: unfold step (hnon_jump : match instr with | .jump _ | .jumpIf _ | .halt => False | _ => True) :
356: refine ⟨s', ?_, hst', hlocals⟩ ∃ o, step [instr] s = o ∧ SafeOutcome o ∧ (∀ s', o = Outcome.ok s' → StackMatches s'.stack tys' ∧ LocalsMatches s'.locals tys_locals') := by
357: rw [heval] rcases s with ⟨pc, stack, locals, halted⟩
358: case h_2 heq => contradiction subst hpc hhalt
359: case halt => contradiction cases instr
360: case push val =>
361: end SilverSight.AVMIsa unfold checkInstr at hcheck
injection hcheck with h
injection h with hst hloc
subst hst hloc
unfold step pop1
simp
split
· refine ⟨SafeOutcome.stackOverflow, by intro s' h; contradiction⟩
· refine ⟨SafeOutcome.ok _, ?_⟩
intro s' heq_s'
injection heq_s' with heq_state
rw [← heq_state]
exact ⟨StackMatches.cons val.val hstack, hlocals⟩
case pop =>
unfold checkInstr at hcheck
dsimp at hcheck
split at hcheck
case h_1 x xs heq =>
injection hcheck with h
injection h with hst hloc
subst hst hloc
cases hstack
unfold step pop1
simp
refine ⟨SafeOutcome.ok _, ⟨by assumption, hlocals⟩⟩
case h_2 heq => contradiction
case dup =>
unfold checkInstr at hcheck
dsimp at hcheck
split at hcheck
case h_1 x xs heq =>
injection hcheck with h
injection h with hst hloc
subst hst hloc
cases hstack with
| cons val h' =>
unfold step pop1
simp
split
· refine ⟨SafeOutcome.stackOverflow, by intro s' h; contradiction⟩
· refine ⟨SafeOutcome.ok _, ?_⟩
intro s' heq_s'
injection heq_s' with heq_state
rw [← heq_state]
exact ⟨StackMatches.cons val (StackMatches.cons val h'), hlocals⟩
case h_2 heq => contradiction
case swap =>
unfold checkInstr at hcheck
dsimp at hcheck
split at hcheck
case h_1 x y xs heq =>
injection hcheck with h
injection h with hst hloc
subst hst hloc
cases hstack with
| cons val1 h1 =>
cases h1 with
| cons val2 h2 =>
unfold step pop1
simp
refine ⟨SafeOutcome.ok _, ⟨StackMatches.cons val2 (StackMatches.cons val1 h2), hlocals⟩⟩
case h_2 heq => contradiction
case load i =>
unfold checkInstr at hcheck
dsimp at hcheck
split at hcheck <;> try contradiction
rename_i ty heq
injection hcheck with h
injection h with hst hloc
subst hst hloc
obtain ⟨val, hloc_val⟩ := getLocal_safety hlocals i heq
simp [getLocal?] at hloc_val
unfold step pop1 getLocal?
simp
rw [hloc_val]
simp
split
· refine ⟨SafeOutcome.stackOverflow, by intro s' h; contradiction⟩
· refine ⟨SafeOutcome.ok _, ?_⟩
intro s' heq_s'
injection heq_s' with heq_state
rw [← heq_state]
exact ⟨StackMatches.cons val hstack, hlocals⟩
case store i =>
unfold checkInstr at hcheck
dsimp at hcheck
split at hcheck
· -- isTrue
rename_i hbound
split at hcheck
case h_1 ty tys_tail heq =>
injection hcheck with h
injection h with hst hloc
subst hst hloc
cases hstack with
| cons val h' =>
unfold step pop1 setLocal?
simp
have hbound_locals : i < locals.length := by
rw [hlocals.1]
exact hbound
rw [if_pos hbound_locals]
simp
refine ⟨SafeOutcome.ok _, ⟨h', setLocal_safety hlocals i val hbound⟩⟩
case h_2 heq => contradiction
· -- isFalse
contradiction
case jump target => contradiction
case jumpIf target => contradiction
case prim p =>
unfold checkInstr at hcheck
dsimp at hcheck
split at hcheck
case h_1 stack' heq =>
injection hcheck with h
injection h with hst hloc
subst hst hloc
obtain ⟨o, heval, hsafe, hst'⟩ := evalPrim_safety hstack heq
unfold step
have hlookup : [Instr.prim p][0]? = some (Instr.prim p) := rfl
rw [hlookup]
simp
rw [heval]
cases o
case ok s1 =>
refine ⟨SafeOutcome.ok _, ?_⟩
intro s' heq_s'
injection heq_s' with heq_state
rw [← heq_state]
obtain ⟨hst_matches, hlocals_eq⟩ := hst' s1 rfl
dsimp at hlocals hlocals_eq ⊢
rw [hlocals_eq]
exact ⟨hst_matches, hlocals⟩
case err e =>
refine ⟨hsafe, by intro s' h; contradiction⟩
case h_2 heq => contradiction
case halt => contradiction
end SilverSight.AVMIsa