crosslang/tsm-lean/TsmLean/Core/Preservation.lean
Maximus Gorog bd2e14214d Add 'tsm-lean/' from commit '2e9061abead6f2daa464b39a79c17a949db30785'
git-subtree-dir: tsm-lean
git-subtree-mainline: 6592cd058d
git-subtree-split: 2e9061abea
2026-05-12 02:59:14 -06:00

203 lines
5.4 KiB
Text

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