Repository navigation
01_tokenize: lex matchers as pattern data, dag_prepared_lex tier-served (stacked on #13287) - #13294
Conversation
…kenize prepare_lex_rules compiles the rule set (matchers, first-character dispatch, one dispatch per mode) and checks its mode declarations once into PreparedLexRules; tokenize_prepared reads it. tokenize(rules) stays the one-text door. The per-file folds (program assembly, closure ingest, reference conservation, the native front end) prepare once beside prepare_grammar and hand the prepared rules to program_assembly_phase_tokenize, instead of recompiling per file and relying on the interpreter's in-context call memo to dedupe it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…_lex served like dag_prepared_grammar lex_rule_thunk built one LexMatchThunk closure per pattern node, so a compiled rule set held closures, which the cross-claim tier refuses to publish: every claim recompiled the .dag rules. lex_match_pattern now reads the LexPattern data directly, arm for arm what each closure did, so CompiledLexRule carries the rule, its index and its FIRST set only and the prepared rule set is portable. dag_prepared_lex (beside dag_prepared_grammar) prepares it once and is enrolled warm in floor_pure_producer_share; the declaration-choice route claims read it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ed_lex The module's 15 claims each recompiled the .dag lex rules through tokenize(rules: dag_lex()); they now read the prepared rules served across claims. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Both conflicts were #13287's own changes, already on main: the generated v1_compiler_emit_rust.rs mirror and 05_emit_rust.dag now equal main's exactly, so #13294 no longer touches v1 and main's regen fixed point covers it; tokenize_prepared takes main's unicode_scalar_unfold ingress (#13151). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… hand warm row #13043 deleted the hand-maintained floor_cross_claim_pure_producers_warm roster: cross-claim sharing is now derived from planned claims' call-site demand. dag_prepared_lex is a nullary producer of a portable value demanded by many claims, so the derivation shares it; the row and its comment go. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…iew 76232) Structural questions about a pattern go through fold_lex_pattern; matching a pattern against input threads a cursor through its children, which a catamorphism can only produce as closures, and #13294 exists to keep compiled matchers as data. The departure and its reason are now stated at the rule in v2.std.compilers.lexing and at the walker; a new LexPattern variant refuses the walker's exhaustive match at compile time, so it cannot be skipped silently. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Re review 76232 ( Why not (a): What changed: the rule at — sent from stern-bear-500 |
Stacked on #13287, and the closure-free half of the program manager's ruling. The compiled lex rules become data, so the prepared rule set is portable and
dag_prepared_lexcan be served across claims likedag_prepared_grammar.The defect (DESIGN §6b reading)
v2.compiler.tokenizelex_rule_thunkfolded eachLexPatterninto a tree ofLexMatchThunk { apply: fn(LexCursor) -> … }closures, andCompiledLexRulestored that closure. The cross-claim tier refuses to publish a value that contains closures. The floor's cross-claim demand census showed the result:lex_compile_ruleswas evaluated once per claim (16 of 16 on #13279's run) and never served, so every claim that tokenized .dag text first recompiled the language's whole rule set.Fix, at the owning link. The matcher is the pattern, read:
lex_match_pattern(pattern, source)is one structural walk over theLexPatterndata. Each arm answers exactly what the corresponding closure answered: the consumed source as the lexeme, a keyword refused when an identifier character follows, a choice trying its left alternative first, a repeat stopping at a rejection or an empty match, and a delimited body running until its close matches.lex_repeat_stepandlex_delimited_steptake patterns instead of thunks.CompiledLexRulekeeps the rule, its index and its FIRST set;LexMatchThunkandlex_rule_thunkare deleted.v2.compiler.program_assemblygainsdag_prepared_lex()besidedag_prepared_grammar(), enrolled warm inv2.workflow.floor_pure_producer_sharewith its ledger reason.route_parse_at) read it throughtokenize_prepared.Controls
@); and two python functions. The printed values match: 14,494 bytes each, the same sha256.src/v2/test/claim/tokenize+src/v2/test/claim/parse: 389 pass / 7 fail. The seven are the same claims that fail on main; none is introduced here.Per-claim measurement on the floor
Base run 37216639425 (this PR before the helper switch) vs run 37219911955 (this head).
dag_prepared_lexlanded at warm preparation with disposition Stored (fill 54 ms, so the value is portable), but no claim read it yet. The cross-claim demand census still listedprepare_lex_ruleswithclaims=15 evals=15: all 15 claims intest.claim.parse_test_fn_decl_return_clauserecompiled the rules throughtokenize(rules: dag_lex()). This head: their helpernfbcp_parsedreadstokenize_prepared(dag_prepared_lex()). The fill row showsconsumer_claims=15, andprepare_lex_rulesno longer appears in the per-claim demand census.nfbcp_eq_body_specimen_parses_holdswent from 44,364 to 37,228,nfbcp_control_ordinary_fn_return_type_holdsfrom 51,802 to 44,663, andnfbcp_repeated_declaration_refuses_at_the_second_declaration_holdsfrom 66,882 to 59,737.Other
tokenize(rules: dag_lex())callers in claims can switch to the served value the same way; this PR switches the two helpers the floor plans.🤖 Generated with Claude Code