Skip to content

Portable emit targets (ts/go/rust) have no incremental edit — full re-parse only #57

Description

@johnsoncodehk

The target-agnostic emitter (#6, #56) emits portable parsers in TypeScript, Go, and Rust, but they are full-parse only — they expose tokenize(src) + parse(tokens) and have no incremental re-parse. Incremental edit exists only in the JS paths:

Path Incremental
createParser() interpreter .edit(...)
jsTarget (optimized JS emit) ✅ exported parseEdited (PR #38)
portable tsTarget / goTarget / rustTarget ❌ full parse(tokenize(src)) only

Why

The incremental machinery — watermarked memo carry, subtree reuse (adoptPath), and the maxPos watermark — lives in the optimized path (src/emit-parser.ts / src/gen-parser.ts), shipped as parseEdited in PR #38 and gated ≡ fresh (1.4–5.6×). The portable emitter (src/emit-portable.ts's buildIR) renders a different, simpler parser: a clean backtracking recursive-descent + Pratt core with no memo / no incremental infrastructure. So nothing in the portable IR or the target-*.ts renderers can carry a prior parse forward.

What it would take

  • Lift the memo-carry + watermark + subtree-reuse model into the language-agnostic IR layer so each Target can render it.
  • Per-target incremental state: ts via module globals; go/rust need incremental arena reclamation (reusing surviving subtrees without leaking the flat nodes/kids slices).
  • Extend test/portable-targets.ts to assert edit ≡ fresh for the portable targets, mirroring the existing JS incremental gate.

Substantial — not a single-construct change. Tracking it as a known boundary of the portable emitter; the JS interpreter / jsTarget remain the path for incremental use until then.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions