Structured word-RAM programs #
Flat programs (Cslib.WordRAM.Program) are lists of instructions with numeric jump targets,
which is inconvenient to write and to reason about. A structured program
(Cslib.WordRAM.Code) is built from data instructions by sequencing, conditionals and while
loops on the comparisons of Cslib.WordRAM.Cond. It has a big-step semantics
(Cslib.WordRAM.Exec) that counts exactly the instructions of the flat program it compiles to
(Cslib.WordRAM.Code.assemble, Cslib.WordRAM.Exec.runs): a conditional costs one branch
instruction, plus a jump when the second alternative runs, and a loop costs a branch and a jump
per test. No rule executes a Lean function as one instruction.
Proofs about structured programs mostly need upper bounds on time rather than exact counts,
and Cslib.WordRAM.ExecWithin packages these. Its rules compose like Hoare logic, with time
bounds added along sequences:
Cslib.WordRAM.ExecWithin.const,….alu,….copy,….load,….store: forward rules for the data instructions, with the resulting data in closed form, and….bin,….widthfor the operations of the standard basis;Cslib.WordRAM.ExecWithin.seq,….branch_pos,….branch_neg: sequencing and conditionals;Cslib.WordRAM.ExecWithin.loop: a loop through an explicit family of states, andCslib.WordRAM.ExecWithin.loop_invariant: a loop with an invariant and a decreasing measure, whose iterations are counted by the measure.
Loop-free code can instead be executed symbolically: Cslib.WordRAM.Code.eval is a structurally
recursive interpreter, so simp and decide evaluate it, and Cslib.WordRAM.Exec.of_eval turns
its result into an execution.
Subprograms are reused through Cslib.WordRAM.Code.rename, which runs a program on any
injectively chosen registers of a larger register file and leaves the others untouched
(Cslib.WordRAM.Exec.rename).
Main definitions #
Cslib.WordRAM.Code,Cslib.WordRAM.Code.size,Cslib.WordRAM.Code.ReadsWidth,Cslib.WordRAM.Code.IsRandFree: structured programs over a basis, the length of the flat program they compile to, whether a program reads the word size, and whether it avoidsCode.rand.Cslib.WordRAM.Exec,Cslib.WordRAM.ExecWithin: executions with an exact instruction count, and within a time bound.Cslib.WordRAM.Code.evalLoop,Cslib.WordRAM.Code.eval: an interpreter with a budget of loop iterations.Cslib.WordRAM.Op.dest,Cslib.WordRAM.Code.Preserves: written register of a data instruction and register preservation predicate.Cslib.WordRAM.Data.comap,Cslib.WordRAM.Data.extend,Cslib.WordRAM.Op.rename,Cslib.WordRAM.Cond.rename,Cslib.WordRAM.Code.rename: running a program on other registers.
Main results #
Cslib.WordRAM.Exec.unique: executions are deterministic.Cslib.WordRAM.Exec.of_eval: the interpreter only finds executions.Cslib.WordRAM.ExecWithin.loop_invariant: the loop rule with an invariant and a measure.Cslib.WordRAM.ExecWithin.loop_potential: the loop rule with an invariant and a potential that pays for iterations of different times.Cslib.WordRAM.Exec.regs_eq: registers that a program never writes keep their contents.Cslib.WordRAM.Exec.rename: renamed programs run on the chosen registers.Cslib.WordRAM.Exec.mono_width,Cslib.WordRAM.Exec.bounded: a program that does not read the word size runs in the same way at every larger word size, and executions keep data word-sized.
References #
- MIT–ULB CompGeom Group, Undecidability of tiling with a tromino; the structured programs, their cost-exact semantics, register preservation and register embedding are adapted from its accompanying Lean formalization.
Structured programs #
Structured programs: data and random-sampling instructions combined by sequencing, conditionals and loops.
- op {B : Basis} {r : ℕ} (o : Op B r) : Code B r
A data instruction.
- seq {B : Basis} {r : ℕ} (c₁ c₂ : Code B r) : Code B r
Run
c₁, thenc₂. - branch {B : Basis} {r : ℕ} (c : Cond r) (pos neg : Code B r) : Code B r
Run
posifcholds, andnegotherwise. - loop {B : Basis} {r : ℕ} (c : Cond r) (body : Code B r) : Code B r
Run
bodywhilecholds. - rand {B : Basis} {r : ℕ} (dst src : Fin r) : Code B r
Sample uniformly from
[0, regs src]intodstunder randomized execution.
Instances For
Decidability of whether a structured program reads the word size.
Decidability of whether a structured program is rand-free.
Executions #
Exec w c x y n: at word size w, the structured program c leads from data x to data y
executing exactly n instructions of the flat program it compiles to.
- op {B : Basis} {r w : ℕ} {o : Op B r} {x y : Data r} : Op.eval w o x = some y → Exec w (Code.op o) x y 1
A data instruction is one instruction.
- seq {B : Basis} {r w : ℕ} {c₁ c₂ : Code B r} {x y z : Data r} {m n : ℕ} : Exec w c₁ x y m → Exec w c₂ y z n → Exec w (c₁.seq c₂) x z (m + n)
Sequencing adds the instruction counts.
- branch_pos {B : Basis} {r w : ℕ} {c : Cond r} {pos neg : Code B r} {x y : Data r} {n : ℕ} : c.Holds x → Exec w pos x y n → Exec w (Code.branch c pos neg) x y (n + 1)
The first alternative of a conditional costs one branch instruction.
- branch_neg {B : Basis} {r w : ℕ} {c : Cond r} {pos neg : Code B r} {x y : Data r} {n : ℕ} : ¬c.Holds x → Exec w neg x y n → Exec w (Code.branch c pos neg) x y (n + 2)
The second alternative of a conditional costs a branch and a jump.
- loop_exit {B : Basis} {r w : ℕ} {c : Cond r} {body : Code B r} {x : Data r} : ¬c.Holds x → Exec w (Code.loop c body) x x 2
Leaving a loop costs a branch and a jump.
- loop_iter {B : Basis} {r w : ℕ} {c : Cond r} {body : Code B r} {x y z : Data r} {m n : ℕ} : c.Holds x → Exec w body x y m → Exec w (Code.loop c body) y z n → Exec w (Code.loop c body) x z (m + n + 2)
An iteration of a loop costs its body, a branch and a jump back.
Instances For
ExecWithin w c x y T: at word size w, the structured program c leads from data x to
data y within T instructions.
Instances For
An exact execution of n instructions is also an execution within n instructions.
Data instructions #
Each data instruction leads to explicitly given data in one instruction. Only constants and operations need the written number to fit a word.
A loop through the states xs 0, …, xs k: the condition holds at the first k of them and
fails at the last, and the body leads from each to the next in T instructions.
Time bounds #
Monotonicity of ExecWithin in the instruction budget.
Sequencing adds the instruction bounds of the two subprograms.
Taking the positive branch of a conditional adds one instruction to the bound.
Taking the negative branch of a conditional adds two instructions to the bound.
A conditional, with one time bound for both alternatives.
One loop iteration followed by the rest of the loop adds T₁ + 2 instructions to the bound.
A loop whose condition holds initially and fails after one body execution runs within T + 4
instructions.
Loop rule, explicit states. If the condition holds at xs 0, …, xs (k - 1) and fails at
xs k, and the body leads from each state to the next within T instructions, the loop leads
from xs 0 to xs k within k (T + 2) + 2 instructions.
Loop rule, invariant and measure. If every state satisfying the invariant I and the
condition is led by the body, within T instructions, to a state satisfying I with a smaller
measure μ, then from a state satisfying I the loop terminates within μ x (T + 2) + 2
instructions, in a state satisfying I where the condition fails.
Loop rule, invariant and potential. If every state x satisfying the invariant I and
the condition is led by the body to a state y satisfying I, within a number T of instructions
with T + 2 + Φ y ≤ Φ x, then from a state satisfying I the loop terminates within Φ x + 2
instructions, in a state satisfying I where the condition fails. The two extra instructions of
each iteration are the condition test and the jump back; the time of the body may differ between
iterations, as long as the potential Φ pays for it.
Data instructions #
An ALU operation whose result v fits in a word executes within one instruction.
Reading the word size w into register d executes within one instruction.
Symbolic execution #
Run a structured program at word size w, allowing each loop at most fuel iterations per
entry: some (y, n) if it leads to y executing n instructions, and none if it faults or
runs out of iterations. The definition is structurally recursive, so simp and decide
evaluate it.
Instances For
Registers a program does not write #
Any register preserved by c retains its value across a bounded execution.
Running a program on other registers #
A program over r registers runs on r' registers through an injective choice
f : Fin r → Fin r': register i of the program is register f i of the larger file. The other
registers keep their contents, so a caller can keep its own state across the call.
Evaluating a renamed instruction along an injective register map f commutes with comap and
extend.
Renaming. A program run on the registers chosen by an injective f does what it does on
its own registers, with the same instruction count, and leaves the other registers unchanged.
Bounded-time execution of a program renamed along an injective register map f.
Word sizes and word bounds #
A program that does not read the word size executes within the same bound at any larger word size.
Executions keep data word-sized.
Bounded-time executions preserve word-sized data.