crosslang/tsm-lean/TsmLean/Core/Semantics.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

80 lines
2.7 KiB
Text

import TsmLean.Core.Syntax
namespace TsmLean.Core
/-! # Small-step operational semantics for TSM.
State = `(Code, PC, Stack)`. The stack is `List Value` (top-of-stack at
the head). Step is a *function* `State → Option State`:
* `some s'` : the next state.
* `none` : halted, OOB, or stuck (type error).
Compare with TGC/TOC's big-step `Env → Term → Value → Env → Prop`:
TSM uses small-step because instructions are atomic. The reflexive-
transitive closure (`MultiStep`) is the analogue of big-step. -/
structure State where
code : Code
pc : Nat
stack : List Value
deriving Repr, Inhabited
def step (s : State) : Option State :=
if h : s.pc < s.code.size then
match s.code[s.pc] with
| .push n => some { s with pc := s.pc + 1, stack := .vInt n :: s.stack }
| .pushB b => some { s with pc := s.pc + 1, stack := .vBool b :: s.stack }
| .pop =>
match s.stack with
| _ :: rest => some { s with pc := s.pc + 1, stack := rest }
| [] => none
| .dup =>
match s.stack with
| v :: rest => some { s with pc := s.pc + 1, stack := v :: v :: rest }
| [] => none
| .swap =>
match s.stack with
| a :: b :: rest => some { s with pc := s.pc + 1, stack := b :: a :: rest }
| _ => none
| .add =>
match s.stack with
| .vInt a :: .vInt b :: rest =>
some { s with pc := s.pc + 1, stack := .vInt (b + a) :: rest }
| _ => none
| .sub =>
match s.stack with
| .vInt a :: .vInt b :: rest =>
some { s with pc := s.pc + 1, stack := .vInt (b - a) :: rest }
| _ => none
| .mul =>
match s.stack with
| .vInt a :: .vInt b :: rest =>
some { s with pc := s.pc + 1, stack := .vInt (b * a) :: rest }
| _ => none
| .eq =>
match s.stack with
| .vInt a :: .vInt b :: rest =>
some { s with pc := s.pc + 1, stack := .vBool (b == a) :: rest }
| _ => none
| .lt =>
match s.stack with
| .vInt a :: .vInt b :: rest =>
some { s with pc := s.pc + 1, stack := .vBool (b < a) :: rest }
| _ => none
| .jmp k => some { s with pc := k }
| .jmpFalse k =>
match s.stack with
| .vBool false :: rest => some { s with pc := k, stack := rest }
| .vBool true :: rest => some { s with pc := s.pc + 1, stack := rest }
| _ => none
| .halt => none
else none
/-- Reflexive-transitive closure of `step`. -/
inductive MultiStep : State → State → Prop where
| refl (s : State) : MultiStep s s
| cons {s s' s'' : State}
(h₁ : step s = some s') (h₂ : MultiStep s' s'') :
MultiStep s s''
end TsmLean.Core