Download bcpl/BCPL/Semantics.lean from Snapkitty/ai-free: direct link, hf CLI and curl.
- Browser
- Download file 7.55 kB
-
https://huggingface.co/Snapkitty/ai-free/resolve/main/bcpl/BCPL/Semantics.lean
- Command line
-
hf download hf://Snapkitty/ai-free/bcpl/BCPL/Semantics.lean
-
curl -L -o Semantics.lean https://huggingface.co/Snapkitty/ai-free/resolve/main/bcpl/BCPL/Semantics.lean
7.55 kB
| import WordDialect | |
| import WordIR | |
| /-! | |
| # BCPL.Semantics | |
| Abstract syntax and reference semantics of the supported BCPL subset. Defined directly on | |
| word-addressed memory, with no reference to the machine or the IR; the lowering is proved | |
| correct against this definition. | |
| BCPL is typeless: every value is a word, a variable is a memory cell, and `!e` / `@x` are | |
| word indirection and address-of. Variable `x` lives at address `addr x` (the global vector). | |
| Conventions: | |
| * Relational operators yield BCPL truth values: `-1` (true) and `0` (false). | |
| * A condition is true iff its value is nonzero. | |
| * `/` is signed division truncating toward zero; division by zero traps. | |
| * `<<` and `>>` are logical shifts. | |
| * Order of evaluation is fixed: left operand before right; in `lhs := rhs`, the right-hand | |
| side is evaluated before an indirect left-hand side. | |
| -/ | |
| namespace WordDialect | |
| namespace BCPL | |
| open IR | |
| abbrev Var := Nat | |
| inductive BinOp where | |
| | add | sub | mul | div | |
| | and | or | neqv | |
| | shl | shr | |
| | eq | ne | lt | gt | le | ge | |
| inductive UnOp where | |
| | neg | not | |
| inductive Expr where | |
| | num (z : Int) | |
| | var (x : Var) | |
| | addrOf (x : Var) | |
| | rv (e : Expr) | |
| | un (o : UnOp) (e : Expr) | |
| | bin (o : BinOp) (a b : Expr) | |
| inductive LVal where | |
| | var (x : Var) | |
| | rv (e : Expr) | |
| inductive Stmt where | |
| | skip | |
| | assign (l : LVal) (e : Expr) | |
| | seq (a b : Stmt) | |
| | test (c : Expr) (t e : Stmt) | |
| | while (c : Expr) (body : Stmt) | |
| def readW {n : Nat} (m : Memory n) (a : Word n) : Except Trap (Word n) := | |
| match m.read? a with | |
| | some v => .ok v | |
| | none => .error .badAddress | |
| def writeW {n : Nat} (m : Memory n) (a v : Word n) : Except Trap (Memory n) := | |
| match m.write? a v with | |
| | some m' => .ok m' | |
| | none => .error .badAddress | |
| namespace BinOp | |
| def sem {n : Nat} : BinOp β Word n β Word n β Except Trap (Word n) | |
| | .add, a, b => .ok (a + b) | |
| | .sub, a, b => .ok (a - b) | |
| | .mul, a, b => .ok (a * b) | |
| | .div, a, b => if b = 0#n then .error .divideByZero else .ok (a.sdiv b) | |
| | .and, a, b => .ok (a &&& b) | |
| | .or, a, b => .ok (a ||| b) | |
| | .neqv, a, b => .ok (a ^^^ b) | |
| | .shl, a, b => .ok (Word.shl a b) | |
| | .shr, a, b => .ok (Word.shr a b) | |
| | .eq, a, b => .ok (flag (Cond.eval .eq a b)) | |
| | .ne, a, b => .ok (flag (Cond.eval .ne a b)) | |
| | .lt, a, b => .ok (flag (Cond.eval .slt a b)) | |
| | .gt, a, b => .ok (flag (Cond.eval .sgt a b)) | |
| | .le, a, b => .ok (flag (Cond.eval .sle a b)) | |
| | .ge, a, b => .ok (flag (Cond.eval .sge a b)) | |
| end BinOp | |
| namespace UnOp | |
| def sem {n : Nat} : UnOp β Word n β Word n | |
| | .neg, v => 0#n - v | |
| | .not, v => ~~~v | |
| end UnOp | |
| /-- Expression evaluation. Expressions read memory but never write it. -/ | |
| def evalE {n : Nat} (addr : Var β Word n) : Expr β Memory n β Except Trap (Word n) | |
| | .num z, _ => .ok (BitVec.ofInt n z) | |
| | .var x, m => readW m (addr x) | |
| | .addrOf x, _ => .ok (addr x) | |
| | .rv e, m => | |
| match evalE addr e m with | |
| | .error t => .error t | |
| | .ok a => readW m a | |
| | .un o e, m => | |
| match evalE addr e m with | |
| | .error t => .error t | |
| | .ok v => .ok (o.sem v) | |
| | .bin o a b, m => | |
| match evalE addr a m with | |
| | .error t => .error t | |
| | .ok va => | |
| match evalE addr b m with | |
| | .error t => .error t | |
| | .ok vb => o.sem va vb | |
| def assignSem {n : Nat} (addr : Var β Word n) (l : LVal) (e : Expr) (m : Memory n) : | |
| Except Trap (Memory n) := | |
| match evalE addr e m with | |
| | .error t => .error t | |
| | .ok v => | |
| match l with | |
| | .var x => writeW m (addr x) v | |
| | .rv a => | |
| match evalE addr a m with | |
| | .error t => .error t | |
| | .ok a' => writeW m a' v | |
| /-- Big-step statement semantics. Non-terminating runs have no derivation. -/ | |
| inductive Exec {n : Nat} (addr : Var β Word n) : Stmt β Memory n β Except Trap (Memory n) β Prop where | |
| | skip {m} : Exec addr .skip m (.ok m) | |
| | assign {l e m r} : assignSem addr l e m = r β Exec addr (.assign l e) m r | |
| | seqOk {a b m m1 r} : Exec addr a m (.ok m1) β Exec addr b m1 r β Exec addr (.seq a b) m r | |
| | seqErr {a b m t} : Exec addr a m (.error t) β Exec addr (.seq a b) m (.error t) | |
| | testErr {c t e m x} : evalE addr c m = .error x β Exec addr (.test c t e) m (.error x) | |
| | testTrue {c t e m v r} : | |
| evalE addr c m = .ok v β Word.isTrue v = true β Exec addr t m r β Exec addr (.test c t e) m r | |
| | testFalse {c t e m v r} : | |
| evalE addr c m = .ok v β Word.isTrue v = false β Exec addr e m r β Exec addr (.test c t e) m r | |
| | whileErr {c body m x} : evalE addr c m = .error x β Exec addr (.while c body) m (.error x) | |
| | whileExit {c body m v} : | |
| evalE addr c m = .ok v β Word.isTrue v = false β Exec addr (.while c body) m (.ok m) | |
| | whileBodyErr {c body m v x} : | |
| evalE addr c m = .ok v β Word.isTrue v = true β Exec addr body m (.error x) β | |
| Exec addr (.while c body) m (.error x) | |
| | whileAgain {c body m v m1 r} : | |
| evalE addr c m = .ok v β Word.isTrue v = true β Exec addr body m (.ok m1) β | |
| Exec addr (.while c body) m1 r β Exec addr (.while c body) m r | |
| /-- The statement semantics is functional: a statement and a memory determine the result. -/ | |
| theorem Exec.deterministic {n : Nat} {addr : Var β Word n} {s : Stmt} {m : Memory n} | |
| {rβ rβ : Except Trap (Memory n)} (hβ : Exec addr s m rβ) (hβ : Exec addr s m rβ) : | |
| rβ = rβ := by | |
| induction hβ generalizing rβ with | |
| | skip => cases hβ; rfl | |
| | assign hr => cases hβ with | assign hr' => rw [β hr, β hr'] | |
| | seqOk ha hb iha ihb => | |
| cases hβ with | |
| | seqOk ha' hb' => have := iha ha'; cases this; exact ihb hb' | |
| | seqErr ha' => have := iha ha'; cases this | |
| | seqErr ha iha => | |
| cases hβ with | |
| | seqOk ha' _ => have := iha ha'; cases this | |
| | seqErr ha' => have := iha ha'; cases this; rfl | |
| | testErr hc => | |
| cases hβ with | |
| | testErr hc' => rw [hc] at hc'; cases hc'; rfl | |
| | testTrue hc' => rw [hc] at hc'; cases hc' | |
| | testFalse hc' => rw [hc] at hc'; cases hc' | |
| | testTrue hc ht _ ih => | |
| cases hβ with | |
| | testErr hc' => rw [hc] at hc'; cases hc' | |
| | testTrue hc' _ h' => exact ih h' | |
| | testFalse hc' hf _ => rw [hc] at hc'; cases hc'; rw [ht] at hf; cases hf | |
| | testFalse hc hf _ ih => | |
| cases hβ with | |
| | testErr hc' => rw [hc] at hc'; cases hc' | |
| | testTrue hc' ht _ => rw [hc] at hc'; cases hc'; rw [hf] at ht; cases ht | |
| | testFalse hc' _ h' => exact ih h' | |
| | whileErr hc => | |
| cases hβ with | |
| | whileErr hc' => rw [hc] at hc'; cases hc'; rfl | |
| | whileExit hc' => rw [hc] at hc'; cases hc' | |
| | whileBodyErr hc' => rw [hc] at hc'; cases hc' | |
| | whileAgain hc' => rw [hc] at hc'; cases hc' | |
| | whileExit hc hf => | |
| cases hβ with | |
| | whileErr hc' => rw [hc] at hc'; cases hc' | |
| | whileExit => rfl | |
| | whileBodyErr hc' ht => rw [hc] at hc'; cases hc'; rw [hf] at ht; cases ht | |
| | whileAgain hc' ht => rw [hc] at hc'; cases hc'; rw [hf] at ht; cases ht | |
| | whileBodyErr hc ht hb ihb => | |
| cases hβ with | |
| | whileErr hc' => rw [hc] at hc'; cases hc' | |
| | whileExit hc' hf => rw [hc] at hc'; cases hc'; rw [ht] at hf; cases hf | |
| | whileBodyErr _ _ hb' => have := ihb hb'; cases this; rfl | |
| | whileAgain _ _ hb' => have := ihb hb'; cases this | |
| | whileAgain hc ht hb hl ihb ihl => | |
| cases hβ with | |
| | whileErr hc' => rw [hc] at hc'; cases hc' | |
| | whileExit hc' hf => rw [hc] at hc'; cases hc'; rw [ht] at hf; cases hf | |
| | whileBodyErr _ _ hb' => have := ihb hb'; cases this | |
| | whileAgain _ _ hb' hl' => have := ihb hb'; cases this; exact ihl hl' | |
| end BCPL | |
| end WordDialect | |