import GolangLean.Core.Syntax namespace GolangLean.Core /-! # Big-step operational semantics for Tiny Go Core. State is `Heap × Env`. The heap is an `Array Value`; references are indices. Env is a list of (name, value) bindings — innermost shadowing outermost. Closures capture the env at the point of `lam`-evaluation (lexical scope, as in Go). The relation is BigStep h env e v h' read "starting from heap `h` and env `env`, term `e` evaluates to value `v` and produces heap `h'`". One inductive constructor per syntactic form. Every premise either appeals to `BigStep` recursively or to a total side-condition (lookup, binop application, bounds). -/ mutual inductive Value where | vUnit : Value | vInt : Int → Value | vBool : Bool → Value | vClos : String → Term → EnvList → Value | vLoc : Nat → Value inductive EnvList where | nil : EnvList | cons : String → Value → EnvList → EnvList end mutual partial def Value.repr : Value → Std.Format | .vUnit => "vUnit" | .vInt n => f!"vInt {n}" | .vBool b => f!"vBool {b}" | .vClos x _ _ => f!"" | .vLoc n => f!"vLoc {n}" partial def EnvList.repr : EnvList → Std.Format | .nil => "[]" | .cons k v r => f!"{k}↦{Value.repr v} :: {EnvList.repr r}" end instance : Repr Value where reprPrec v _ := Value.repr v instance : Repr EnvList where reprPrec env _ := EnvList.repr env abbrev Env := EnvList abbrev Heap := Array Value namespace EnvList def lookup : EnvList → String → Option Value | .nil, _ => none | .cons k v r, x => if k = x then some v else lookup r x def extend (env : EnvList) (x : String) (v : Value) : EnvList := .cons x v env end EnvList namespace BinOp def apply : BinOp → Value → Value → Option Value | .add, .vInt a, .vInt b => some (.vInt (a + b)) | .sub, .vInt a, .vInt b => some (.vInt (a - b)) | .mul, .vInt a, .vInt b => some (.vInt (a * b)) | .eq, .vInt a, .vInt b => some (.vBool (a == b)) | .eq, .vBool a, .vBool b => some (.vBool (a == b)) | .lt, .vInt a, .vInt b => some (.vBool (a < b)) | _, _, _ => none end BinOp inductive BigStep : Heap → Env → Term → Value → Heap → Prop where | unitR {h env} : BigStep h env .unitT .vUnit h | intLitR {h env} (n : Int) : BigStep h env (.intLit n) (.vInt n) h | boolLitR {h env} (b : Bool) : BigStep h env (.boolLit b) (.vBool b) h | varR {h env x v} (hLook : env.lookup x = some v) : BigStep h env (.var x) v h | lamR {h env} (x : String) (body : Term) : BigStep h env (.lam x body) (.vClos x body env) h | appR {h env e1 e2 x body env' v_arg v h1 h2 h3} (D1 : BigStep h env e1 (.vClos x body env') h1) (D2 : BigStep h1 env e2 v_arg h2) (Db : BigStep h2 (env'.extend x v_arg) body v h3) : BigStep h env (.app e1 e2) v h3 | letInR {h env x e1 e2 v1 v2 h1 h2} (D1 : BigStep h env e1 v1 h1) (D2 : BigStep h1 (env.extend x v1) e2 v2 h2) : BigStep h env (.letIn x e1 e2) v2 h2 | ifTR {h env e e1 e2 v h1 h2} (Dc : BigStep h env e (.vBool true) h1) (Dt : BigStep h1 env e1 v h2) : BigStep h env (.ifte e e1 e2) v h2 | ifFR {h env e e1 e2 v h1 h2} (Dc : BigStep h env e (.vBool false) h1) (Df : BigStep h1 env e2 v h2) : BigStep h env (.ifte e e1 e2) v h2 | binopR {h env op e1 e2 v1 v2 v h1 h2} (D1 : BigStep h env e1 v1 h1) (D2 : BigStep h1 env e2 v2 h2) (Hop : op.apply v1 v2 = some v) : BigStep h env (.binop op e1 e2) v h2 | refMkR {h env e v h1} (D : BigStep h env e v h1) : BigStep h env (.refMk e) (.vLoc h1.size) (h1.push v) | derefR {h env e loc v h1} (D : BigStep h env e (.vLoc loc) h1) (Hget : h1[loc]? = some v) : BigStep h env (.deref e) v h1 | assignR {h env e1 e2 loc v h1 h2} (D1 : BigStep h env e1 (.vLoc loc) h1) (D2 : BigStep h1 env e2 v h2) (Hin : loc < h2.size) : BigStep h env (.assign e1 e2) .vUnit (h2.set! loc v) | seqR {h env e1 e2 v1 v2 h1 h2} (D1 : BigStep h env e1 v1 h1) (D2 : BigStep h1 env e2 v2 h2) : BigStep h env (.seq e1 e2) v2 h2 end GolangLean.Core