Skip to content

Disambiguate qualified range endpoints from loop bodies #157

Closed

Description

@itsfuad

Problem

While validating qualified constant folding for #154/#155, valid range headers ending in an imported constant were parsed as enum payloads. This is independent of constant evaluation and was reproduced before the evaluator change on Linux/386 and amd64.

// src/values.peep
const Zero: i64 = 0i64;
const One: i64 = 1i64;
// src/main.peep in project app
import "app/values";
fn Read() -> i64 {
    for value in values::Zero..values::One {
        return value;
    }
}

Observed on baseline: P0003 enum variant payload requires 'with', P0002 recovery errors, missing range-end/body evidence, and downstream missing-return error. Expected: endpoints remain bound qualified value expressions; the brace opens the loop body.

Control: values::Zero..(values::One as i64) parses correctly. With qualified constant folding repaired, ascending ranges gain guaranteed-entry evidence; equal/reversed/runtime ranges retain missing-return behavior. The explicit cast in the prior regression isolated evaluator behavior; it was not a production parser workaround.

Owners and implementation scope

  • internal/frontend/parser/parse_stmt.go: parseForStmt owns the range/body boundary.
  • internal/frontend/parser/parse_expr.go: index/range and Pratt expression parsing retain qualified endpoints and explicitly introduced literals.
  • internal/frontend/parser/recover_literal.go: shared nesting-aware recovery for missing literal introducers; local caller delimiters protect headers, arguments, and following syntax.
  • Resolver/typechecker preserve parser-owned error nodes without redundant syntax diagnostics and record invalid type evidence.

Current grammar uses Enum::Variant with payload, Type.{...}, and .{...}. Peeper is pre-stable: preserve rejection and useful recovery for unsupported syntax, not migration-only parsing or compatibility state. A qualified path is not assumed to denote an enum. Two adjacent blocks alone cannot establish malformed literal intent.

Acceptance criteria

  • Parse bare qualified range endpoints without consuming the loop-body brace.
  • Cover ascending/equal/reversed/runtime headers; retain endpoint bindings, imported ownership, source locations, and downstream entry/lowering evidence on 386/amd64.
  • Preserve explicit enum/struct construction and valid qualified control headers followed by standalone blocks.
  • Keep unsupported literal forms rejected with targeted diagnostics; retain enclosing delimiters, following valid syntax, and independent later errors.
  • Only mention type arguments when parsed syntax evidence establishes them; do not infer enum or generic declaration identity in the parser.
  • Add focused parser/semantic/pipeline tests and positive/applicable negative x_test/ fixtures; validate with the rebuilt bundled compiler.

Delivered

Merged into main through #159 on 2026-10-07 at 29eac4d7de54cb82babf880ea26cf876ba6b1d92. GitHub automatically closed this issue on merge.

Numeric publication, foreign constant ownership, bounds checking, and shared evaluator repair remain in #154/#155.

Related follow-up: #134, a standalone LSP completion feature for current syntax. Assigned milestone: 0.2 Language Foundations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions