Skip to content

Parser correctness wave: integration base#69

Merged
StreamDemon merged 5 commits into
mainfrom
fix/parser-correctness-base
Jul 2, 2026
Merged

Parser correctness wave: integration base#69
StreamDemon merged 5 commits into
mainfrom
fix/parser-correctness-base

Conversation

@StreamDemon

@StreamDemon StreamDemon commented Jul 2, 2026

Copy link
Copy Markdown
Owner

Summary

  • Integration base branch for the parser correctness wave — sub-PRs carrying individual parser/lexer correctness fixes will target this branch and squash-merge into it; this PR merges to main once the wave is complete (same stacked-PR pattern as the v0.5.10 cleanup, see PR Spec v0.5.10: Cleanup batch (integration) #40).
  • Seeds the branch with a truth-up of the crates/AGENTS.md "Implemented subset" gap list: spawn, select, emit, if let, let destructuring patterns, and #[...] compiler directives lex but have no parse production, and storage { } blocks inside onchain mod are consumed but discarded. The list now matches empirically verified parser behavior.

Note for reviewers (stacked-PR architecture): sub-PRs into this branch intentionally keep their scope to the fixes they carry; this base PR owns the wave-level docs reconciliation at merge time. Planned sub-PRs:

  1. Pipe-stage ? misparse (§5.7/§16 pipe_stagex |> f? must parse as (x |> f)?), impl Trait for Type, trait generics/supertraits, dyn Trait<Args>.
  2. Spec-mandated parse errors currently accepted silently: send operand must be a method call (§2.7), assignment-target validation (§16 assign_target), vec!(...) silent !-swallow.
  3. Lexer literal validation: empty '' char literal, bare 0x/0o/0b, integer suffix on float literals, separator-before-exponent (1_e5).

Related Issue

None (review-driven; findings from a full parser-vs-§16 audit).

Spec Sections Affected

None — implementation and crates/ docs only. The spec remains authoritative; these fixes bring the parser toward it.

Checklist

  • Code follows the Sploosh design principles (one way to do it, explicit over implicit, etc.)
  • Documentation updated in relevant docs/ pages (crates/AGENTS.md subset contract)
  • Tests added or updated (sub-PRs carry the tests)
  • All build targets still compile (if applicable)
  • Spec-only PR (skip Build Targets section if checked)

Build Targets Tested

  • N/A (docs/spec only)

Test Plan

  • Docs-only seed commit; cargo test --workspace remains green (11 tests).
  • Each sub-PR carries its own unit tests and corpus fixtures; the wave merges to main only with CI green.

Summary by cubic

Seeds the parser correctness wave branch and lands fixes for |> semantics, impl Trait for Type, trait headers, dyn Trait<...>, grammar checks for send, assignment targets, vec! brackets, and §16.1 lexical literal rules, plus enforcement of non-associative ranges and item modifier placement (offchain/async only on fn; pub rejected on impl/actor/onchain/extern). Updates crates/AGENTS.md and adds unit/corpus tests.

  • Bug Fixes
    • |>: stage-as-callee; trailing ? wraps the accumulated pipe; supports method chains/args/turbofish (final segment only); explicit errors for closure stages and non-final turbofish.
    • impl Trait for Type: records trait ref; parses trait generics, supertraits, and where; supports dyn Trait<...> with type and associated-type args.
    • send: statement-head rule enforced; operand must be a method call.
    • Assignment: validates left side per §16 assign_target.
    • vec!: requires []; vec!(...)/vec!{...} are parse errors.
    • Literals (§16.1): rejects empty '', bare 0x/0o/0b, integer suffixes on float literals, float suffixes on based literals; separators must be between base-valid digits; overflow checking deferred to semantic analysis.
    • Ranges: ../..= are non-associative; chained ranges are a parse error with the diagnostic anchored to the second operator.
    • Item modifiers: offchain/async apply only to fn items; pub is rejected on impl, actor, onchain, and extern items with errors on the modifier token span.

Written for commit 4247268. Summary will update on new commits.

Review in cubic

A review of the parser against spec §16 confirmed several missing
productions that the "Not yet implemented" list did not mention:
`spawn`, `select`, `emit`, `if let`, `let` destructuring patterns, and
`#[...]` compiler directives all lex but fail to parse, and `storage { }`
blocks inside `onchain mod` are consumed but discarded. The subset
contract is the source of truth for what the bootstrap parser accepts,
so the list must match observed behavior.

This commit seeds the integration branch for the parser correctness
wave; fix sub-PRs will merge into this branch and update the lines they
change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H3CinyyqWL6SfCLrKGm3ja
cubic-dev-ai[bot]
cubic-dev-ai Bot previously approved these changes Jul 2, 2026

@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.

No issues found across 1 file

Confidence score: 5/5

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

Auto-approved: Docs-only update aligning AGENTS.md gap list with verified parser behavior. No code changes.

Re-trigger cubic

)

* Fix pipe-stage ?, impl Trait for Type, trait headers, and dyn type args

Four parser bugs found by an empirical review against spec section 16,
all in surface the subset contract claims to support:

- `x |> f?` parsed as `x |> (f?)` because `|>` was an ordinary binary
  operator and the `?` postfix bound inside the right operand. Spec
  sections 5.7 and 16 (pipe_stage) mandate `(x |> f)?` -- the stage's
  trailing `?` wraps the accumulated pipe application. The RHS of `|>`
  now goes through a dedicated pipe_stage() production (callee path,
  optional turbofish, field chain, optional args) and the caller wraps
  the accumulated pipe in ErrorProp. Closure stages and non-final-
  segment turbofish remain not-yet-implemented with explicit errors.
- `impl Trait for Type` failed with "expected item": impl_block() never
  handled `for`. It now records an optional TraitRef and parses `where`
  clauses.
- `trait Convert<T>` and `trait Loggable: Printable` failed: trait_def()
  skipped straight from the name to the body. Generic params, supertrait
  bounds (parsed structurally, not stored), and `where` clauses now
  parse.
- `&dyn Iter<Item = i64>` failed: the dyn branch of ty() ignored
  type_args. Type::Dyn now carries a TraitRef (grammar's trait_ref =
  type_path [type_args]).

Grammar-correct behavior changes, regression-guarded by tests:
`x |> a + b` is now `(x |> a) + b` (a stage is only a callee), and
struct literals are no longer valid pipe stages.

Adds 15 unit tests (AST-shape assertions for every pipe edge case plus
impl/trait/dyn shapes), two corpus fixtures (traits_impls.sp, pipes.sp),
and updates the crates/AGENTS.md subset contract for the lines these
fixes change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H3CinyyqWL6SfCLrKGm3ja

* Add predicate to the pipe-stage not-yet-implemented list item

Cubic review on PR #70: the new list entry was the only clause in the
not-yet-implemented list without a verb. It now states what the parser
actually does — rejects both shapes with explicit not-yet-implemented
parse errors.
Send statements now require a method-call operand behind the section 2.7 statement-head rule, assignment left sides are validated against section 16 assign_target, and a missing bracket after vec! is a parse error instead of a silent fallback. Includes 7 unit tests and the send_assign.sp corpus fixture.
Empty char literals, bare 0x/0o/0b prefixes, integer suffixes on float literals, float suffixes on based literals, and separators touching non-digits of the literal's base are now lex errors, matching the documented section 16.1 constraints. Literal-overflow checking is documented as deferred to semantic analysis. Includes 5 lexer unit tests.
Chained ranges (a..b..c) are now a parse error per the precedence table's None associativity, with the diagnostic anchored to the second operator. Item modifiers are validated per section 16: offchain/async only on fn items, pub rejected on impl, actor, onchain, and extern items, with errors on the modifier's own span. Includes 4 unit tests with span assertions and the ranges_modifiers.sp corpus fixture.
@StreamDemon StreamDemon marked this pull request as ready for review July 2, 2026 07:57

@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 9 files (changes from recent commits).

Requires human review: This PR makes major changes to the parser and core language parsing rules. Although the AI found no issues, these high-impact changes could cause subtle regressions in compilation correctness.

Re-trigger cubic

@StreamDemon StreamDemon merged commit 9dedfe7 into main Jul 2, 2026
3 checks passed
@StreamDemon StreamDemon deleted the fix/parser-correctness-base branch July 2, 2026 08:21
StreamDemon added a commit that referenced this pull request Jul 2, 2026
Empty seed commit for the enhancement-wave base PR; the roadmap lives in
the PR description. Rebase this branch onto main after the parser
correctness wave (PR #69) merges, before the first enhancement sub-PR
lands.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H3CinyyqWL6SfCLrKGm3ja
StreamDemon added a commit that referenced this pull request Jul 2, 2026
Empty seed commit for the enhancement-wave base PR; the roadmap lives in
the PR description. Rebased onto main after the parser correctness wave
(PR #69) merged.
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.

1 participant