import TsmLean.Core.TypeSoundness namespace TsmLean.Core /-! # Preservation and progress for TSM. Local (per-instruction) preservation: if the stack matches an instruction's input type and that instruction succeeds, the post-stack matches its output type. Global type soundness — that *every* reachable PC has a consistent stackmap — requires program-wide code typing (JVM-style stackmaps). That's a layer above; this file proves the per-instruction theorem on which the global one is built. Progress: well-typed non-halt instructions always make a step. -/ theorem stack_preservation {s s' : State} {in_ty out_ty : StackTy} (h_pc : s.pc < s.code.size) (h_typed : HasTypeInstr (s.code[s.pc]'h_pc) in_ty out_ty) (h_stack : HasTypeStack s.stack in_ty) (h_step : step s = some s') : HasTypeStack s'.stack out_ty := by unfold step at h_step rw [dif_pos h_pc] at h_step generalize h_at : s.code[s.pc]'h_pc = instr at h_typed h_step generalize h_stk : s.stack = stk at h_stack h_step cases h_typed with | push n => simp at h_step obtain ⟨_, rfl⟩ := h_step exact .cons (.vInt n) h_stack | pushB b => simp at h_step obtain ⟨_, rfl⟩ := h_step exact .cons (.vBool b) h_stack | pop => cases h_stack with | cons _ hs => simp at h_step obtain ⟨_, rfl⟩ := h_step exact hs | dup => cases h_stack with | cons hv hs => simp at h_step obtain ⟨_, rfl⟩ := h_step exact .cons hv (.cons hv hs) | swap => cases h_stack with | cons hv1 h_rest => cases h_rest with | cons hv2 hs => simp at h_step obtain ⟨_, rfl⟩ := h_step exact .cons hv2 (.cons hv1 hs) | add => cases h_stack with | cons hv1 h1 => cases hv1 with | vInt a => cases h1 with | cons hv2 hs => cases hv2 with | vInt b => simp at h_step obtain ⟨_, rfl⟩ := h_step exact .cons (.vInt _) hs | sub => cases h_stack with | cons hv1 h1 => cases hv1 with | vInt a => cases h1 with | cons hv2 hs => cases hv2 with | vInt b => simp at h_step obtain ⟨_, rfl⟩ := h_step exact .cons (.vInt _) hs | mul => cases h_stack with | cons hv1 h1 => cases hv1 with | vInt a => cases h1 with | cons hv2 hs => cases hv2 with | vInt b => simp at h_step obtain ⟨_, rfl⟩ := h_step exact .cons (.vInt _) hs | eq_int => cases h_stack with | cons hv1 h1 => cases hv1 with | vInt a => cases h1 with | cons hv2 hs => cases hv2 with | vInt b => simp at h_step obtain ⟨_, rfl⟩ := h_step exact .cons (.vBool _) hs | lt_int => cases h_stack with | cons hv1 h1 => cases hv1 with | vInt a => cases h1 with | cons hv2 hs => cases hv2 with | vInt b => simp at h_step obtain ⟨_, rfl⟩ := h_step exact .cons (.vBool _) hs | jmp => simp at h_step obtain ⟨_, rfl⟩ := h_step exact h_stack | jmpFalse => cases h_stack with | cons hv hs => cases hv with | vBool b => cases b with | false => simp at h_step obtain ⟨_, rfl⟩ := h_step exact hs | true => simp at h_step obtain ⟨_, rfl⟩ := h_step exact hs | halt => simp at h_step theorem progress {s : State} {in_ty out_ty : StackTy} (h_pc : s.pc < s.code.size) (h_typed : HasTypeInstr (s.code[s.pc]'h_pc) in_ty out_ty) (h_stack : HasTypeStack s.stack in_ty) (h_not_halt : s.code[s.pc]'h_pc ≠ .halt) : ∃ s', step s = some s' := by unfold step rw [dif_pos h_pc] generalize h_at : s.code[s.pc]'h_pc = instr at h_typed h_not_halt generalize h_stk : s.stack = stk at h_stack cases h_typed with | push n => exact ⟨_, rfl⟩ | pushB b => exact ⟨_, rfl⟩ | pop => cases h_stack with | cons _ _ => exact ⟨_, rfl⟩ | dup => cases h_stack with | cons _ _ => exact ⟨_, rfl⟩ | swap => cases h_stack with | cons _ h1 => cases h1 with | cons _ _ => exact ⟨_, rfl⟩ | add => cases h_stack with | cons hv1 h1 => cases hv1 with | vInt _ => cases h1 with | cons hv2 _ => cases hv2 with | vInt _ => exact ⟨_, rfl⟩ | sub => cases h_stack with | cons hv1 h1 => cases hv1 with | vInt _ => cases h1 with | cons hv2 _ => cases hv2 with | vInt _ => exact ⟨_, rfl⟩ | mul => cases h_stack with | cons hv1 h1 => cases hv1 with | vInt _ => cases h1 with | cons hv2 _ => cases hv2 with | vInt _ => exact ⟨_, rfl⟩ | eq_int => cases h_stack with | cons hv1 h1 => cases hv1 with | vInt _ => cases h1 with | cons hv2 _ => cases hv2 with | vInt _ => exact ⟨_, rfl⟩ | lt_int => cases h_stack with | cons hv1 h1 => cases hv1 with | vInt _ => cases h1 with | cons hv2 _ => cases hv2 with | vInt _ => exact ⟨_, rfl⟩ | jmp => exact ⟨_, rfl⟩ | jmpFalse => cases h_stack with | cons hv _ => cases hv with | vBool b => cases b <;> exact ⟨_, rfl⟩ | halt => exact absurd rfl h_not_halt end TsmLean.Core