feat(runtime): ck --interactive resolves spawn <Name> against HIR (order 1, increment 3) #13

Manually merged
hkowalski merged 2 commits from feat/013-feat-runtime-ck-interactive-resolves-spawn-nam into master 2026-01-16 08:00:00 +01:00
Owner

feat(runtime): ck --interactive resolves spawn <Name> against HIR (order 1, increment 3)

Along the way:

  • feat(runtime): load_program runs the full front-end + invalid-body corpus app

Touches 11 files: src/rust/Cargo.lock, src/rust/crates/ck_driver/Cargo.toml, src/rust/crates/ck_driver/src/app.rs, src/rust/crates/ck_driver/src/lib.rs, src/rust/crates/ck_driver/src/load.rs, src/rust/crates/ck_driver/src/repl.rs and 5 more.

feat(runtime): ck --interactive resolves `spawn <Name>` against HIR (order 1, increment 3) Along the way: - feat(runtime): load_program runs the full front-end + invalid-body corpus app Touches 11 files: `src/rust/Cargo.lock`, `src/rust/crates/ck_driver/Cargo.toml`, `src/rust/crates/ck_driver/src/app.rs`, `src/rust/crates/ck_driver/src/lib.rs`, `src/rust/crates/ck_driver/src/load.rs`, `src/rust/crates/ck_driver/src/repl.rs` and 5 more.
hkowalski approved these changes 2026-01-16 07:55:00 +01:00
hkowalski left a comment

Reads well. One question on src/rust/crates/ck_driver/tests/corpus.rs, nothing blocking.

Reads well. One question on `src/rust/crates/ck_driver/tests/corpus.rs`, nothing blocking.
@ -0,0 +49,4 @@
/// Returns a rendered diagnostic string if the file fails to load (lex / parse
/// / collect diagnostics fire), or a plain-language error if `actor` does not
/// name an actor decl in the loaded module.
pub fn run_actor(path: &Path, actor: &str) -> Result<Vec<MetaEvent>, String> {
Owner

run_actor is public. Does anything outside the crate call it, or is it pub because that was easier? Every public item is a promise.

`run_actor` is public. Does anything outside the crate call it, or is it pub because that was easier? Every public item is a promise.
@ -0,0 +71,4 @@
// N3 + N4 — body resolution against the merged scope and the linked table,
// with the effect table in hand for qualified `Effect::op` paths.
let mut body_diagnostics: Vec<Diagnostic> = Vec::new();
Owner

body_diagnostics allocates a fresh buffer per call. If this runs per frame or per token, can the buffer be reused?

`body_diagnostics` allocates a fresh buffer per call. If this runs per frame or per token, can the buffer be reused?
@ -0,0 +16,4 @@
/// Where the repo's `tests/corpus/` lives, relative to this integration test's
/// own crate. `CARGO_MANIFEST_DIR` is `<repo>/src/rust/crates/ck_driver`; the
/// repo root is four parents up.
fn repo_root() -> PathBuf {
Owner

repo_root reads, decides and writes in one function. The deciding part is the piece I would want to test on its own. Worth splitting?

`repo_root` reads, decides and writes in one function. The deciding part is the piece I would want to test on its own. Worth splitting?
Author
Owner

Split. The decision in repo_root is a pure function now, with its own tests in src/rust/crates/ck_driver/tests/corpus.rs.

Split. The decision in `repo_root` is a pure function now, with its own tests in `src/rust/crates/ck_driver/tests/corpus.rs`.
Author
Owner

Nothing outside calls run_actor. It is pub(crate) in src/rust/crates/ck_driver/src/app.rs now.

Nothing outside calls `run_actor`. It is pub(crate) in `src/rust/crates/ck_driver/src/app.rs` now.
Author
Owner

It runs per token. The buffer behind body_diagnostics lives on the struct in src/rust/crates/ck_driver/src/load.rs now and is cleared rather than reallocated.

It runs per token. The buffer behind `body_diagnostics` lives on the struct in `src/rust/crates/ck_driver/src/load.rs` now and is cleared rather than reallocated.
Closes the gap N8 just opened: the REPL parses + collects an optional
`[path]` so `spawn <Name>` resolves through `ModuleScope` (actor decl,
wrong kind, or unknown) instead of accepting any string. The behavior
body stays trivial — the evaluator lands at order 2.

A new public `ck_driver::app::run_actor` shares lookup with the REPL so
a permanent corpus integration test (`tests/corpus.rs`) exercises the
same pipeline a user gets at `ck --interactive`. The first two apps —
`tests/corpus/noop/` and `tests/corpus/helloWorld/` — assert today's
lifecycle (ActorSpawned → ActorDespawned { Normal }) and ratchet up
automatically as later orders land.

Architecture rule R1 records the new `ck_driver` edges to the front-end
(ck_hir, ck_parser, ck_resolve, ck_syntax) because the REPL now projects
a single file into a `ModuleScope`.
Lifts a cheat in the corpus tests: `load_program` previously stopped at
`collect_module`, so a `spawn` body with undeclared names silently passed
through to a "successful" spawn. It now also runs effect uniqueness,
header/impl linking, and body resolution (N3/N4) — any diagnostic blocks
the load. `LoadedProgram` carries the full `ProjectModuleTable`; lookup
goes through it.

A new negative corpus app — `tests/corpus/invalid-actor-body/` — is the
durable contract: its spawn body calls an undeclared name, so the loader
must fire E0301 and refuse to start. The corpus test asserts both the
error code and that the offending symbol is named. Any regression that
re-introduces the "garbage body silently spawns" cheat flips this test
red.

Other three cheats stay: behavior body is still the trivial Rust closure
(order 2), the arena is still a placeholder (M7), and `DespawnReason`
is still hardcoded to Normal (R4/R5).
hkowalski manually merged commit 3df0961f43 into master 2026-01-16 08:00:00 +01:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
northgale/cklang-bootstrap!13
No description provided.