Skip to content

Parse spawn, select, and emit - #94

Merged
StreamDemon merged 2 commits into
mainfrom
feature/parser-spawn-select-emit
Aug 17, 2026
Merged

Parse spawn, select, and emit#94
StreamDemon merged 2 commits into
mainfrom
feature/parser-spawn-select-emit

Conversation

@StreamDemon

@StreamDemon StreamDemon commented Aug 17, 2026

Copy link
Copy Markdown
Owner

Closes #93.

Summary

The three reserved keywords had no parse productions — every actor spawn (§8.2/§8.7), multiplexed receive (§8.6), async task (§8.9), and event emission (§11.1/§11.3) failed, including §4.6's own spawn move || { ... } example. This was milestone 1's exit criterion: #67's round-trip and #68's corpus cover the spec's §8 examples, and nearly all of them spawn actors.

  • AST: Spawn(Box<Expr>), SpawnAsync { body: Block } (raw block like Loop), Select { arms: Vec<SelectArm> } with SelectArm { pattern, source, body } (unboxed; block bodies wrapped per MatchArm); Stmt::Emit { event: String, fields } reusing field-init shorthand, spanless per the Stmt convention; plus ExprKind::Tuple for unit/tuple expressions (see below).
  • Parser: spawn_expr() (operand via plain expr(0)not cond_expr(), spawn is not a block-head position, spawn Worker { count: 0 } parses, pinned); select_expr()/select_arm() modeled on the match pair (same arm loop, recovery, comma discipline; deferred pattern? like match_arm; the = delimiter means full or-patterns apply with no closure-param collision); emit as a block_inner() arm next to return — statement-only, no prefix() arm, on-chain-only restriction semantic. can_begin_expr gains Spawn/Select (send-head consequence pinned). Spans anchor at each construct's keyword token (Parse closures and the closure pipe stage #92 lesson), pinned by test.
  • Bonus discovery: the corpus fixture tripped over Ok(()) — the parser had no unit or tuple expression, though the spec's own §11.1 example ends with one and the shape pervades §6/§8/§11. () and (a, b) now parse as ExprKind::Tuple with (a) still grouping; §16's expr list has no explicit alternative for these — recorded as Spec drift: §5.2/§3.7 examples do not derive from the §16 grammar (return-as-expression, ref field-pat shorthand) #89 item 5.
  • Tests: 15 new (91 in the crate) — every node shape structurally; §8.6 select verbatim (return-arm adapted, Spec drift: §5.2/§3.7 examples do not derive from the §16 grammar (return-as-expression, ref field-pat shorthand) #89 item 1's third occurrence); or-pattern select arm; struct-literal pins (spawn operand, select source); greedy spawn (x |> f) pin (§16 grouping ambiguity, noted on Spec drift: §5.2/§3.7 examples do not derive from the §16 grammar (return-as-expression, ref field-pat shorthand) #89); select {…} |> f and pipe-in-arm-body; spawn async with .await tail; emit shorthand + statement-only pin; send-head consequence; span anchors; grammar violations; recovery count; non-tail ; behavior.
  • Corpus: tests/corpus/spawn_select_emit.sp — §4.6 spawn-move (verbatim at last), §8.2 constructor spawns, §8.2a/§8.7 worker pools, §8.9 spawn async + JoinHandle, §8.6 select, §11.1/§11.3 emit inside an onchain mod (18 fixtures total).
  • Docs: crates/AGENTS.md — the three keywords moved to Accepted with parse-only caveats, plus the four sentences the design review flagged as going stale (patterns-wired list gains select arms and notes select's return-arm rejection; send-head list gains spawn/select; the non-tail-; set gains select/spawn async with the Parser: block-like expressions as statements without trailing ; #62 reconciliation note).

Filed on #89 this round: item 5 (unit/tuple expressions), the third item-1 occurrence (§8.6 + §8.8, correcting #89's stale §8.10.1 citation), and the spawn x |> f grouping ambiguity.

Spec Sections Affected

None — implements existing §8/§11/§16; docs/reference/grammar.md remains byte-identical to §16.

Build Targets Tested

N/A — parser crate only, no codegen.

Test Plan

  • cargo fmt --all -- --check — pass
  • cargo clippy --workspace --all-targets -- -D warnings — pass
  • cargo test --workspace — 103 tests pass (11 lexer, 91 parser incl. 15 new, 1 corpus over 18 fixtures)
  • Corpus fixture covers §4.6/§8.2/§8.2a/§8.6/§8.7/§8.9/§11.1/§11.3 shapes
  • CI green (rust.yml triggers: crates/** and tests/corpus/** changed)

Summary by cubic

Parses spawn, select, and emit so actor spawns, multiplexed receive, async tasks, and on-chain event emission now succeed. Previously these keywords had no productions; now spawn/select begin expressions and emit is statement-only. Side effects: send before spawn/select opens a send-statement; non-tail select, spawn async, and brace-final spawn require a trailing ;; spans anchor at each keyword.

  • AST (sploosh-ast): adds ExprKind::Spawn, ExprKind::SpawnAsync { body }, ExprKind::Select { arms: Vec<SelectArm> } with SelectArm { pattern, source, body }, Stmt::Emit { event, fields } (spanless), and ExprKind::Tuple for () and (a, b).
  • Parser (sploosh-parser): spawn takes an unrestricted operand and binds trailing pipes greedily; spawn async takes a raw block. select parses match-style arms using pattern = expr => with full patterns; expression bodies require a trailing comma, block bodies do not. emit parses only as a statement and reuses field-init shorthand. can_begin_expr now includes spawn and select.
  • Behavior to review: send followed by spawn or select opens a send-statement and their operands fail the method-call check. Non-tail select, spawn async, and brace-final spawn forms (spawn { ... }, spawn Type { ... }) need ;. Spans anchor at the construct keyword.
  • Docs/tests: AGENTS.md reflects parse support and clarifies the semicolon rule for brace-final spawn. Adds a corpus covering §4.6/§8/§11 shapes and unit/tuple expression tests.

Written for commit 03058f7. Summary will update on new commits.

Review in cubic

Implements #93 (adversarially reviewed design). The three reserved
keywords had no productions, so every actor spawn (§8.2/§8.7),
multiplexed receive (§8.6), async task (§8.9), and event emission
(§11.1/§11.3) failed - including §4.6's own spawn move || example. This
was milestone 1's exit criterion: #67's round-trip and #68's corpus
cover the spec's §8 examples, and nearly all of them spawn actors.

Adds Spawn (unrestricted-expr operand - a struct-literal operand parses
since spawn is not a block-head position, and trailing pipes bind
greedily into the operand, both pinned by tests), SpawnAsync with a raw
block, Select with match-style arms (the = delimiter means full
patterns apply with no closure-param collision; arms defer pattern
failure exactly like match arms), and the emit statement reusing
field-init shorthand - statement-only, spanless per the Stmt
convention, on-chain-only restriction semantic. Spans anchor at each
construct's keyword token, per the #92 lesson. can_begin_expr gains
Spawn/Select, so send before them opens a send-statement whose operand
fails the method-call check, like closures.

The corpus fixture tripped over Ok(()): the parser had no unit or tuple
expression, though the spec's own §11.1 example ends with one. () and
(a, b) now parse as ExprKind::Tuple with (a) still grouping - §16's
expr list has no explicit alternative for these, recorded as #89 item
5. §8.6's return-arm is the third occurrence of #89 item 1, noted
there along with §8.8 and the spawn-pipe grouping ambiguity.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 4 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread crates/AGENTS.md Outdated
Review feedback on #94: the doc list named only select and spawn async,
but plain spawn with a brace-final operand (spawn { ... }, spawn Worker
{ ... }) is equally block-like at statement position and needs its ;.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 1 file (changes from recent commits).

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Auto-approved: Implements existing spec grammar for spawn/select/emit with 15 new tests and corpus fixtures; change is confined to the parser/AST and introduces no operational or policy tradeoffs.

Re-trigger cubic

@StreamDemon
StreamDemon merged commit 117c77e into main Aug 17, 2026
3 checks passed
@StreamDemon
StreamDemon deleted the feature/parser-spawn-select-emit branch August 17, 2026 01:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Parser: spawn, select, and emit productions (§8.2, §8.6, §8.9, §11.1, §11.3, §16)

1 participant