Skip to content

parse: support parenthesized parallel <*> in pkg/script (grammar parity)#24

Merged
vinodhalaharvi merged 1 commit into
mainfrom
claude/parser-parallel
May 25, 2026
Merged

parse: support parenthesized parallel <*> in pkg/script (grammar parity)#24
vinodhalaharvi merged 1 commit into
mainfrom
claude/parser-parallel

Conversation

@vinodhalaharvi-claude
Copy link
Copy Markdown
Collaborator

What & why

<*> parallel fan-out works in the original internal/agentscript grammar and always has. The newer pkg/script parser — the path loom uses — was built >=>-only (an MVP omission documented in the code), so parallel pipelines that ran fine in the CLI failed through loom. This restores parity: the same DSL that parses in the original runtime now parses in pkg/script. No capability the project already had should be missing from the unified pipeline.

Parser changes (pkg/script/parse.go)

  • Add a Fanout token (<*>) to the lexer
  • Grammar: pipeline = stage ( >=> stage )*; stage = call | group; group = ( pipeline ( <*> pipeline )* ). One-branch group = grouping; two+ branches = parallel fan-out
  • toAST: new stageToAST/groupToAST emit ast.Parallel for multi-branch groups
  • Invariant preserved: a block body is still always an ast.Pipeline; Parallel appears only as a stage

⚠️ An earlier draft collapsed single-stage pipelines and broke three existing parse tests. I caught it, reverted the collapse, and kept the always-Pipeline contract that Lower and the memory bridge depend on. No regression ships.

Downstream was already ready

ast.Parallel / resolved.Parallel exist, Resolve has the ast.Parallel case, and the memory bridge maps resolved.Parallel → the runtime's *Parallel. This PR is purely the parser catching up.

Verified end-to-end (new pipeline)

memory static ( ( ssl_check "google.com" <*> dns_lookup "github.com" ) )
→ parse → resolve → RunMemory → BOTH branches execute in parallel ✓

Complex grammar parses + resolves:

( search >=> analyze <*> search >=> analyze ) >=> merge >=> ask "..."

Tests

parse_parallel_test.go: parallel forms parse; multi-branch group → Parallel stage; single group is not parallel; complex grammar parse+resolves. All prior parse tests still pass (regression guard).

Step Result
vet / gofmt / staticcheck
go test -race ./pkg/...
build

…original grammar)

<*> parallel fan-out works in the original internal/agentscript grammar
and always has. The newer pkg/script parser — the path loom uses — was
built >=>-only (an MVP omission), so parallel pipelines that worked in
the CLI failed through loom. This restores parity: the same DSL that
parses in the original runtime now parses in pkg/script. No capability
the project had may be missing from the unified pipeline.

Parser (pkg/script/parse.go):
  - Add a Fanout token (<*>) to the lexer.
  - Grammar now: pipeline = stage ( >=> stage )* ; stage = call | group ;
    group = ( pipeline ( <*> pipeline )* ). A one-branch group is pure
    grouping; two+ branches is a parallel fan-out.
  - toAST: new stageToAST / groupToAST emit ast.Parallel for multi-branch
    groups; single-branch groups unwrap to their inner pipeline.
  - INVARIANT PRESERVED: a block body is still always an ast.Pipeline
    (even single-stage). Parallel appears only as a stage. (An earlier
    draft collapsed single-stage pipelines and broke three existing parse
    tests — reverted; the always-Pipeline contract that Lower and the
    memory bridge depend on is kept.)

The downstream was already ready: ast.Parallel / resolved.Parallel exist,
Resolve has the ast.Parallel case, and the memory bridge maps
resolved.Parallel → the runtime's *Parallel. So this is purely the parser
catching up.

Verified end to end through the NEW pipeline:
  memory static ( ( ssl_check "google.com" <*> dns_lookup "github.com" ) )
  → parse → resolve → RunMemory → BOTH branches execute in parallel.
Also the full complex grammar parses+resolves:
  ( search >=> analyze <*> search >=> analyze ) >=> merge >=> ask "..."

Tests (parse_parallel_test.go): parallel forms parse; multi-branch group
→ Parallel stage; single group is NOT parallel; complex grammar
parse+resolves. All prior parse tests still pass (regression guard).

CI: vet, gofmt, staticcheck, go test -race ./pkg/..., build pass.
@vinodhalaharvi vinodhalaharvi merged commit 011d32c into main May 25, 2026
1 check passed
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.

2 participants