Skip to content

Commit 00d34ad

Browse files
fix: exhaustive Statement match for concurrency variants (restores build) (#56)
## Problem The `Statement` enum in `src/ast/mod.rs` gained worker/concurrency variants (`WorkerSpawn`, `SendMessage`, `ReceiveMessage`, `AwaitWorker`, `CancelWorker`) but several `match stmt` sites were never updated. This produced `error[E0004]` non-exhaustive match and broke `cargo build` (the `woke` binary failed to compile; `cargo build --lib` exited 101). ## Sites fixed Four match sites were missing the new variants: 1. **`src/ast/visitor.rs` — `walk_statement`** (missing `SendMessage`, `ReceiveMessage`, `AwaitWorker`, `CancelWorker`): `SendMessage` now recurses into its `message` expression, exactly like the neighbouring expr-bearing arms (`Expression`, `Assignment`, …). The three name-only variants are leaves, so they join the existing leaf arm alongside `WorkerSpawn`/`Complain`/`Break`/`Continue`. 2. **`src/interpreter/mod.rs` — `execute_statement`** (missing `SendMessage`, `ReceiveMessage`, `AwaitWorker`, `CancelWorker`; `WorkerSpawn` was already handled): There is no worker-name-addressed messaging runtime — `WorkerSpawn`'s own inline comment states workers communicate via channels created in the main scope, and workers run detached. Rather than fake a no-op, each of the four variants returns a clear, actionable `RuntimeError` (built with `RuntimeError::new`, consistent with the `Complain` arm and the break/continue-outside-loop guards), pointing the user at the channel-based pattern. 3. **`src/sexpr.rs` — `stmt_to_sexpr` and `stmt_to_json`** (both missing all four variants): real serialization added for each, matching the style of neighbouring arms (`(send :to "..." <expr>)`, `(receive :from "...")`, `(await-worker "...")`, `(cancel-worker "...")`; and the equivalent JSON objects). No silent `_ => {}` catch-all was introduced anywhere, so any future `Statement` variant will continue to surface as a compile-time error. ## Build verification ``` $ cargo build --lib warning: `wokelang` (lib) generated 14 warnings Finished `dev` profile [unoptimized + debuginfo] target(s) $ cargo build warning: `wokelang` (bin "woke-dap") generated 1 warning Finished `dev` profile [unoptimized + debuginfo] target(s) $ cargo test --no-run Executable unittests src/bin/woke-lsp.rs (...) Executable tests/codegen_test.rs (...) Executable tests/e2e_full_pipeline_test.rs (...) Executable tests/lsp_handler_test.rs (...) Executable tests/lsp_integration_test.rs (...) Executable tests/property_test.rs (...) ``` All three complete with no errors (pre-existing warnings only). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: hyperpolymath <hyperpolymath@users.noreply.github.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 4655f3b commit 00d34ad

3 files changed

Lines changed: 59 additions & 1 deletion

File tree

src/ast/visitor.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,10 @@ pub fn walk_statement<V: Visitor>(v: &mut V, stmt: &Statement) {
7474
for s in &c.body { v.visit_statement(s); }
7575
}
7676
Statement::Expression(e) => v.visit_expr(&e.node),
77-
Statement::WorkerSpawn(_) | Statement::Complain(_)
77+
Statement::SendMessage(s) => v.visit_expr(&s.message.node),
78+
Statement::WorkerSpawn(_) | Statement::ReceiveMessage(_)
79+
| Statement::AwaitWorker(_) | Statement::CancelWorker(_)
80+
| Statement::Complain(_)
7881
| Statement::Break(_) | Statement::Continue(_) => {}
7982
Statement::EmoteAnnotated(e) => v.visit_statement(&e.statement),
8083
Statement::Decide(d) => {

src/interpreter/mod.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,30 @@ impl Interpreter {
515515
Ok(Value::Unit)
516516
}
517517

518+
Statement::SendMessage(send) => Err(RuntimeError::new(format!(
519+
"Worker-addressed message passing is not implemented: cannot `send` to worker '{}'. \
520+
Use a channel created in the main scope and pass it to the worker instead.",
521+
send.target
522+
))),
523+
524+
Statement::ReceiveMessage(recv) => Err(RuntimeError::new(format!(
525+
"Worker-addressed message passing is not implemented: cannot `receive` from worker '{}'. \
526+
Use a channel created in the main scope and pass it to the worker instead.",
527+
recv.source
528+
))),
529+
530+
Statement::AwaitWorker(await_worker) => Err(RuntimeError::new(format!(
531+
"Awaiting a worker by name is not implemented: cannot `await` worker '{}'. \
532+
Workers run detached; synchronise via a channel created in the main scope.",
533+
await_worker.worker_name
534+
))),
535+
536+
Statement::CancelWorker(cancel) => Err(RuntimeError::new(format!(
537+
"Cancelling a worker by name is not implemented: cannot `cancel` worker '{}'. \
538+
Workers run detached and cannot currently be cancelled.",
539+
cancel.worker_name
540+
))),
541+
518542
Statement::Complain(complain) => Err(RuntimeError {
519543
message: complain.message.clone(),
520544
}),

src/sexpr.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,20 @@ fn stmt_to_sexpr(stmt: &Statement, out: &mut String, indent: usize) {
331331
Statement::WorkerSpawn(w) => {
332332
out.push_str(&format!("(spawn-worker \"{}\")", w.worker_name));
333333
}
334+
Statement::SendMessage(s) => {
335+
out.push_str(&format!("(send :to \"{}\" ", s.target));
336+
expr_to_sexpr(&s.message.node, out, indent + 2);
337+
out.push(')');
338+
}
339+
Statement::ReceiveMessage(r) => {
340+
out.push_str(&format!("(receive :from \"{}\")", r.source));
341+
}
342+
Statement::AwaitWorker(a) => {
343+
out.push_str(&format!("(await-worker \"{}\")", a.worker_name));
344+
}
345+
Statement::CancelWorker(c) => {
346+
out.push_str(&format!("(cancel-worker \"{}\")", c.worker_name));
347+
}
334348
Statement::Complain(c) => {
335349
out.push_str(&format!("(complain \"{}\")", c.message));
336350
}
@@ -710,6 +724,23 @@ fn stmt_to_json(stmt: &Statement) -> serde_json::Value {
710724
"type": "spawn_worker",
711725
"name": w.worker_name
712726
}),
727+
Statement::SendMessage(s) => serde_json::json!({
728+
"type": "send_message",
729+
"target": s.target,
730+
"message": expr_to_json(&s.message.node)
731+
}),
732+
Statement::ReceiveMessage(r) => serde_json::json!({
733+
"type": "receive_message",
734+
"source": r.source
735+
}),
736+
Statement::AwaitWorker(a) => serde_json::json!({
737+
"type": "await_worker",
738+
"name": a.worker_name
739+
}),
740+
Statement::CancelWorker(c) => serde_json::json!({
741+
"type": "cancel_worker",
742+
"name": c.worker_name
743+
}),
713744
Statement::Complain(c) => serde_json::json!({
714745
"type": "complain",
715746
"message": c.message

0 commit comments

Comments
 (0)