Side-by-side comparisons of Go syntax with two Lean encodings:
* Surface AST (GolangLean.Expr) — mirrors go/ast.Node from upstream.
* Tiny Go Core (GolangLean.Core.Term) — kernel calculus with proven
operational + type semantics.
Twelve sections covering: literals, arithmetic, comparison, conditional,
variables/let-binding, functions/application, references/deref/assign,
sequencing. Each example includes a `#eval` running the term through
the proven Core.eval; output matches what's expected at run time.
Demonstrated programs:
- `(5 + 3) * 2` → 16
- `let x = 3 in let y = 7 in x < y` → true
- `(λ x. x*2) 21` → 42
- `let double = λ x. x*2 in double (double 5)` → 20
- `let p = &42 in *p = 100; *p` → 100 (heap: [vInt 100])
- higher-order: `(λ f. λ x. f (f x)) double 3` → 12
Each #eval is a runtime witness for a Core.BigStep derivation. Apply
Core.eval_sound to get a proof of the BigStep relation, and
Core.preservation to get the value's type.
Supporting changes:
- Added Repr instances for Core.Value and Core.EnvList (manual,
handling the mutual inductive — derive doesn't compose across the
mutual block).
- Added RosettaStone as a lean_lib in lakefile.toml.
130 lines
4.4 KiB
Text
130 lines
4.4 KiB
Text
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
|