Agreement with the standard evaluator #
den is a compositional Nat-level denotation of verbs using evalN at *
nodes. den_step proves one-step preservation; runProgram_sound is
small-step-to-big-step agreement.
Compositional denotation: * nodes use evalN; operator nodes apply the matching
Nock.Noun operator; ⊥-nodes are cons; leaves are atoms.
Equations
- One or more equations did not get rendered due to their size.
- Nock.Verb.den x✝ (Nock.Verb.leaf k) = some (Nock.Noun.atom k)
- Nock.Verb.den 0 (Nock.Verb.node a a_1 a_2) = none
- Nock.Verb.den fuel.succ (Nock.Verb.node Nock.Action.null l r) = match Nock.Verb.den fuel l, Nock.Verb.den fuel r with | some a, some b => some (a.cell b) | x, x_1 => none
- Nock.Verb.den fuel.succ (Nock.Verb.node Nock.Action.star l r) = match Nock.Verb.den fuel l, Nock.Verb.den fuel r with | some a, some b => Nock.evalN fuel a b | x, x_1 => none
- Nock.Verb.den fuel.succ (Nock.Verb.node Nock.Action.slot l r) = match Nock.Verb.den fuel l, Nock.Verb.den fuel r with | some (Nock.Noun.atom ax), some b => Nock.Noun.slot ax b | x, x_1 => none
- Nock.Verb.den fuel.succ (Nock.Verb.node Nock.Action.equal l r) = match Nock.Verb.den fuel l, Nock.Verb.den fuel r with | some a, some b => some (a.tis b) | x, x_1 => none
- Nock.Verb.den fuel.succ (Nock.Verb.node Nock.Action.edit l (Nock.Verb.leaf a)) = none
- Nock.Verb.den fuel.succ (Nock.Verb.node Nock.Action.wut l r) = none
Instances For
(B) The initial program verb denotes exactly what evalN computes #
Small-step to big-step simulation #
Natural-number Nock evaluation succeeds with some finite fuel.
Instances For
well-formedness: edit nodes never carry a pending r-child #
Every edit node has a non-pending right child, recursively throughout the verb.
Equations
Instances For
slot equation lemmas #
Structural relation: w is v with the subtree at one pending node replaced by a
Den-equivalent verb. base is restricted to pending nodes so it can never sit at an
edit node's ⊥ r-child (where den reads structure), the one place congruence needs care.
- leaf {k : Nat} : (Verb.leaf k).Rel (Verb.leaf k)
- base {v w : Verb} : v.isPending = true → (∀ (x : Noun), v.Den x ↔ w.Den x) → v.Rel w
- cong {a : Action} {l l' r r' : Verb} : l.Rel l' → r.Rel r' → (node a l r).Rel (node a l' r')
Instances For
edit/slot characterization — the %10 soundness relation #
`Noun.edit ax new old` (the `#` operator, opcode 10's structural write, `main.tex:1071`,
`1587–1607`) replaces the subtree of `old` at axis `ax` with `new`. The paper's
`NockVMROM` excludes `%10` entirely, so this relation is stated nowhere in the manuscript;
it is the noun-level soundness relation an `%edit`-table arithmetization must prove
against. Two **necessary** properties an `%edit`-table arithmetization must discharge
(sufficiency / uniqueness of `res` is not proved here):
* `slot_edit_eq` — **read-back**: on a successful edit, reading axis `ax` of the
result yields `new`.
* `slot_edit_sibling` — **sibling carry**: every off-path sibling encountered from `ax`
to the root is carried unchanged from `old` (the property whose
absence lets a fraudulent proof mutate an unrelated subtree).
Both are over the fuel-free `Noun.slot`/`Noun.edit` (`Algorithm:Noun_Operators`,
`main.tex:1537–1607`). `Noun.edit` recurses bottom-up — it rebuilds each parent by
pairing `new` with the sibling read from the *original* `old`, then edits the halved
(parent) axis. Read-back uses strong induction on `ax`; full sibling carry then follows by
induction over the siblings encountered by that same `ax / 2` walk.
The sibling axis of ax = a+2: its co-child under the shared parent ax / 2.
Even axes are left children (sibling ax+1); odd axes are right children (sibling
ax-1). This is exactly the sibAxis local of Noun.edit's a+2 branch.
Instances For
SiblingOf ax sib says that sib is an off-path sibling encountered while following
ax toward the root: either the immediate sibling of ax, or a sibling of one of ax's
proper ancestors. For example, both axes 5 and 3 are siblings of target axis 4.
- immediate (a : Nat) : SiblingOf (a + 2) (siblingAxis (a + 2))
- ancestor (a : Nat) {sib : Nat} : SiblingOf ((a + 2) / 2) sib → SiblingOf (a + 2) sib
Instances For
A sibling shares its parent: siblingAxis (a+2) / 2 = (a+2) / 2.
Read-back (#// round-trip). If editing old at axis ax with new succeeds,
reading axis ax of the result res returns new: slot ax res = some new
(conditional on edit ax new old = some res).
The "terminal replaced node equals the patch" half of the %10 relation.
slot at any axis ≥ 2 in terms of the parent read slot (m/2) and the parity pick —
the slot equation stated for a general m rather than the a+2 constructor pattern.
Sibling carry. If editing old at axis ax succeeds, every off-path sibling subtree
encountered from ax to the root is unchanged in the result. Thus an edit cannot mutate
either the target's immediate sibling or a sibling branching from any proper ancestor of the
target.