Expand description
LOGOS Compilation Pipeline
This module provides the end-to-end compilation pipeline that transforms LOGOS source code into executable Rust programs.
§Pipeline Overview
LOGOS Source (.md)
│
▼
┌───────────────────┐
│ 1. Lexer │ Tokenize source
└─────────┬─────────┘
▼
┌───────────────────┐
│ 2. Discovery │ Type & policy definitions
└─────────┬─────────┘
▼
┌───────────────────┐
│ 3. Parser │ Build AST
└─────────┬─────────┘
▼
┌───────────────────┐
│ 4. Analysis │ Escape, ownership, verification
└─────────┬─────────┘
▼
┌───────────────────┐
│ 5. CodeGen │ Emit Rust source
└─────────┬─────────┘
▼
Rust Source§Compilation Functions
| Function | Analysis | Use Case |
|---|---|---|
compile_to_rust | Escape only | Basic compilation |
compile_to_rust_checked | Escape + Ownership | Use with --check flag |
compile_to_rust_verified | All + Z3 | Formal verification (requires verification feature) |
compile_project | Multi-file | Projects with imports |
compile_and_run | Full + Execute | Development workflow |
§Examples
§Basic Compilation
let source = "## Main\nLet x be 5.\nShow x.";
let rust_code = compile_to_rust(source)?;
// rust_code contains:
// fn main() {
// let x = 5;
// println!("{}", x);
// }§With Ownership Checking
let source = "## Main\nLet x be 5.\nGive x to y.\nShow x.";
let result = compile_to_rust_checked(source);
// Returns Err: "x has already been given away"Re-exports§
pub use crate::concurrency::marshal::decode_value_raw;pub use crate::concurrency::marshal::encode_value_raw;
Structs§
- AotModule
- A compiled AOT-native module (HOTSWAP §Axis-3): the cdylib Rust SOURCE plus the
exact exported
symbolto resolve and itsarity— everything the loader needs. - Check
Artifacts - Compile LOGOS source and write output to a directory as a Cargo project.
- Compile
Output - Full compilation output including generated Rust code and extracted dependencies.
- Crate
Dependency - A declared external crate dependency from a
## Requiresblock. - Genuine
Projection Result - Result of a genuine Futamura projection via self-application. Contains the LOGOS source of the residual and the discovered entry points.
- RunOutcome
- What a program run produced: every output line emitted before completion or
failure, plus the error if it failed. The differential contract is
vm_outcome(src) == tw_outcome(src)— output AND error.
Enums§
- Compile
Error - Errors that can occur during the LOGOS compilation pipeline.
Functions§
- aot_
build_ function - On-demand AOT-native build + load (HOTSWAP §Axis-3): compile
fn_name(and its callees) to an optimized cdylib (cached),dlopenit, and return the loadedcrate::vm::NativeFnready to install viaVm::install_aot_native.Noneif the function is absent / outside the scalar subset / the build or load failed — the caller keeps it on VM+JIT. Blocking (runsrustc); the background worker (BgAotCompiler) calls this off the interpreter thread. - aot_
cache_ key - The cache key for an AOT-native artifact (HOTSWAP §Axis-3 / P16): a deterministic
FNV-1a hash of the rustc toolchain version AND the optimized Rust source. The
toolchain is in the key because Rust has no stable cross-version ABI — a different
rustc/runtime yields a different key, so a stale, ABI-mismatched.sois NEVER reused (soundness over convenience). The source captures the function, its callees, and the optimization config (it IS the codegen output). - aot_
load_ bundle - Load every
native-annotated function insourceas a compiled-nativecrate::vm::NativeFn(HOTSWAP §Axis-3): the run path installs these viaVm::install_aot_native, so an annotated function dispatches torustc -O3machine code from its first call. Uses the persistent cache, so a bundle pre-built bylargo build --native-functionsis a cache hit — norustcon the run path. A function outside the scalar subset / failing to build is skipped (stays on VM+JIT). - build_
native_ bundle - Pre-build every
native-annotated function insourceinto the AOT bundle underbundle_dir(HOTSWAP §Axis-3 / P16 — the “tools to bundle them”). Returns the(function_name, cdylib_path)manifest. Functions outside the sound scalar subset are silently skipped — they keep running on VM+JIT, no gap at the seam.Erronly on a genuine parse/type error. - build_
native_ cdylib - Build AOT-native cdylib Rust source (from
compile_function_to_native_rust) into a loadablecdylib(HOTSWAP §Axis-3 / P16). Generates a minimal crate underwork_dir/<crate_name>, copies the shared runtime crates (so the.soand the interpreter share the SAMElogicaffeine_dataABI), and runscargo build --release. Returns the path to the produced dynamic library.panic = "unwind"(the default) — NOTabort— so a panic in a loaded function can be contained rather than killing the host process. - build_
native_ cdylib_ cached build_native_cdylibwith a persistent cache (HOTSWAP §Axis-3 / P16). The artifact lives atcache_dir/aot_<fn>_<key>/…keyed byaot_cache_key; an identical function reuses its.soacross runs (no rebuild), and a toolchain change yields a new key so the stale library is never loaded.- build_
native_ pe_ binary - build_
native_ pe_ cdylib - Build (and cache) the PE compiled as an IN-PROCESS cdylib exporting
logos_pe_specialize. Mirrorsbuild_native_pe_binarybut emits acdylibwhoselib.rsis the generated PE engine (pe_cdylib_source) plus a hand-writtenextern "C"shim ([PE_CDYLIB_SHIM]) that decodes the wireCProgramand callspeSpecializeOncedirectly — so the caller loads it once and specializes with a plain function call, no process, no pipe. Content-addressed on the (stable) cdylib PE source + shim + toolchain, so warm calls skip rustc. - build_
native_ wasm - Build a function’s AOT module to a browser-loadable
wasm32-unknown-unknowncdylib (HOTSWAP §Axis-3 / P17 — the browser analog ofbuild_native_cdylib). The module is the same scalar-ABI shim; the wasm crate keepslogicaffeine-data+logicaffeine-system(both wasm-ready) but drops the desktop-onlytokio, thelogicaffeine-systemfullfeature, andtarget-cpu=native. Returns the.wasmpath; the browser thenWebAssembly.instantiates it and the entry calls into it through the warm-bytecode indirection. Requires thewasm32-unknown-unknowntarget. - classify_
source - Phase 0 (work/FINISH_INTERPRETER.md): classify the determinacy of a LOGOS program.
- compile_
and_ run - Compile and run a LOGOS program end-to-end.
- compile_
file - Compile a LOGOS source file. For single-file compilation without dependencies.
- compile_
function_ to_ native_ rust - Generate the Rust SOURCE for an AOT-native cdylib of ONE function (HOTSWAP §Axis-3
/ P14b): the
targetfunction plus its transitive callees (crate::codegen::function_slice), emitted through the normal ARCHITECT codegen, with thecrate::codegen::codegen_native_tier_exportshim appended so the loader can resolve thelogos_native_<target>symbol. Mirrorscompile_program_full’s front-end, then slices before codegen. - compile_
program_ full - compile_
program_ full_ deterministic - Compile LOGOS source and return full output including dependency metadata.
- compile_
program_ full_ with_ proven - Like
compile_program_full, but bundles an extracted math/logic module (proven) into the generated Rust — the imperative half of a mixed document. The module is emitted aspub mod proven { … } use proven::*;so the imperative program can call its functions /check_*predicates by name.None(or a blank module) yields output byte-identical tocompile_program_full. - compile_
program_ full_ with_ wire - Like
compile_program_full, but every emitted (non-generic)enumalso getsWireEncode/WireDecodeimpls over the sharedlogicaffeine_data::wirecodec — byte-identical to the peer codec’sencode_value_raw. This lets a compile-once native partial evaluator receive a program AST as data over the same fast codec the interpreter uses. Ordinary compiles (the default) are byte-unchanged. - compile_
program_ traced - Compile
sourcewhile recording which optimizations actually FIRED — the honest, single-compile alternative tooptimizations_used’s O(N) diff. An optimization is “fired” when it actually changed the program or emitted its optimized form for this compile, under the effective (normalized) config. Reusable: any caller can compile a program and learn what fired, for tracing and tooling. - compile_
project - Compile a multi-file LOGOS project with dependency resolution.
- compile_
to_ c - Compile LOGOS source to C code (benchmark-only subset).
- compile_
to_ dir - compile_
to_ rust - Compile LOGOS source to Rust source code.
- compile_
to_ rust_ checked - Compile LOGOS source to Rust with ownership checking enabled.
- compile_
to_ rust_ deterministic - Compile in Mode B (deterministic replay): identical to
compile_to_rustexcept aSelectlowers to the seeded winner-pick that shares the interpreter’s choice function, so a binary run underLOGOS_SEED=…reproduces the interpreter’s selection. Used bylargo build --deterministicand the seeded differential harness. Non-Selectemission is unchanged. - compile_
to_ rust_ traced - One compile returning the generated Rust, the fired-optimization keywords, AND
the
(winner, loser)precedence decisions made — what an interactive viewer calls per toggle state to show the firing opts and the conflicts that occurred. - compile_
to_ rust_ with_ proven - Compile imperative LOGOS to Rust with an extracted math/logic module bundled in.
provenis a main-less Rust module body (the Forge’s extraction); it is emitted aspub mod proven { … } use proven::*;so the imperative program can call its functions /check_*predicates by name. Seecompile_program_full_with_proven. - compile_
to_ wasm - Compile LOGOS source DIRECTLY to a self-contained WebAssembly module — no rustc, no cargo,
no wasm-bindgen, no toolchain. Uses the SAME front-end as
vm_outcome(crate::ui_bridge::with_parsed_program→crate::vm::Compiler::compile_with_types), so the emitted module runs the IDENTICAL bytecode the VM does; the AOT WebAssembly backend then lowers the whole program to.wasm. - compile_
to_ wasm_ linked - Compile LOGOS source to a LINKED WebAssembly module that uses the real
logicaffeine_base::BigIntruntime for arbitrary-precision integer arithmetic: an overflowing integer expression (Show 99999999999 * 99999999999,Show 2 to the power of 200) computes the EXACT big number — matching the VM’s promote-on-overflow — instead of trapping, andShowprints its decimal. - copy_
runtime_ crates - Copy the runtime crates to the output directory. Copies logicaffeine_data and logicaffeine_system.
- core_
interp_ source - The self-interpreter (
coreEval/coreExecBlock) as a first-class committed artifact — the Logos program the genuine P2/P3 projections specialize (Futamura:pe(pe, coreEval)is a compiler). Promoted out of thephase_futamuratest fixture so it is a real source file, not a string constant; the fixture nowinclude_str!s this exact file (parity is structural). - core_
types_ for_ pe_ source - The canonical inductive type catalog the Futamura projections are built on
(
CStmt/CExpr/CVal/…). Every statement the tree-walker executes has aC…constructor here; the partial-evaluator dialects dispatch on it. Exposed so cross-tier lock tests can prove this catalog and every tier stay in sync — a statement added to the language must appear here or it is dropped from the projections (seetier_parity_lock.rs). - count_
dispatch - The Jones-optimality oracle: count the units of interpreter dispatch remaining in a residual program.
- decompile_
source_ text - display_
float_ like_ logos - Format an
f64exactly as aShowof aFloatwould — i.e. byte-identical to the tree-walker / VM (RuntimeValue::to_display_string). The direct-WASM host’sprint_f64sink uses this so aShowof a float matches every other engine. Delegating to the real formatter (rather than re-deriving it) makes drift impossible. - encode_
program_ source - Encode a LogicAffeine program (given as source) into CProgram construction source.
- encode_
program_ source_ compact - Compact encoding: inlines simple expressions (literals, variables) to reduce encoding size by ~3x. Same semantics as encode_program_source but produces fewer Let statements.
- finish_
projection1_ residual - The post-processing applied to a raw PE residual (the
Any-type safety net +## Mainnormalization). - first_
parallel_ block_ independent - Phase 0 test seam: is the first
Simultaneously:/Attempt all of the following:block insourcemade of data-independent branches?Noneif the program contains no such block. - genuine_
projection2_ residual - Run genuine PE(pe_source, pe_mini(targetStmts)) and return the specialized compiler residual as LOGOS source code.
- genuine_
projection3_ residual - Run genuine PE(pe_source, pe_bti(targetExpr)) and return the specialized cogen residual as LOGOS source code.
- interpret_
program - Interpret LOGOS source and return output as a string.
- native_
export_ function_ names - The names of functions annotated for the AOT-native tier —
## To <fn> … is exported for native:(HOTSWAP §Axis-3 selectivity). These are the functionslargo build --native-functionspre-bundles; everything else stays on VM+JIT. - next_
inspect_ otherwise_ idx - The next
Inspect-with-Otherwiseflag index (post-increment). Called at the START of each such Inspect’s desugaring in BOTH encoders, so a nested Inspect gets a strictly higher index than its enclosing one — no two live flags ever collide. - optimization_
dependencies - The per-program DEPENDENCY edges for
source, discovered by evaluating with all optimizations on and probing: disabling a fired optimizationdepthat makes another fired optimizationdependentSTOP firing meansdependentdepended ondepfor this program. Stops already explained by a declaredrequires-cascade (normalizewould disable the dependent anyway) are excluded — those are captured by the static registry graph. What remains are the EMERGENT, program-specific dependencies (e.g. dead-code elimination only had work because scalarization produced the dead code): returned as(dependent, dep)keyword pairs, sorted and deduped (deterministic). - optimization_
graph - The complete per-program optimization graph from one all-on evaluation: the
optimizations that
fired, theblockers((winner, loser)preemptions that occurred), and the emergentdependencies((dependent, dep)— seeoptimization_dependencies). Everything the menu-tree needs, baked once per benchmark so the UI never probes in the hot path. All on the AOT codegen path (the one that produces the shown Rust), so the three views agree. - optimization_
preemptions - The
(winner, loser)precedence decisions the compiler made forsource— the conflicts traced at their source (mark_preempted), under the effective config. - optimizations_
fired - The decorator keywords of the optimizations that fired for
source(registry order), under the default/effective config. One compile, exact. - optimizations_
fired_ run - The optimizations that fired on the RUN path — the VM/interpreter optimizer
(
optimize_for_run) — forsource. The run-path analogue ofoptimizations_fired(which traces the AOT codegen path); it surfaces the run-path-only passes — inlining, loop-carried CSE, float strength reduction — the AOT trace cannot see. Respects file-level## No <opt>decorators. - optimizations_
fired_ vm - The optimizations that fired while compiling
sourceto VM bytecode — the third path, after AOT codegen and the run-path optimizer. Surfaces the VM-compile-time opts (constant-divisor magic division, VMi32narrowing) the other two traces cannot see. Compiles only (no execution), so it is fast and needs no program arguments. - optimizations_
fired_ with - The optimizations that fired for
sourceunder an explicit config — re-traces an arbitrary toggle state (turning some off can make others fire). Realised by disabling that config’s off-keywords on the source, then tracing. - optimizations_
used - Which optimizations actually FIRE for
source: an optimization is “used” when disabling it (via a file-level## No <X>decorator) changes the generated Rust. Lets the benchmarks UI show, per program, which optimizations it USES vs the full set it CAN use. O(number of optimizations) compiles — intended for per-benchmark, not hot-path, use. Returns the decorator keywords of the firing optimizations (in registry order). - pe_
bti_ source_ text - pe_
cdylib_ source - The PE as an IN-PROCESS cdylib entry: the identical engine to
pe_native_source, but the driver is a single-shot## To peSpecializeOnce (__prog: CProgram) -> Textthat RETURNS the residual instead of writing it to stdout — noreadWireProgram/writeWireResidual, no stdin loop. The exported cdylib (build_native_pe_cdylib) decodes the wire bytes to aCProgramin itsextern "C"shim and calls this function directly, so the resident server’s process/pipe round-trip is gone.## Mainis a trivial stub (a cdylib never runs it). - pe_
combined_ source - Assemble the full PE-run source (core types + PE + decompiler + encoded
input + driver) — the exact program
projection1_source_real_fastexecutes. Public so differential harnesses can run it on a specific engine. - pe_
mini_ source_ text - pe_
native_ source - pe_
source_ text - Returns the source text of the partial evaluator written in LogicAffeine.
- program_
covered_ by_ native_ builder - Whether the native Core-IR value builder covers
program(the fast marshal path is taken, not the interpreter fallback). For test coverage assertions. - program_
to_ core_ wire_ bytes - Serialize a program’s Core-IR
CProgram(aCProgwith its functions and main block) to the plain wire form — the bytes a compile-once native partial evaluator reads on stdin. FAST PATH: [program_to_core] on [WireSink] emits the wire bytes in ONE pass straight from the AST — no intermediateRuntimeValuetree and no secondencode_value_rawwalk (byte-for-byte identical to the old two-pass form; locked bynative_builder_is_byte_identical_to_the_interpreter). FALLBACK: for a construct the native builder does not cover, run the constructor source on the tree-walker (wireBytes). Both are decoded identically by the native binary’s generatedCProgram::wire_decode. - program_
to_ core_ wire_ bytes_ two_ pass - The TWO-PASS marshal that
program_to_core_wire_bytesreplaced: build the fullRuntimeValueCore-IR tree ([TreeSink]) thenencode_value_rawit. Kept as the correctness ORACLE and the speed BASELINE for the single-pass ([WireSink]) form — the two are byte-identical by construction (WireSinkemits exactly whatencode_value_rawwould), and the single pass avoids the tree allocation + the second encode walk.Noneif a construct is uncovered. - program_
to_ core_ wire_ bytes_ via_ interpreter - The REFERENCE marshal: always the interpreter path (construct the
CProgramvia the tree-walker,wireBytes-serialize it). The native builder’s output must be BYTE-IDENTICAL to this — locked bynative_pe_wire::native_builder_is_byte_identical_to_the_interpreter. Kept public so the lock can force the reference regardless of native-builder coverage. - projection1_
source - First Futamura Projection: PE(interpreter, program) = compiled_program
- projection1_
source_ real - Real Futamura Projection 1: pe(program) = compiled_program
- projection1_
source_ real_ fast - In-process variant of
projection1_source_real. - projection1_
source_ real_ fast_ on_ vm - VM-driven twin of
projection1_source_real_fast. - projection2_
source - Second Futamura Projection: PE(PE, interpreter) = compiler
- projection2_
source_ real - Genuine Futamura Projection 2 via self-application: PE(pe_source, pe_mini(targetStmts))
- projection3_
source - Third Futamura Projection: PE(PE, PE) = compiler_generator
- projection3_
source_ real - Genuine Futamura Projection 3 via self-application: PE(pe_source, pe_bti(targetStmts))
- quote_
pe_ source - Encodes the partial evaluator as CProgram construction source code.
- run_
genuine_ p2_ on_ target - Run genuine P2 on a specific target: PE(pe_source, pe_mini(target))
- run_
genuine_ p3_ on_ target - Run genuine P3 on a specific target: PE(pe_source, pe_bti(target))
- run_
logos_ source - Compile and run LOGOS source, returning stdout.
- run_
native_ pe - Specialize
programon the compile-once native PE — the DEFAULT entry and the pit of success. Prefers the IN-PROCESS cdylib path (run_native_pe_inprocess; no process/pipe boundary) and falls back to the resident server (run_native_pe_server) only if the in-process build/load fails (e.g. no toolchain), so the fast+correct route is what every caller gets by default. The two paths are proven byte-identical bynative_pe_wire. - run_
native_ pe_ inprocess - Specialize
programon the compile-once native PE, IN PROCESS: marshal it to wire bytes, hand them to thedlopened PE cdylib’slogos_pe_specializeas a plain function call, and reclaim the residual bytes. No child process, no pipe — the ~59 µs IPC round-trip of the resident server is gone; all that remains is the host marshal + nativepeBlock+ one FFI call. The cdylib is built + loaded ONCE per thread and cached. Residual-identity with the server / tree-walker is locked bynative_pe_wire. - run_
native_ pe_ server - rustc_
check - Run rustc’s analysis over a LOGOS program and translate every finding back to English with real user-source spans — the flycheck engine.
- rustc_
check_ artifacts - Compile for CHECKING: the same front as
compile_program_fullbut with the optimizer off and mapped codegen, so every generated line ties back to its statement span and the map stays 1:1 (the optimizer may fuse or drop statements; a check build has no use for its output anyway). - send_
check_ source - Phase 4 (work/FINISH_INTERPRETER.md): run the Send/escape analysis over a program.
- stmts_
to_ core_ wire_ bytes - The PARSE-FREE marshal: emit a program’s Core-IR wire bytes directly from an ALREADY-PARSED AST,
skipping the lex + discovery +
parse_programthat dominatesprogram_to_core_wire_bytes(~90% of a specialization). An integrated caller that parsed the program once for compilation reuses that AST here to feed the native PE at a fraction of the cost.variant_fieldsmaps each variant constructor name to its ordered field names (the caller derives it from its type registry, as [program_to_core] does).Noneif a construct is uncovered. Byte-identical toprogram_to_core_wire_byteson the same program — same [build_core]/[WireSink] spine. - tw_
outcome - Run
sourceon the TREE-WALKER (the oracle), capturing partial output and the error, if any. This entry point always uses the tree-walker — the dispatchinginterpret_for_ui_syncnow runs the VM for the sync path, and the differential suites need the oracle by itself. - tw_
outcome_ with_ args tw_outcomewith the program argument vector for theargs()system native (full argv; index 0 is the program name) — the seam the benchmark corpus differential uses to runmain.lgprograms that read their size from argv.- verify_
no_ overhead_ source - Verify that a LogicAffeine program has no interpretive overhead.
- vm_
outcome - Run
sourceon the bytecode VM, capturing partial output and the error, if any. Same front-end astw_outcome. - vm_
outcome_ bg vm_outcome_with_argsdriven through the BACKGROUND native compiler (HOTSWAP §6): hot functions compile on a worker thread off the interpreter’s path. Requires a process-installed tier (the P8 gate installs one first). The compiled chain is identical to the synchronous one — only WHEN it is produced differs — so output must match the synchronous/tree-walker engines exactly.- vm_
outcome_ concurrent - The VM outcome for a CONCURRENT program — drives the bytecode VM on the cooperative scheduler
(
VmTaskonrun_with_seed, seed 0) exactly as the browser/playground does, so aPipe/task/Selectprogram runs on the VM byte-identical to the tree-walker’s async path. The plainvm_outcomeerrors on any concurrency op (requires the scheduler driver); this is the oracle the AOT concurrency lock compares against so tw == VM == AOT is verifiable for the concurrent set. - vm_
outcome_ net - The VM outcome for a peer-NETWORKING program — drives the resumable bytecode VM and services each
VmBlock::Net*through the shared LOCALNetInbox(the same inbox the tree-walker’s offline mode uses), soListen/Send/Sync/PeerAgentrun on the VM byte-identical to the tree-walker. The AOT networking lock compares against this so tw == VM == AOT holds for the local-mode net set. - vm_
outcome_ tiered vm_outcome_with_args, but the statements pass through the run-path optimizer at an explicit hotnesstier(HOTSWAP §4) before reaching the VM — the seam thetier_invariancegate drives at every tier T0..T3 to assert byte-identical output.tier = Tier::T3reproduces today’s optimized run path.- vm_
outcome_ with_ args vm_outcomewith the program argument vector and an optional private native tier (so a differential test can observe THAT program’s JIT compile counters in isolation — the process-wide tier’s counters are shared by every test in the binary).- vm_
run_ source - Parse LOGOS source and execute it on the register bytecode VM, returning the
captured output. Uses the SAME front-end as the tree-walker
(
crate::ui_bridge::with_parsed_program: lex → MWE → discovery → parse), so differential tests compare two engines on one program, never two programs. ReturnsErrfor programs outside the VM’s supported subset (the compiler reportsvm: unsupported …). - write_
cargo_ project - Write a generated program as a runnable cargo project:
src/main.rs,Cargo.toml(runtime path-deps + user## Requires),.cargo/config.toml, and the staged runtime crates. Shared bycompile_to_dirandrustc_check.