crosslang/golang-lean/GolangLean/Core/Semantics.lean
Maximus Gorog fd3d42ae33 Add 'golang-lean/' from commit 'f5f17019224c6a6c319387214ceb8e29d09251c6'
git-subtree-dir: golang-lean
git-subtree-mainline: 6487c7046f
git-subtree-split: f5f1701922
2026-05-12 02:59:14 -06:00

130 lines
4.4 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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!"<closure λ {x}. ...>"
| .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