Frontiers, memoization, and materialized worlds
Materialized worlds deserve a frontier language #X7Q90E
This page takes an affirmative position: frontier-shaped computation is a real organizing principle for luvcraft, and Common Lisp gives us unusually good means to make that principle executable. The intention is not merely to extract a queue utility from lighting. It is to grow a small frontier language in which a derived world can state, at its own semantic level:
| Layer | What becomes sayable |
|---|---|
| derived-product lifecycle | capture a source, build and settle a candidate, validate it, publish coherently |
| frontier maintenance | seed, reserve, expose relations, admit, prioritize, coalesce, commit |
| local law | what light, water, fire, connectivity, copying, or another materialization actually means |
This is generality as clarification. A light module should be able to read primarily as the law of voxel light: where illumination originates, how a face relation attenuates it, how competing contributions join, and what counts as fixation. Packed buckets, chunk crossings, candidate extent, counters, and publication remain fully real, but become named machinery rather than hundreds of lines interleaved with that law. The same gain is available to fluid motion, fire, components, terminal surfaces, dependency rebuilding, and other materialized worlds without pretending that those domains have the same transfer rule.
The first executable slice now lives beside the established lighting system.
luvcraft/frontier.lisp defines inspectable frontier programs, retained
execution evidence, packed finite priority buckets, and a compiler-visible
voxel-relation traversal. luvcraft/frontier-light.lisp uses that vocabulary
for a greenfield, from-scratch monotone light program:
The declaration is an inspectable CLOS definition, while its realization is
one closed loop over specialized arrays. On a three-chunk proof world with
vertical and lateral seams, occlusion, a sky shaft, and competing emitters,
the new program produces exactly the reference oracle's sky and block arrays
with the same number of site visits. The compiled program is now the only
production solver. The deliberately simple oracle lives in the explicit
luvcraft/light-reference system: it can compare a captured candidate without
publishing it, but cannot be selected accidentally by runtime dispatch:
#53Q1II states the paradigm explicitly: these are compiled sparse kernels,
formed by composing a frontier/control IR with the quantity-checked
arithmetic IR and lowering the result to a chosen scalar, SIMD, or GPU
execution plan. #PJY6E1 records the first real compiler path: the same
voxel-light-addition definition now also carries its local law, and
compile-frontier-program closes it over the sky or block field into one
scalar loop that agrees exactly with both older solvers and runs faster than
either. #T2G95K describes the kernel language, #FE0O5R what a family
contributes, #716UN6 how bindings reach storage, and #55IRJO the terminal
wall as the second compiled client.
The retired solver remains only as test/reference evidence. Incremental invalidation, removal, and residency reconciliation have since joined the addition fixpoint as compiled frontier programs (#K3WRD3). Misspelled or retired solver names signal rather than silently changing algorithms. This keeps differential evidence available without preserving a second operational truth.
The proof carries cost evidence at the same semantic boundaries. Both solvers emit nested CPU/Tracy zones for the whole solve, sky and block seeding, propagation, and frontier draining. Each retained frontier execution records semantic evidence--visits, relations, admissions, crossings, and peak frontier size--while Tracy owns interactive temporal structure. The CPU trace and the retained A/B result record allocated bytes, garbage-collection time, and the number of automatic collections crossing each dynamic extent. A/B comparison therefore asks four different questions without confusing them: are the fields identical, did the programs perform the same semantic work, where did the physical realizations spend time, and how much memory pressure did they create? The ordinary production worker traverses these same zones, so a live Tracy capture observes the selected solver in the actual asynchronous world path, not only in a special benchmark. #J5KRQ9 explains how these instruments compose.
The first terrain measurement is already useful specialization evidence. On fifteen alternating solves of the same nine-chunk captured world, both programs produced equal fields and made 30,534 site visits. The medians were 22.676 ms and 1.125 MiB allocated for the legacy solver, versus 30.784 ms and 2.560 MiB for the frontier solver: 1.36 times the time and 2.28 times the allocation. A sustained batch of forty equivalent captures made the memory pressure tangible: 51 MiB allocated by the legacy solver and 102 MiB by the frontier solver, with one garbage collection crossing each batch.
That original result is retained here because the ensuing explanation is a small demonstration of the language paying for itself. The fields and visit counts excluded semantic divergence; matching 2,304-site seed frontiers and identical bucket capacities excluded different growth. Phase allocation then isolated the excess to admission, where one runtime-constructed type specifier allocated three conses on every push. #GJZL85 records the fix and the reversal of the allocation result. The remaining time difference now exposes a clean representation question, including the sealed-dispatch possibility in #U84XNW, rather than an indistinct mixture of algorithm and garbage collection.
Mentioned in: 5. Voxel lighting keeps oracle, experiment, and production live
Referenced from code: One live semantic account of frontier-shaped materialization work. #X7Q90E The definition names the dynamic family, physical frontier layout, and
neighborhood at an aggregate boundary, and states its local law: field roles,
realization constants, relation predicates, and the arithmetic TRANSFER,
ADMISSION, and PRIORITY forms over them. Concrete methods on
EXECUTE-FRONTIER-PROGRAM lower that account by hand; Drain FRONTIER and execute defclass frontier-program-definition frontier.lisp:51 ↗
compile-frontier-program
lowers it mechanically over bound fields.defmacro do-voxel-frontier-relations frontier.lisp:359 ↗
body once for every spatial relation it exposes.source is a retained aggregate materialization and SOURCE-OFFSET is its dense
site identity. TARGET is the local source or a materialization selected by
WINDOW at a crossing. DESTINATION has dynamic extent. The client body owns
admission, transfer, mutation, and unavailable-neighbor semantics; the macro
keeps traversal and value lifetimes visible to the compiler. This is the
manually staged lowering which compile-frontier-program now generates. #X7Q90Edefparameter *voxel-light-solver* light.lisp:420 ↗
Frontier is an operational pattern, not merely a queue #NXXOQT
The small Haskell repository
mbrock/frontier at 1688ab1
asks why breadth-first numbering, A* search, and Cheney copying garbage
collection can all become instances of one short program. Its answer is more
specific than “they use a worklist.” Each computation combines:
- an unfolder which reveals adjacent work without choosing traversal order;
- a frontier which chooses the next item;
- a memo which gives discovered identities stable results;
- a planning rule which admits, rejects, prioritizes, or coalesces new work; and
- a two-phase materialization rule which reserves a result before adjacent results exist and commits it once those results can be named.
The repository is useful to luvcraft as source evidence, not as a library to
port. Its Map, Seq, lists of plans, and monadic interfaces make the
relationships unusually legible. Luvcraft's lighting evidence #QS1ERH says
that a voxel implementation needs quite different physical machinery: packed
parallel vectors, small finite priority buckets, dense fields, and
compiler-visible iteration. The source can teach the separation of
responsibilities without prescribing the hot-loop representation.
This page first describes what the Haskell program actually does. It then
uses that account to classify the frontier-shaped work already present, or
plausible, in a Minecraft-like world. Claims about frontier are observations
of that repository; the final vocabulary is a proposal for luvcraft.
Mentioned in: The fixed-point algebra should wait for a second client
Five roles make the engine legible #6BM1IQ
The public types in
FrontierTraversal.hs
divide the computation into five roles. Omitting monadic plumbing, their
shape is:
data Step f b a e
= Done b
| Kids (f (a, e))
data Node a b = Node
{ nodeSeed :: a
, nodeResult :: b
}
data Plan a b k = Plan
{ planKey :: k
, planSeed :: a
, planUpdate :: Node a b -> BucketUpdate (Node a b)
}
data FrontierAlg m f a b k e = FrontierAlg
{ initResult :: a -> m b
, commitResult :: Node a b -> f b -> m ()
, planChildren :: Node a b -> f (a, e) -> m [Plan a b k]
, priorityOf :: Node a b -> k
}| Type parameter | Meaning in one traversal |
|---|---|
a | seed or source identity |
b | reserved result associated with that identity |
e | information on an outgoing edge |
f | one layer of adjacent structure |
k | frontier priority or scheduling class |
m | effects and client state used while traversing |
Step lets unfolding either expose a layer of labelled children or stop with
a completed result. Node keeps a seed beside the result already reserved
for it. Plan is a scheduling instruction rather than a child: it adds a
priority and a bucket-update policy. FrontierAlg supplies the four client
decisions. Separate MonadMemo and MonadFrontier interfaces supply identity
and scheduling storage.
The type variables are not decoration. They prevent a common collapse in which “neighbor,” “unvisited node,” “queued item,” and “computed result” all become one vaguely shaped record.
Reservation precedes adjacency; commitment follows naming #L4WPDP
The essential ordering appears in drainFrontier. Roots are first ensured
in the memo and pushed. Each iteration then performs this sequence:
flowchart TD R["root seed"] --> I["look up or init result"] I --> Q["push frontier item"] Q --> P["pop minimum key"] P --> U["unfold seed"] U -->|"Done b"| D["write final memo result"] U -->|"Kids"| C["plan children"] C --> S["ensure each child's result; schedule admitted work"] S --> M["look up every child result"] M --> F["commit parent from reserved child results"] D --> P F --> P
“Child results are available” has a precise and slightly surprising meaning: they have been initialized and memoized, but their own nodes need not yet have left the frontier. The parent therefore does not wait for a recursive post-order fold. It can commit as soon as stable names for its children exist.
For a seed a, let \mu(a) be its memoized result. The scheduler establishes the implication
When a parent with children a_1,\ldots,a_n commits, every \mu(a_i) exists even though some a_i may remain pending. This is the small invariant that makes shared and cyclic structures ordinary rather than special cases.
Memoization is identity preservation, not just a visited set #AQ5EDF
A visited bit answers whether an identity has been encountered. The
MonadMemo relationship answers a stronger question: what stable result has
been assigned to this seed? lookupOrInit performs the only reservation and
writes it immediately, so every later encounter observes the same result.
That distinction matters on a directed acyclic graph with sharing. If two parents point to one child c, both receive the same \mu(c); traversal does not duplicate the child's materialization. On a cycle, an edge back to an already discovered seed also finds a result which can be named before either object is fully committed.
The memo can still be trivial for algorithms that need only discovery. BFS numbering uses the result as a visit number. A voxel connected-component pass might use a bitfield plus a component identifier. A copying collector uses a forwarding address. The general lesson is that discovery often creates a durable correspondence, not merely a boolean historical fact.
Cheney collection is breadth-first materialization #RLNHEF
The repository's most clarifying example is the Cheney heap. The correspondence is exact:
| Frontier role | Cheney role |
|---|---|
seed a | from-space pointer |
result b | reserved to-space pointer |
| memo a \mapsto b | forwarding table |
| unfolder | read the source object's child pointers |
initResult | allocate the next to-space address |
planChildren | enqueue referenced source objects |
commitResult | install an object using forwarded child pointers |
| FIFO frontier | breadth-first copying order |
flowchart LR FP["from pointer p"] -->|"initResult"| FWD["forwarding p ↦ q"] FWD --> Q["reserved to pointer q"] FP -->|"unfold"| OBJ["object containing p₁ … pₙ"] OBJ --> ENSURE["ensure forwarding pᵢ ↦ qᵢ"] ENSURE --> COPY["commit object at q containing q₁ … qₙ"]
Reservation is the forwarding-pointer operation. Commitment copies the one
object layer after every child pointer has a to-space name. Shared children
remain shared because lookupOrInit cannot allocate them twice. Garbage
never enters the frontier because traversal begins only from roots. A Lens
Traversal describes an arbitrary root structure, allowing the final pass to
rewrite every root through the forwarding memo.
The property tests in
test/Main.hs
check structure preservation, compact pointer ranges, garbage removal, and
preservation of sharing in generated DAGs. The abstraction is therefore not
supported only by suggestive examples; the tests exercise precisely the
identity claims that make the example interesting.
BFS and A* differ mainly at admission and order #BNUDE9
BFS numbering gives every new seed the next integer in initResult, commits
nothing, assigns the neutral priority (), and enqueues every child. FIFO
order within the single priority bucket determines the numbering.
A* leaves the memoized result trivial and keeps best-known path costs g(s) in client state. For an edge s \xrightarrow{w} t, planning computes
and emits a plan only when g'(t) < g(t). Its priority is
When the goal leaves the minimum frontier, the unfolder returns Done and the
remaining work short-circuits. Thus the same runner expresses two visibly
different algorithms because adjacency, admission, priority, and stopping are
separate decisions.
This example also exposes a limit. A* may plan the same state again when its best-known cost improves. The memo says that the state has a stable result; the external g field says that its current approximation changed. “Has an identity” and “has reached its final value” are different predicates.
Bucket updates make duplicate work a policy question #BJCG8G
The concrete priority queue is a map from keys to FIFO sequences, accompanied
by a min-priority queue of nonempty keys. BucketUpdate receives the proposed
item and the existing sequence at one key, then returns a possibly changed
sequence and a boolean saying whether it added work. The supplied policies
are only enqueue and skip, but the seam can express replacement, deduplication,
beam-width limits, or domain-specific coalescing.
This is more than a queue convenience. It puts the question “does this newly observed relation justify future work?” beside the algorithm that knows the answer. A generic queue cannot infer that a dimmer light arrival is obsolete, that two fluid updates at one site should merge, or that a path with a worse cost should disappear. Conversely, baking one deduplication rule into the frontier would make it wrong for clients that deliberately revisit a site.
The relevant abstraction boundary is therefore admission and coalescing,
not merely push and pop.
The repository became clearer by becoming less grand #3Y7EQ1
The Git history is part of the evidence. Early versions explored Elgot
algebras, hylomorphisms, and several Cheney-specific recursion-scheme modules.
Commit 932631b replaced roughly 1,500 lines of those experiments with about
700 lines centered on FrontierTraversal and Heap. The final commit's own
message says “change terminology to be less pretentious,” and the README now
leads with a worklist-driven traversal engine.
That evolution did not abandon the underlying structure. It found an operational vocabulary in which the structure could be inspected:
unfold reserve plan schedule look up commit
This is a useful precedent for luvcraft. Mathematical interpretations can help discover laws and counterexamples, as #EQ6GLY argues, while the engine still speaks in terms a profiler and debugger can show directly.
Minecraft contains several families of frontier work #SRJEKA
“Flood fill” is too narrow a name for the work a voxel game performs, while “general graph solver” is too broad to guide representation. The useful middle ground is a family of spatial maintenance problems sharing explicit frontiers and materialized state:
| Work | Frontier item | Materialized state | Admission or priority |
|---|---|---|---|
| sky and block light addition | chunk entry, cell offset, level | best light level | enqueue only a strict improvement; brightest first |
| light removal | cell and invalidated level | candidate light field | remove dependents, then reseed surviving sources |
| terminal-wall discovery | block site and display face | membership/component ID | matching coplanar terminal material and not yet visited |
| fluid flow | active cell, face, pressure or level | volume and flow state | changed capacity/pressure; often priority or time ordered |
| fire | burning or heat-bearing site | fuel, heat, burn state | ignition threshold and scheduled decay |
| redstone-like signals | component port or conductor site | signal level and device state | enqueue when output changes; order may affect glitches |
| navigation and reachability | cell or navigation node | cost, predecessor, region | unseen or improved path cost |
| terrain/ecology influence | site and influence value | distance, moisture, fertility | strict improvement or threshold crossing |
| falling-block or support updates | changed support site | stability/component state | adjacent support relation changed |
| chunk production | chunk request and dependency stamp | staged world product | priority from visibility/distance; reject stale results |
| critter perception or sound | source/site/intensity | transient influence field | attenuated contribution remains significant |
Some rows operate over the six face-neighbor relation; others use faces, ports, visibility sets, chunk dependencies, or a metric radius. #E4T0PD is therefore still the right separation: the domain owns primitive stepping, a neighborhood policy chooses relations, and the maintenance rule decides what those relations mean.
Discover, relax, and invalidate are three different dynamics #DURBKN
The workloads fall into at least three algorithmic families.
- Discover once. Connected components and terminal-wall assembly usually assign each reachable site once for one source revision. A visited bit or component memo prevents repeated work.
Relax monotonically. Distances, influence, and light addition keep a best-known value. For a transfer T_e along edge e and join \sqcup, a site changes by
x_v \leftarrow x_v \sqcup T_e(x_u).It enters the frontier only when this update strictly changes x_v. Finite light levels make termination especially plain.
- Invalidate and rebuild. Removing a source, conductor, support, or resident neighbor can make a previously justified value too large. The system must trace invalid dependencies or conservatively clear a region, then run monotone addition again from surviving evidence. Voxel lighting's removal and addition queues in #SKRELT are the current concrete example.
These families can share storage, adjacency, counters, and scheduling machinery. They should not be forced through one callback protocol that pretends deletion is an ordinary join or that every discovered node is final. The fixed-point shape proposed in #BA9MCA is one client protocol over a more basic frontier substrate, not the definition of that substrate.
Mentioned in: Families own admission, commit, and priority, Invalidation is a family with a companion frontier
Referenced from code: Families are the semantic dynamics of #DURBKN. Each family knows which
roles a program must declare and what its default admission, commit, and
priority laws are. A definition is checked against its family at
definition time so a wrong program fails before any realization. Signal an error unless define-frontier-program voxel-light-removal frontier-light.lisp:168 ↗
defgeneric frontier-family-check-definition frontier.lisp:186 ↗
definition is well formed for family.
Terminal walls supply a second, deliberately simpler client #K3PCP3
A planar rectangle of adjacent terminal-material blocks is a useful discover-once client. Starting from a placed or changed block face, the pass can traverse coplanar face neighbors of the same material, reserve a candidate surface identity, and collect bounds and membership. It then validates that the bounding rectangle is full and publishes one display surface over the participating blocks.
flowchart LR
E["block edit"] --> S["seed affected terminal faces"]
S --> W["discover coplanar component"]
W --> B["accumulate orientation and bounds"]
B --> V{"every rectangle site present?"}
V -->|yes| P["publish terminal surface materialization"]
V -->|no| X["publish components or no display, by chosen rule"]
P --> G["project terminal grid and Slug draws over the whole face"]Unlike light, the terminal surface need not revisit a site because a numeric approximation improved. Unlike a permanent world entity, its identity is derived from block material, orientation, adjacency, and source revisions. Breaking one block invalidates the old component and may discover several new ones. That places terminal walls between ordinary component labeling and incremental connectivity.
The terminal grid described by #RD8AEI remains a separate domain. The block frontier discovers where the display surface exists; Ghostty and the terminal presentation determine what cells the display contains. Surface geometry maps between those domains without making one terminal cell equal to one voxel block.
Mentioned in: Adjacent terminal-material blocks define one unified display surface, Terminal walls are the second compiled client, The fixed-point algebra should wait for a second client
Referenced from code: Discovery is a discover-once frontier program (#K3PCP3): starting from
one exposed terminal face, admit coplanar neighbours which are the same
material and exposed, mark each once, and retain the admitted component.
The compiled realization walks chunk offsets through the world's chunk
window; no coordinate objects, hash keys, or conses appear per site.define-frontier-program terminal-surface-discovery terminal-wall.lisp:546 ↗
Voxel efficiency requires translating the algebra, not its objects #RR9ODK
The Haskell carrier deliberately favors clarity: Map memoization, a Map of
Seq priority buckets, allocated lists of Plan values, traversable child
layers, and monadic state. Those choices make the experiment easy to vary and
test. They are not an acceptable inner-loop cost model for millions of voxel
visits.
Luvcraft's existing packed light worklist records the relevant facts. Moving from retained structures and conses to parallel vectors reduced one measured solve from about 264 MB to 31.8 MB consed without changing its 2.43 million visits. Changing scheduling to sixteen brightest-first buckets then reduced the solve to about 13.3 MB, 340,050 visits, and 0.18 seconds. Representation and order were independent performance dimensions.
The luvcraft translation should therefore preserve semantic seams while specializing physical execution:
| Semantic role | Hot representation |
|---|---|
| seed identity | retained chunk-window entry plus dense domain offset |
priority k | small integer bucket or client-specific packed key |
| memo/result | dense field lane, bitset, component lane, or side table |
| child layer | compiler-visible neighborhood iteration with dynamic-extent coordinates |
| plan | immediate admission branch; no allocated plan object |
| bucket update | client-specialized enqueue, skip, replace, or coalesce operation |
| commit | direct writes into a candidate materialization |
One dispatch when choosing a maintenance policy may be useful. Generic function calls, closures, conses, and coordinate allocation per edge would put abstraction precisely where #FGT96H says the current profiler is most sensitive. A macro can expose the algebraic phases to source readers while expanding the trusted inner loop over primitive arrays.
Mentioned in: Adjacent terminal-material blocks define one unified display surface
A frontier language composes meaning with specialized execution #QHBZJZ
The unification is real precisely because it is layered. We do not need one generic call per edge, or one object shape for every domain, to possess a shared language. We need stable compositional roles which can be lowered to the right concrete execution:
flowchart TB D["chunk domains and checked windows"] --> N["client neighborhood iteration"] F["materialized fields and revisions"] --> M["maintenance policy"] N --> M P["packed frontier storage and priority discipline"] --> M M --> C["candidate mutation / result reservation / commit"] C --> U["coherent publication"]
The reusable words are concrete and already beginning to exist:
- packed frontier ownership, growth, clearing, counters, and retention rules;
- finite priority-bucket disciplines and perhaps FIFO/LIFO alternatives;
- validated source-site scopes with allocation-free local and crossing neighbor iteration;
- dense visitation, best-known-value, component, and dirty-state materializations; and
- lifecycle rules for candidate state, stale inputs, and coherent publication.
Client programs own transfer laws, admission predicates, removal semantics, stopping conditions, and the interpretation of unavailable neighbors. This is what makes the abstraction powerful: light remains unmistakably light and a terminal wall remains unmistakably a terminal wall, while both can speak in the same precise language about frontier, domain, materialization, extent, and publication.
Mentioned in: Adjacent terminal-material blocks define one unified display surface
Frontier programs are compiled sparse kernels #53Q1II
The proposed frontier language is a DSL compiler, not a generic worklist framework whose inner loop depends on accidental devirtualization. A live, inspectable program definition remains open to Common Lisp development; one compilation closes that definition over particular fields, domains, neighborhoods, representations, and an execution plan, then emits the exact scalar, SIMD, or GPU machinery required by that realization. This is the explicit staging which C++ templates and Haskell type-class specialization obtain through their host languages, but here the generated program and every choice which produced it can themselves be ordinary Lisp objects.
The compiler composes two deliberately different languages:
flowchart TB F["frontier program IR<br/><small>family, domain, neighborhood, effects, fixation, publication</small>"] A["arithmetic IR<br/><small>quantity-checked transfer, join, admission, priority</small>"] C["frontier compiler<br/><small>bind fields and choose a physical plan</small>"] S["closed scalar Lisp loop"] V["columnar SIMD batches"] G["bulk GPU passes"] W["GPU work graph"] F --> C A --> C C --> S C --> V C --> G C --> W
The arithmetic language owns pure value laws: derive a propagation loss, compute a candidate, compare it with a destination, join compatible values, and derive a priority. The frontier language owns work-generating effects: seed, expose a relation, read and commit fields, admit another site, settle or invalidate work, and publish a coherent candidate. Chunk lookup, unavailable neighbors, queues, atomics, revision stamps, and publication do not become arithmetic expressions. Conversely, a light attenuation law should not be duplicated as handwritten scalar, SIMD, and shader arithmetic. This sharpens the local-law boundary anticipated by #WEE8P5 and realizes the checked field kernel of #ADR040 through the multi-backend arithmetic medium #5N6SOQ.
One execution plan need not contain a conventional queue. The physical meaning of “unsettled work” may be a packed bucket frontier, a FIFO, an active bitset, current/next append buffers, component parents undergoing pointer jumping, or records emitted between GPU nodes. Two sources make that range concrete:
- Kuth et al.'s 2025 real-time GPU tree generator uses GPU work-graph nodes which consume typed tree records and emit recursive stem, leaf, and mesh work. This is a heterogeneous, dynamically growing frontier realized by the device scheduler.
- Jain et al.'s 2024 FastFlow instead turns terrain flow into regular bulk GPU iterations: rake-compress and pointer jumping accumulate stream trees, while a Borůvka-style process merges depression basins. Its GPU may run a fixed logarithmic number of rounds rather than synchronizing with the CPU to detect early convergence. Here the frontier is evolving dense relations, not an emitted queue.
These are source observations, not a claim that luv already has either GPU
backend. Their design consequence is that :frontier-layout alone is too
narrow to describe compilation: layout is one part of an execution plan.
The compiler may select a different algorithmic realization when the program
declares and tests the laws which justify it--for example monotonicity,
associative joining, an acyclic recipient relation, finite priority, or a
bounded round count. Such laws are semantic claims with differential and
property evidence, never optimistic compiler annotations.
The same source can make SIMD explicit without demanding that irregular scheduling itself vectorize. A plan may drain a homogeneous bucket cohort, separate same-materialization interior sites from crossings, borrow raw columns once, evaluate transfer and admission over lanes and masks, compact successful lanes, and handle a scalar tail. Selection occurs outside the hot loop. The scalar lowering remains the reference realization for exact field, visit, and arithmetic conformance.
Quantity meaning survives compilation while quantity wrappers do not. The
current :sky-propagation-level and :block-propagation-level fields are
already different dimensionless kinds over the same u8 encoding; neither
should be renamed radiance or illuminance merely because future lighting will
be more physical. A richer kernel may distinguish radiance, irradiance,
luminance, spectral or photon quantities, material transmittance, and
photopic, scotopic, or mesopic conditions at its checked boundary, then still
execute over plain integer or floating lanes. Physicalization therefore
strengthens this compiler seam: it does not make a quantity object per voxel.
The current implementation is a useful manually staged compiler prototype:
| Present definition | Compiler reading |
|---|---|
define-frontier-program | embryonic semantic source definition |
compile-frontier-program | semantic program and field bindings become one realization |
do-voxel-frontier-relations | fused scalar loop template with compiler temporaries exposed |
bucket-frontier | one physical scheduler and record store |
| inline light body | not-yet-reified arithmetic kernel |
| reference/candidate A/B | explicit test-system conformance and cost evidence |
The large binding list of do-voxel-frontier-relations is thus not the
desired human-facing API. It is evidence about the lowered loop. A pleasant
kernel source should primarily name fields, relations, transfer, join,
admission, priority, and lifecycle; the compiler introduces offsets,
crossing flags, buffer access, counters, and temporaries while retaining
source provenance for inspection. CLOS remains the open control plane for
definitions and backend protocols, while generated code deliberately contains
no generic dispatch at the per-site or per-relation grain.
Mentioned in: Materialized worlds deserve a frontier language, The kernel language names fields, constants, predicates, and laws, The shared questions are now concrete, Fast generic functions can specialize a sealed semantic domain, Compile the monotone light kernel to scalar Lisp
Referenced from code: Scalar lowering. The generic realization above dispatches on numbers
versus vectors at run time so one compiled function can serve every
representation. A hot loop whose operands are known scalars wants the
ordinary Common Lisp operators instead, so that declared integer or float
types flow through the emitted arithmetic. The choice is made once, by
the caller lowering an expression, and never per operation. How Voxel light loses one attenuation step per cell entered plus the entered
cell's own opacity, except that a direct transmission (sky light continuing
straight down) pays only the opacity. This is the one local law shared by
the legacy solver, the seeds, and the compiled frontier kernel, which
inlines the checked definition rather than calling this function. #53Q1II ------------------------------------------------------------------------
Realizations One program compiled over bound fields into closed scalar Lisp. TRANSFER, ADMISSION, and PRIORITY are the checked arithmetic expression
graphs; DRAIN-FORM and ADMIT-FORM are the emitted lambda forms; the two
functions are their compiled realizations. ADMIT-FUNCTION seeds one site
through the same admission and commit law as a relation, or is NIL when the
law needs a source. RELATE-FUNCTION exposes one relation from a virtual
source whose field values are supplied as arguments, so a boundary such as
open sky is the program's own transfer law rather than client arithmetic.
#53Q1II #581ZQP Close Parse and check the laws.defvar *lisp-arithmetic-lowering* compiler.lisp:253 ↗
lower-lisp-arithmetic-expression emits calls: :GENERIC uses the
representation-dispatching lisp-add family; :SCALAR emits CL operators over
declared scalar operands. #53Q1IIdefine-lisp-arithmetic-function light-propagation-loss arithmetic.lisp:25 ↗
defclass frontier-realization frontier.lisp:468 ↗
defun compile-frontier-program frontier.lisp:923 ↗
program over field bindings and emit its scalar realization.site-domain is a form over MATERIALIZATION yielding the chunk domain that
gives a site's dense offset spatial meaning. Each field role of the program
must have one frontier-field-binding. The laws are parsed and quantity
checked against the bound fields, lowered with scalar arithmetic, and spliced
into one closed loop over raw buckets and lanes. With compile NIL the forms
are emitted but not compiled, for inspection. #53Q1II #T2G95K #716UN6
The kernel language names fields, constants, predicates, and laws #T2G95K
A frontier program is now written as its own semantic source rather than as a name attached to a handwritten loop. Voxel light reads:
The clauses divide along the two languages of #53Q1II. :fields names
roles the program reads or writes at source and target without saying
where they live. :constants are values supplied when a realization runs;
:predicates are raw truth values about the exposed relation, such as
whether its direction is the constant direct-direction or whether it
crosses a chunk. :transfer, :admission, and :priority are arithmetic
expressions over (FIELD ROLE) reads, predicates, and constants, parsed by
the arithmetic frontend and quantity checked against the bound fields, so
the one transfer law is checked once as sky propagation levels and once as
block propagation levels. as-field-quantity is the explicit boundary at
which attenuation steps become propagation-level differences; the checker
refuses the subtraction without it. light-propagation-loss is an ordinary
define-lisp-arithmetic-function: the seeds call it as a function, while the
kernel inlines its checked definition.
A realization exposes three entry points besides the drain: admit
seeds a site through the family's law with a supplied value, relate
exposes one relation from a virtual source (#581ZQP), and schedule pushes
a site whose value stands for reconsideration. Families with a secondary
effect take a companion frontier (#ZEENY3).
The realization retains everything the reader could want: the parsed
expressions with their quantity specifications, the emitted lambda forms,
and the compiled functions. frontier-realization-drain-form prints the
whole loop, and the light tests assert that it contains no arithmetic
dispatch and no funcall. The reserved words of the language--source,
target, materialization, offset, value, window, crossing,
direction=--are recognized by name so programs and bindings can be written
in their client packages.
Mentioned in: Materialized worlds deserve a frontier language, Compile the monotone light kernel to scalar Lisp
Referenced from code: Close Parse and check the laws.defun compile-frontier-program frontier.lisp:923 ↗
program over field bindings and emit its scalar realization.site-domain is a form over MATERIALIZATION yielding the chunk domain that
gives a site's dense offset spatial meaning. Each field role of the program
must have one frontier-field-binding. The laws are parsed and quantity
checked against the bound fields, lowered with scalar arithmetic, and spliced
into one closed loop over raw buckets and lanes. With compile NIL the forms
are emitted but not compiled, for inspection. #53Q1II #T2G95K #716UN6
Families own admission, commit, and priority #FE0O5R
The :family clause is semantic, not a label. #DURBKN's dynamics become
compiler knowledge:
| Family | Requires | Admits a target when | Commits | Schedules at |
|---|---|---|---|---|
:monotone-max-fixpoint | one :relaxed field and a :transfer | the transfer exceeds the field's value | the transfer into the field | the transfer, or a stated :priority |
:discover-once | one :memo field and an :admission | the memo is clear and the admission holds | the memo | 0, or a stated :priority |
:invalidation | one :invalidated field and an :admission (dependency) | the target is lit and depended on the source | zero into the field | the level the target had; an independent lit target is instead handed to the companion frontier |
A definition is checked against its family when it is defined, so a
monotone program without a relaxed field fails before any realization. This
is why the light program states only its transfer, and the terminal program
only its admission: strict improvement, brightest-first scheduling, and
visit-once memoization are what those families mean. #ZEENY3 adds the
third dynamic of #DURBKN. Further families (A*-style external cost, bounded
rounds) add methods on frontier-family-law-forms without touching any
client.
Mentioned in: Materialized worlds deserve a frontier language
Referenced from code: Return (VALUES TEST-FORM COMMIT-FORMS PRIORITY-FORM OTHERWISE-FORMS) for
one exposed target under defgeneric frontier-family-law-forms frontier.lisp:811 ↗
family, given the lowering environment of bound
field values. candidate-variable names the transfer result for monotone
families, or the supplied value when seed-p says the target is being seeded
rather than reached through a relation. OTHERWISE-FORMS run when the test
fails, for families with a secondary effect. #FE0O5R
Bindings close a program over storage #716UN6
compile-frontier-program takes the definition, one frontier-field-binding
per role, and a site-domain template. A binding names the represented-value
declaration that gives the field its quantity and Lisp type (for light, the
:sky-light voxel field definition and the light-opacity slot
declaration), the lanes it borrows once per materialization, and read and
write templates over those lanes:
The emitted loop binds the raw bucket vectors and counters once, borrows a
popped source's lanes and reads its field values once per pop, and at each
relation either reuses those lanes (a local step) or borrows the crossing
materialization's (an if crossing). Field values are read into declared
variables, so the inlined law is fixnum arithmetic over (unsigned-byte 8)
reads. A :lazy binding is instead read where the law mentions it, which
lets a short-circuiting admission skip an expensive probe. The popped site
is validated once and its relations are primitive fixnum steps through
do-chunk-site-neighbors (#FGT96H). Nothing per relation is generic,
rechecked, or allocated; the only allocation left in a warmed drain is the
window's coordinate key at chunk crossings (#L84JCX), and a test bounds it by
the crossing count.
The brightest-first layout takes its bucket count from the relaxed field's legal values, so the frontier's priority meaning is the field definition itself. Realizations are cached per bound field and invalidated by the definition's revision, so redefining the program in a running image recompiles on next use.
Mentioned in: Materialized worlds deserve a frontier language, Compile the monotone light kernel to scalar Lisp, Pay checked adjacency cost once per visited site
Referenced from code: Close Parse and check the laws.defun compile-frontier-program frontier.lisp:923 ↗
program over field bindings and emit its scalar realization.site-domain is a form over MATERIALIZATION yielding the chunk domain that
gives a site's dense offset spatial meaning. Each field role of the program
must have one frontier-field-binding. The laws are parsed and quantity
checked against the bound fields, lowered with scalar arithmetic, and spliced
into one closed loop over raw buckets and lanes. With compile NIL the forms
are emitted but not compiled, for inspection. #53Q1II #T2G95K #716UN6
Terminal walls are the second compiled client #55IRJO
#K3PCP3 asked for terminal discovery as a deliberately simpler client. It now is one program:
Its window is the block world itself, whose chunks are the materializations
and whose locate-chunk-window-site continues a step across a seam. The
memo is a per-chunk bit vector owned by one discovery's table; terminal is
an eq against the constant material through the chunk's content column;
exposed is a lazy probe of the outward neighbour. Because the program
retains admissions, the execution hands back the component as one packed
buffer of chunk and offset, and find-terminal-surface folds that into
projections and a rectangle test. The old hash-of-coordinate-lists walk is
gone; the earlier expectations (rectangle, L-shape, covered, wrong material)
and a seam-straddling rectangle whose retained component is exactly its
eighteen blocks are the tests.
Mentioned in: Materialized worlds deserve a frontier language
Invalidation is a family with a companion frontier #ZEENY3
Removing a source, or a departed neighbour, leaves levels no surviving
source justifies. #DURBKN argued that this is a different dynamic from
addition, not an option on it; it is now the :invalidation family, and voxel
light's removal program reads:
Three things distinguish the family. First, the source's value is not a
field read: a cleared site's field is already zero, so (level source) is
the priority it was admitted at--the level it had. Second, the family has
a secondary effect: a lit target that the source did not feed is a surviving
source, and the drain hands it to a companion frontier--here the addition
program's--at its own level, counted as an emission. Third, the retained
admissions are the cleared set, which the client walks afterwards to
re-admit emitters and relate open sky (#581ZQP) before draining addition.
The compiled reconciler in frontier-light.lisp composes exactly the
legacy sequence from these words: invalidate dirty cells and departed
neighbours' faces (admit with the old level), drain removal with addition
as companion, reseed emitters and open sky over the cleared set, seed
arrivals (relate for sky, admit for emitters, schedule for resident
neighbours' facing sites, whose values already stand but whose relations
must be exposed again), then drain addition. reconcile-lighting selects
it through *voxel-light-solver* :compiled.
Evidence is differential and exact: the incremental, random-edit, departure, re-arrival, same-key replacement, and cross-chunk crystal tests run under both reconcilers against the from-scratch reference; a roofing test checks that sky removal clears exactly the sixteen cells of the beam and emits survivors. Over forty ten-edit bursts on six chunks both reconcilers visited 121,110 cells; the compiled one settled a burst in a median 0.55 ms against the legacy 1.25 ms.
Mentioned in: The kernel language names fields, constants, predicates, and laws, Families own admission, commit, and priority, Give frontier light its own invalidation program
The shared questions are now concrete #7U572V
The frontier repository and luvcraft's two clients replace the vague question
“should we generalize the flood fill?” with questions that can be answered in
code and measurements:
- Can one packed frontier storage vocabulary serve both light levels and terminal component sites without weakening either representation?
- Which admission choices can be selected outside the loop, and which must be macro-expanded into it?
- Is a dense per-materialization bitset sufficient for terminal discovery, or does incremental splitting soon justify retained component metadata?
- Can one validated-site neighborhood scope remove repeated bounds checks for lighting while remaining useful to component discovery?
- Which clients need result reservation in the strong Cheney sense, rather than only visited or best-known state?
- Can every candidate prove its source materialization and boundary revisions before publication?
- Do queue counters distinguish useful visits, stale pops, strict improvements, invalidations, and cross-chunk steps well enough to compare scheduling policies?
The exciting criterion is semantic compression with mechanical strength: clients share storage and iteration laws, retain their own meanings, allocate no per-edge garbage, and become easier to read and observe than their separate predecessors. If several modules can become short declarations of their world laws while the generated or macro-expanded loops remain excellent, that is not abstraction for its own sake. It is the engine discovering one of its native languages. #53Q1II now names the compiler architecture which makes that criterion explicit rather than leaving specialization to macro convention or implementation luck.
Tracy aligns temporal structure with semantic work #J5KRQ9
with-cpu-trace-zone is one instrumentation vocabulary with two independent
observers. Its outer observer is a real Tracy zone. When Tracy is stopped,
the path is one special-variable test. When Tracy is running, a literal zone
uses an interned foreign source location and one begin/end FFI pair. The
inner observer is luv's bounded cpu-trace tree, enabled only around an
explicit retained capture. It samples host time, allocated bytes, and GC
clocks at zone boundaries. The frontier code does not maintain a third
per-execution stopwatch: retained executions keep semantic counters, while
Tracy and the explicit A/B observation own time.
This division follows the instruments' actual powers:
| Instrument | Best question |
|---|---|
| Tracy zones | which temporal region was active, nested under which thread and frame? |
| Tracy zone values | how much semantic work did this particular interval perform? |
| Tracy plots | how did allocation or GC observations change along the capture timeline? |
| runtime observation | how many process-wide bytes and collections crossed one explicit A/B extent? |
| SB-SPROF allocation mode | which sampled Lisp call stacks were active at allocation-region refills? |
| source and disassembly | which exact form allocates, dispatches, or escapes? |
The drain zones now attach their visit count through Tracy's zone-value API.
The A/B comparator emits reference/candidate allocated-byte, GC-millisecond, and
collection-count plots. A thirty-pair capture therefore showed every sky
drain beside the value 30,534, and the steady allocation samples for both
solvers converged to 1,179,696 bytes after #GJZL85. A separate sixty-pair
capture measured mean sky propagation at 23.03 ms legacy and 27.63 ms
frontier. Tracy thus says both when and how much semantic work; the
allocation plot rules out GC as the steady explanation for the remaining
time gap.
Tracy also has a C memory-allocation API, but using it honestly would require allocator-level object addresses and matching frees. SBCL owns a moving generational heap, so emitting a fake Tracy allocation for each sampled byte delta would manufacture object identities and lifetimes that do not exist. For Lisp heap attribution, zone-level byte deltas plus SB-SPROF and compiler inspection are the sounder composition.
Mentioned in: Materialized worlds deserve a frontier language
Fast generic functions can specialize a sealed semantic domain #U84XNW
Marco Heisig's fast-generic-functions
turns a CLOS generic function into a compiler-specializable one. A client
defines the generic function with fast-generic-function as its metaclass,
seals a chosen argument domain after installing methods, and supplies enough
static argument type information at call sites. On SBCL, the library
installs IR1 transforms. The default optimized call bypasses the
discriminating function and calls a compiled effective method directly; when
every applicable method declares the inlineable method property, it can
inline the complete effective method.
This is a beautiful fit for closed physical realization beneath an open semantic boundary, but sealing has exact consequences. No method may later change behavior inside the sealed domain. User-defined standard classes must participate through a sealable metaclass and externalizable prototype instances. The project itself recommends putting definitions, methods, and sealing in separate load stages and measuring with sealing disabled as an A/B control.
The current light result makes its relevance precise:
- The retired
execute-frontier-programselector cost only two dispatches per solve; deleting it closed runtime policy but could not explain several milliseconds. bucket-frontier-pushandbucket-frontier-popare ordinary functions, but their CLOS slot readers and writers are generic functions in the per-site path. Disassembly of push contains nine accessor FDEFN calls and is 1,044 bytes, versus 644 bytes for the struct-backed legacy push.- A queue-only run of 1.8 million warmed push/pop operations took
80.14 msthroughbucket-frontierand18.15 msthrough the legacy structure. Both perform the same finite-bucket discipline; the generic frontier now allocates zero bytes in that loop.
There are therefore two excellent proof candidates. One makes the frontier
accessors fast generic functions and seals the bucket-frontier domain. The
other binds the CLOS owner's raw buckets and counters once, runs a
compiler-visible drain over local primitive state, and writes the counters
back at the boundary. The former tests whether sealed CLOS can itself be the
zero-overhead physical language; the latter preserves unrestricted live CLOS
at the boundary. Comparing their generated code, live redefinition behavior,
and whole-solver Tracy capture remains informative. The compiler proposal
#53Q1II gives the second candidate a larger meaning: raw binding is not an
adapter around CLOS but one deliberate lowering of an open semantic program.
Fast generic functions remain a valuable A/B realization, not a prerequisite
for zero-overhead frontier semantics.
Mentioned in: Materialized worlds deserve a frontier language
DONE Remove the per-admission type construction #GJZL85
Intent: explain and remove the frontier solver's measured allocation excess without weakening the semantic frontier API.
Evidence: bucket-frontier-push constructed
`(integer 0 ,maximum-priority) for every runtime typep. Three conses per
admission predicted approximately 108 KiB for the 2,304 initial sky sites and
1.27 MiB for propagation, matching the phase measurements. Replacing it with
integer and range predicates changed forty terrain sky propagations from
88.18 MiB to 37.24 MiB; the legacy batch used 37.56 MiB. Frontier
seeding fell to 6.82 MiB versus legacy's 8.37 MiB. A focused warmed test
now admits and removes 8,192 sites under a 4 KiB allocation ceiling.
Done when: allocation attribution predicts the measured delta, the physical fix preserves exact field and visit equality, and a regression rejects a return of per-site type construction.
Mentioned in: Materialized worlds deserve a frontier language, Tracy aligns temporal structure with semantic work
DONE Begin frontier light beside the oracle #DVUZ6H
The first greenfield program has its own inspectable declaration, packed brightest-first frontier, relation traversal, counters, exact oracle comparison, and live selector. It reuses capture and publication on purpose: those shared boundaries make the A/B result exact while the new execution model proves itself.
A warmed two-chunk live-image snapshot ran seven exact A/B pairs. Legacy
solves ranged from 11.7 to 12.3 ms and frontier solves from 15.7 to
16.3 ms on this machine. The nested trace localized the present difference
to frontier sky seeding and propagation. This is an optimization map, not a
verdict on the language: both programs visited the same sites and produced
identical fields, while the new semantic boundaries made their physical cost
directly comparable.
DONE Compile the monotone light kernel to scalar Lisp #PJY6E1
Intent: turn the manually staged frontier-light proof into the smallest real compiler path described by #53Q1II. Reify the local transfer, join, admission, and priority arithmetic with checked field meanings; make the program definition drive a scalar execution plan; and emit one closed Lisp loop over bound raw storage. Keep the existing handwritten frontier solver and legacy solver unchanged as two independent oracles.
Evidence: voxel-light-addition now carries its fields, constants,
predicates, and transfer (#T2G95K); compile-frontier-program (#716UN6)
realizes it once over the sky field and once over the block field, and
solve-light-region-using :compiled drives both. On the three-chunk proof
world the compiled solver produces the legacy oracle's exact sky and block
arrays with the same 12,458 visits, and its executions report the same
visits, relations, and crossings as the handwritten frontier lowering. On
fifteen alternating solves of the nine-chunk little world all three programs
made 30,534 visits; medians were 22.9 ms for the legacy solver, 28.0 ms for
the handwritten frontier program, and 20.3 ms for the compiled kernel, with
1.1 MiB allocated by each. A batch of forty captures took 920, 1150, and
813 ms respectively. Once the emitted loop stepped through the trusted
scope of #FGT96H, the compiled median fell further to 6.1 ms and the batch to
242 ms. The emitted form is inspectable and inlines the
checked light-propagation-loss law as ordinary fixnum arithmetic; a
warmed drain over the proof world's 68,000 relations allocates only the
crossing lookups. The one supporting arithmetic-language change was a scalar
lowering mode plus logical and, or, and not.
Done when: one inspectable source definition can be recompiled in the live image; its generated scalar realization contains no per-site generic dispatch or allocation; its sky and block fields and visit counts agree exactly with both current oracles; its emitted form and compiler output are inspectable; and Tracy attributes any remaining cost at the same semantic zones. All of these hold; SIMD, GPU lowering, invalidation, and a final surface syntax remain outside this proof.
The later retirement cut kept that proof but removed both old runtime
choices. Production calls can now reach only the compiled realization; the
simple from-scratch oracle and comparator load only with
luvcraft/light-reference.
Mentioned in: 5. Voxel lighting keeps oracle, experiment, and production live, Materialized worlds deserve a frontier language
Referenced from code: Solve defun solve-compiled-light-region frontier-light.lisp:121 ↗
region from scratch with the compiled voxel-light realization. #PJY6E1defparameter *voxel-light-solver* light.lisp:420 ↗
DONE Compile the sky seeds as boundary transfers #581ZQP
Intent: let the realization admit a virtual open-sky source through the program's own transfer law, so seeding stops restating the loss arithmetic in client code and a boundary is just a relation whose source is not a site.
Evidence: every realization now also emits a relate entry
(relate-frontier-realization-site): the source role's field values arrive
as keyword arguments named by role, the relation direction as an argument,
and the crossing predicate is true, after which the target is tested,
committed, and admitted by exactly the relation body. Sky seeding calls it
with :level 15 and the inward direction of each open face; the loss
arithmetic no longer appears in frontier-light.lisp. Fields and the
12,458 proof-world visits are unchanged against both oracles, and a test
relates one virtual source straight down (15), laterally (14), into an
opaque cell (not admitted), and dimly into an already-brighter site (not
admitted).
Done when: sky seeding calls a compiled entry with the source level and the inward direction, the transfer law appears once in the program, and the compiled solver's fields and visits are unchanged. All hold.
Mentioned in: The kernel language names fields, constants, predicates, and laws, Invalidation is a family with a companion frontier
Referenced from code: The compiled solver. Seeds and drains both go through the realization:
a sky boundary is a virtual source at full brightness whose loss follows
the same law, and an emitter is a value joined into the block field. Relate open sky into every open face of Open sky is a virtual source at full brightness beyond the
face; the relation into the entry runs the other way. The
program's own transfer law decides the level and admission.
#581ZQP ------------------------------------------------------------------------
Realizations One program compiled over bound fields into closed scalar Lisp. TRANSFER, ADMISSION, and PRIORITY are the checked arithmetic expression
graphs; DRAIN-FORM and ADMIT-FORM are the emitted lambda forms; the two
functions are their compiled realizations. ADMIT-FUNCTION seeds one site
through the same admission and commit law as a relation, or is NIL when the
law needs a source. RELATE-FUNCTION exposes one relation from a virtual
source whose field values are supplied as arguments, so a boundary such as
open sky is the program's own transfer law rather than client arithmetic.
#53Q1II #581ZQP Expose one relation into MATERIALIZATION/OFFSET from a virtual source.defun seed-compiled-sky-boundaries frontier-light.lisp:78 ↗
region's entries, or of entry.defclass frontier-realization frontier.lisp:468 ↗
defun relate-frontier-realization-site frontier.lisp:565 ↗
arguments supply the program's constants and, keyed by role name, the source
field values the transfer reads; direction is the relation's direction as
seen from that source. The target is tested, committed, and admitted by the
same law as an ordinary relation. Return whether it was admitted. #581ZQP
DONE Give frontier light its own invalidation program #K3WRD3
Intent: state removal and incremental reconsideration in the same compiled vocabulary after the monotone kernel establishes its source and lowering boundary.
Evidence: #ZEENY3. voxel-light-removal is an :invalidation program whose
compiled drain reads like unlight-light-region but is emitted from the
family and the one dependency law; the compiled reconciler composes it with
the addition program through admit, relate, schedule, and the
companion frontier. Removal executions retain the cleared set and count
visits, relations, crossings, admissions, and emissions (survivors handed
on). Under *voxel-light-solver* :compiled every incremental test
converges to the from-scratch reference across edits, emitters appearing
and vanishing, departures, re-arrivals with fresh edits, same-key chunk
replacement, and crystals across chunk boundaries; forty random edit bursts
visit the same 121,110 cells as the legacy reconciler at a median 0.55 ms
against 1.25 ms.
Done when: invalidation and re-admission are explicit program operations,
executions retain stale and useful work counters, and the compiled program
converges bit-for-bit with from-scratch frontier light across each residency
and edit case above. All hold. The subsequent retirement cut removed the
legacy incremental reconciler altogether; light-matches-reference-p now asks
the separate luvcraft/light-reference system for a from-scratch oracle and
compares that result with the production compiled path.
Mentioned in: 5. Voxel lighting keeps oracle, experiment, and production live, Materialized worlds deserve a frontier language
Referenced from code: Invalidation. Removing a source, an occluder's disappearance being an
addition, or a departed neighbour can leave levels that no surviving
source justifies. The removal program clears every level the removed
site fed--strictly dimmer, or equal for direct sky continuing down--and
re-admits the cleared site at the level it had; a lit neighbour it did
not feed is handed to the addition frontier as a surviving source. The
cleared set is the execution's retained admissions. #K3WRD3 #DURBKN Settle The compiled removal and addition programs must reproduce the reference
field across the same edit bursts, departure, and re-arrival. #K3WRD3 Settle define-frontier-program voxel-light-removal frontier-light.lisp:168 ↗
defun reconcile-compiled-lighting frontier-light.lisp:405 ↗
state's dirty cells, departures, and arrivals over candidate region
with the compiled removal and addition programs. Return the executions and
the total visits. #K3WRD3deftest compiled-random-edits-and-residency-match-the-reference-solver light-tests.lisp:584 ↗
defparameter *voxel-light-solver* light.lisp:420 ↗
defgeneric reconcile-light-region-using light.lisp:629 ↗
state's dirty cells, departures, and arrivals over candidate
region with the explicitly implemented incremental relighter named by solver.
There is deliberately no default method: unsupported names signal rather than
falling back to a different algorithm. #K3WRD3
(name &rest options
&key family frontier-layout neighborhood fields constants predicates
transfer admission priority retain-admissions)The voxel-light program selected for production solves. Only :COMPILED is implemented by the runtime. The legacy implementation is loaded explicitly by the LUVCRAFT/LIGHT-REFERENCE system as a differential test oracle; unsupported names signal through the closed EQL dispatch. #X7Q90E #PJY6E1 #K3WRD3
(world &key (candidate :compiled))Compare the test-only legacy oracle with production CANDIDATE over WORLD. Equivalent captures are solved without publication. The result reports exact per-chunk array equality, work and runtime observations, and the candidate's retained frontier executions. Unsupported candidate names signal through the production…
The live game session in this Lisp, or NIL.
One live semantic account of frontier-shaped materialization work. #X7Q90E The definition names the dynamic family, physical frontier layout, and neighborhood at an aggregate boundary, and states its local law: field roles, realization constants, relation predicates, and the arithmetic TRANSFER, ADMISSION, and…
(program &key bindings site-domain (compile t))Close PROGRAM over field BINDINGS and emit its scalar realization. SITE-DOMAIN is a form over MATERIALIZATION yielding the chunk domain that gives a site's dense offset spatial meaning. Each field role of the program must have one FRONTIER-FIELD-BINDING. The laws are parsed and quantity checked against the bound…
((source source-offset priority
target target-offset direction destination crossing availability
frontier window domain directions
&key execution result)
&body body)Drain FRONTIER and execute BODY once for every spatial relation it exposes. SOURCE is a retained aggregate materialization and SOURCE-OFFSET is its dense site identity. TARGET is the local SOURCE or a materialization selected by WINDOW at a crossing. DESTINATION has dynamic extent. The client body owns admission,…
(frontier)(frontier)(domain offset)((offset destination crossing direction materialization availability
window domain local directions &optional result)
&body body)Execute BODY for the DIRECTIONS neighboring LOCAL through WINDOW. DIRECTIONS is the caller's explicit neighborhood policy. DESTINATION has dynamic extent on each iteration and must be copied before BODY retains it. Interior steps remain domain arithmetic; window dispatch occurs only at an actual chunk crossing.…
Logical disjunction of tests and raw truth values.
Test whether one compatible scalar is less than another.
Logical conjunction of tests and raw truth values.
Test whether two compatible scalars are equal.
(family definition)Signal an error unless DEFINITION is well formed for FAMILY.
One top-level defining form of a source file.
An explicitly owned libghostty-vt terminal.
How LOWER-LISP-ARITHMETIC-EXPRESSION emits calls: :GENERIC uses the representation-dispatching LISP-ADD family; :SCALAR emits CL operators over declared scalar operands. #53Q1II
(expression environment)Lower checked EXPRESSION to ordinary Lisp using target-to-name ENVIRONMENT.
(&rest operands)(name parameters &body body)Addition over compatible quantities.
Construct a meaningful literal.
One program compiled over bound fields into closed scalar Lisp. TRANSFER, ADMISSION, and PRIORITY are the checked arithmetic expression graphs; DRAIN-FORM and ADMIT-FORM are the emitted lambda forms; the two functions are their compiled realizations. ADMIT-FUNCTION seeds one site through the same admission and…
One program field role bound to storage reachable from a materialization. DECLARATION is the represented-value declaration (often a voxel field definition) giving the field its quantity and Lisp representation. LANES are (NAME FORM &key TYPE): storage borrowed once per materialization, where FORM mentions the…
(name)Return the live frontier program definition named by NAME.
Compiler bookkeeping for one bound field role.
(name specification)(name role)Working state for one COMPILE-FRONTIER-PROGRAM call.
Logical negation of one test or raw truth value.
(compilation form)(compilation)(expression lowered what)(compilation)(definition relaxed-binding)(compilation)(compilation)(family)Whether FAMILY's drain hands sites to a second, companion frontier.
(compilation)Emit the virtual-source relation entry point. The source role's field values arrive as keyword arguments named by role, the relation direction as an argument, and the crossing predicate is true: a virtual source is by definition outside the target's materialization.
Subtraction or unary negation.
Assert that a raw or foreign value is measured in a program field's quantity.
(family compilation candidate-variable
lowering-environment &key seed-p)Return (VALUES TEST-FORM COMMIT-FORMS PRIORITY-FORM OTHERWISE-FORMS) for one exposed target under FAMILY, given the lowering environment of bound field values. CANDIDATE-VARIABLE names the transfer result for monotone families, or the supplied value when SEED-P says the target is being seeded rather than reached…
(name &key declaration lanes read write lazy)(slot-name)Multiplication and scalar scaling.
(field-name)(realization &key (initial-capacity 256))(realization input frontier)((name &key (tracy-value nil tracy-value-supplied-p)) &body body)Measure BODY as nested zone NAME for whichever measurement is watching. TRACY-VALUE, when supplied, is attached to the Tracy zone at exit. It does not affect the bounded CPU trace, whose zones retain time and runtime costs. Two independent things may be: a Tracy viewer attached to this image, and an opt-in…
(realization region frontier execution &key key entry)(realization window frontier execution &rest arguments)Run the compiled program until FRONTIER is empty; return EXECUTION. ARGUMENTS are the program's constants as keywords. A program whose family hands sites to a companion frontier, such as invalidation's surviving sources, takes that frontier as the first argument before the keywords.
(realization region frontier execution)(region coordinate direction)(region key direction)(direction)(entry direction function)Call FUNCTION with OFFSET and borrowed LOCAL for one face of ENTRY. LOCAL has dynamic extent and must be copied before FUNCTION retains it.
(realization window frontier execution materialization offset direction
&rest arguments)Expose one relation into MATERIALIZATION/OFFSET from a virtual source. ARGUMENTS supply the program's constants and, keyed by role name, the source field values the transfer reads; DIRECTION is the relation's direction as seen from that source. The target is tested, committed, and admitted by the same law as an…
(state region)Settle STATE's dirty cells, departures, and arrivals over candidate REGION with the compiled removal and addition programs. Return the executions and the total visits. #K3WRD3
(queue swapchain image-index
&key (wait-semaphores #()) present-id present-stage time-domain-id
target-time target-time-domain-present-stage)(region coordinate)(reconciliation entry offset)(coordinate direction)(world coordinate)(region chunk &key from-field-p copy-content-p)(reconciliation entry direction)(reconciliation)(function execution)(reconciliation entry offset)(reconciliation entry offset)(reconciliation key)(reconciliation)(solver state region)Settle STATE's dirty cells, departures, and arrivals over candidate REGION with the explicitly implemented incremental relighter named by SOLVER. There is deliberately no default method: unsupported names signal rather than falling back to a different algorithm. #K3WRD3
#K3PCP3 asked for terminal discovery as a deliberately simpler client. It now is one program: Its window is the block world itself, whose chunks are the materializations and whose locate-chunk-window-site continues a step across a seam. The memo is a per-chunk bit vector owned by one discovery's table; terminal…
with-cpu-trace-zone is one instrumentation vocabulary with two independent observers. Its outer observer is a real Tracy zone. When Tracy is stopped, the path is one special-variable test. When Tracy is running, a literal zone uses an interned foreign source location and one begin/end FFI pair. The inner observer…
Intent: explain and remove the frontier solver's measured allocation excess without weakening the semantic frontier API. Evidence: bucket-frontier-push constructed `(integer 0 ,maximum-priority) for every runtime typep. Three conses per admission predicted approximately 108 KiB for the 2,304 initial sky sites…
Marco Heisig's fast-generic-functions turns a CLOS generic function into a compiler-specializable one. A client defines the generic function with fast-generic-function as its metaclass, seals a chosen argument domain after installing methods, and supplies enough static argument type information at call sites. On…
Intent: remove the retained frontier's per-item list cell, light-region-site, and copied local-coordinate without prematurely extracting the general fixed-point algebra discussed in #BA9MCA. Represent a lighting site densely as a region entry plus domain offset, while iteration reconstructs only a dynamic-extent…
Affine lattices, combinatorial topology, covers, sheaves, order-theoretic lattices, and discrete exterior calculus are useful sources of distinctions. They draw attention to placement, adjacency, incidence, locality, overlap, restriction, partial knowledge, and values associated with cells or faces. That does not yet…
A chunk-domain should be the one place that knows the finite patch's local shape and storage order. Its useful operational vocabulary is approximately: step-domain-site should report either another local site or a boundary crossing. It should not decide that crossing the east face reaches air, stone, open sky, an…
Maintain two roles with the same semantics but deliberately different loader and dispatch status. – A from-scratch reference relight clears a finite captured region, seeds known sky boundaries and emitters, imports explicit boundary values, and propagates to fixation. It favors obvious correctness and is loaded…
Light has two lattice-like structures. Its sites form a spatial lattice under six-neighbor adjacency. Its levels form a finite order in which max is the join. From-scratch propagation repeatedly joins attenuated neighbor contributions until it reaches a fixed point. Incremental removal first over-removes a region,…
The visible terminal grid is a small, honest client of luv's finite-domain vocabulary. A terminal-grid-domain can own the current column and row counts, answer domain-cardinality with their product, map (x,y) to a row-major offset, and map an offset back to a cell coordinate. Row-major order is not just convenient…
Intent: preserve checked public domain stepping while avoiding the same bounds and coordinate type validation for each of a trusted worklist site's six neighbors. The packed frontier already proves its entry and offset; adjacency should validate that site once, then keep primitive steps inside the checked scope.…
The light solver is the best first proof because it already separates block content, two light fields, palette-derived attenuation and emission tables, boundary availability, fixed-point work, publication, and revision tracking. The arithmetic DSL should describe a local transfer law, not the entire algorithm. In…
Luv's arithmetic work already has the layers this design needs: – luv.arithmetic owns dimensions, units, named quantity meanings, tensor order, and point/absolute/difference character; – luv.arithmetic.language owns backend-neutral checked definitions and expression graphs; – luv.arithmetic.lisp lowers one such…
This figure is the design stance; #SQC5JN is the same idea as ownership layers, and #VIZMU6 / #FTQEQD are its realization as the :luv/arithmetic/language frontend and :luv/arithmetic/lisp backend. It is kept in the argumentative voice because the commitments below — language-owned semantics, driver-owned domain…
Removing a source, or a departed neighbour, leaves levels no surviving source justifies. #DURBKN argued that this is a different dynamic from addition, not an option on it; it is now the :invalidation family, and voxel light's removal program reads: Three things distinguish the family. First, the source's value is…
Intent: expose the shared aggregate operation already visible in the live world, resolved meshing neighborhood, immutable halo snapshot, and light-region atlas. Give those four concrete representations a small protocol for locating a world site or resolving a domain crossing, while keeping availability distinct from…
A planar rectangle of adjacent terminal-material blocks is a useful discover-once client. Starting from a placed or changed block face, the pass can traverse coplanar face neighbors of the same material, reserve a candidate surface identity, and collect bounds and membership. It then validates that the bounding…
The :family clause is semantic, not a label. #DURBKN's dynamics become compiler knowledge: A definition is checked against its family when it is defined, so a monotone program without a relaxed field fails before any realization. This is why the light program states only its transfer, and the terminal program only…
A frontier program is now written as its own semantic source rather than as a name attached to a handwritten loop. Voxel light reads: The clauses divide along the two languages of #53Q1II. :fields names roles the program reads or writes at source and target without saying where they live. :constants are values…
compile-frontier-program takes the definition, one frontier-field-binding per role, and a site-domain template. A binding names the represented-value declaration that gives the field its quantity and Lisp type (for light, the :sky-light voxel field definition and the light-opacity slot declaration), the lanes it…
The proposed frontier language is a DSL compiler, not a generic worklist framework whose inner loop depends on accidental devirtualization. A live, inspectable program definition remains open to Common Lisp development; one compilation closes that definition over particular fields, domains, neighborhoods,…
Intent: let the realization admit a virtual open-sky source through the program's own transfer law, so seeding stops restating the loss arithmetic in client code and a boundary is just a relation whose source is not a site. Evidence: every realization now also emits a relate entry (relate-frontier-realization-site):…
The workloads fall into at least three algorithmic families. – Discover once. Connected components and terminal-wall assembly usually assign each reachable site once for one source revision. A visited bit or component memo prevents repeated work. – Relax monotonically. Distances, influence, and light addition keep…
This page takes an affirmative position: frontier-shaped computation is a real organizing principle for luvcraft, and Common Lisp gives us unusually good means to make that principle executable. The intention is not merely to extract a queue utility from lighting. It is to grow a small frontier language in which a…
Intent: turn the manually staged frontier-light proof into the smallest real compiler path described by #53Q1II. Reify the local transfer, join, admission, and priority arithmetic with checked field meanings; make the program definition drive a scalar execution plan; and emit one closed Lisp loop over bound raw…
Intent: state removal and incremental reconsideration in the same compiled vocabulary after the monotone kernel establishes its source and lowering boundary. Evidence: #ZEENY3. voxel-light-removal is an :invalidation program whose compiled drain reads like unlight-light-region but is emitted from the family and the…
Invalidation. Removing a source, an occluder's disappearance being an addition, or a departed neighbour can leave levels that no surviving source justifies. The removal program clears every level the removed site fed--strictly dimmer, or equal for direct sky continuing down--and re-admits the cleared site at the level it had; a lit neighbour it did not feed is handed to the addition frontier as a surviving source. The cleared set is the execution's retained admissions. #K3WRD3 #DURBKN