80 lines
2.7 KiB
Text
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
|