Map: core (ral-core)

core/ is the ral-core crate — the language engine — and a host reaches it through two narrow crate-root seams: a compile-then-typecheck pipeline that turns source into typed IR, and the framed run door that is the only entry into evaluation. It is the bulk of the codebase (~100k lines of Rust); both binaries, ral and exarch, embed it.

core/src/lib.rs is the front door. The compilation ladder is source → tokens → flat AST → CBPV IR → typed IR, bundled as compile::compile_and_typecheck (parse → elaborate → typecheck, failing with a CompileError of Parse or Types) and, crate-privately, compile (the same ladder without the checker), both returning a Toplevel — a sequence of phrases (Define/Run) run by evaluator::run_phrases, which replaced the flat Comp-rooted top level. Evaluation is not on the crate root — parse, elaborate, and Toplevel are crate-private, reached by the owning module path when a host deliberately steps past the seam (after-turn-api-simplifications).

Reach is enforced rather than intended: an item is pub because something outside the crate names it, pub(crate) otherwise, so dead_code can name an internal whose last caller went away (pub-crate-by-default). Core’s own integration tests link ral-core as an external crate and reach internals through one gated door, core::test_access — its engine reads go through IdentityTransport::inspect, the one test-util-only read of an identity engine’s shell; core’s unit tests boot engines through engine::testkit.

The evaluation seam

Evaluation enters only through the framed run door on Shell, never the reduction primitive behind it. A host states policy; core owns resources.

  • Shell::run(RunRequest) runs one whole Run, synchronously and runtime-agnostic, returning one flat RunReport. Its Program is either source text or a registered hook applied to first-order arguments — Shell::register_hook stores compiled hooks by name in the session-lived hook table (run-turn-is-host-api).
  • Completion is the call returning, never a channel disconnecting, so a deferred worker holding a surface clone cannot keep a run from ending (run-turn-host-loop).
  • The protocol itself is transport-parametric: protocol is the frame algebra (Attach/Dispatch/Event/Control) a front-end speaks, run in-process as the identity transport or across a socket to the engine child (engine-protocol).
  • The reduction host behind the door is crate-private, so a host cannot start an unframed evaluation that would foreground or capture against a stale frame.

host and boot

The crate splits driving a Shell from probing the machine it runs on.

  • boot embeds a Shell in a host process. Shell::root(runtime) constructs over a Runtime, the surface a host chooses through HostSurface::runtime or boot_runtime, so every shell chooses its surface through a door: HostSurface::shell (core’s CORE_SETS, then the host’s sets, no env, no prelude: a loader’s scaffold) or boot_shell, which adds the host env and seats a BakedPrelude whole (BakedPrelude::seat). A half-dressed production shell is unrepresentable, and HostSurface::manifest hands the checker the same list. The prelude is baked ahead of time into a schema-less postcard blob whose single encode site (boot::bake_prelude_to_out_dir) and single decode site (boot::BakedPrelude) sit together, and the build-dependency edge from each host to ral-core reruns the bake, so the schema-evolution hazard has one guard rather than three that must agree (host-embedding-api, evaluator-runtime-split).
  • host probes the underlying machine: git(), os_name/arch/family, wall-clock now(), and re-exports of cwd/user/home. exarch’s host snapshot is a formatter over it.

The pipeline, by judgment

Source text flows down a fixed ladder; each rung is a subsystem page.

  • syntax — lexer and parser, producing the flat surface AST (core/src/syntax/).
  • elaboration — lowers surface forms into CBPV IR (core/src/elaborator.rs).
  • ir — the Val / Comp intermediate representation (core/src/ir.rs).
  • ty — the type language as data, below the IR (core/src/ty.rs, core/src/ty/).
  • typecheck — Hindley–Milner inference with row types (core/src/typecheck/), the sole inference engine, including the grade that places capture (CompTy::Return(Grade, _)).
  • evaluator — the CEK machine over computation closures: focus, frame stack, matching, audit (core/src/evaluator/).
  • runtime — the command/pipeline/transport machinery the machine dispatches into, and the shared re-exec’d-child eval runner (core/src/runtime/, core/src/seed.rs).

Authority, plumbing, surface

  • capabilities — the dynamic capability stack and the OS process sandbox (core/src/capability/, core/src/sandbox/).
  • io-process — byte streams, signals, process groups (core/src/io/, core/src/process/).
  • builtins — Rust-implemented commands and bundled coreutils/grep (core/src/builtins/).
  • shell-state — runtime values and the Shell interpreter state (core/src/types/).
  • transport — the serde mirror and wire envelope that carry a shell across a re-exec (core/src/seed.rs, seed/table.rs, frame.rs).
  • diagnostics — source locations and error rendering (core/src/source.rs, diagnostic.rs, compile.rs, terminal.rs, ansi.rs).
  • prelude — the embedded prelude.ral standard library (core/src/prelude.ral).

Siblings

repl is the ral binary over this engine; exarch is the agent embedding it.

The formal account is docs/SPEC.md; the design rationale lives in the durable layer. These pages point at code, they do not restate it.