Parse six high-impact real-world Ruby front-end constructs (Round 1) - #3
Merged
Conversation
Round 1 of the parse-conformance push toward 100% on real Ruby apps
(Rails/Puppet/stdlib/RuboCop/Chef). Each construct is verified valid
against MRI (ruby -c) and covered by MRI-parity table tests.
1. masgn to non-local targets (the biggest gap): the multiple-assignment
LHS parser now accepts instance/class/global variables, constants,
scoped constants, attribute targets (obj.x), and index targets
(arr[i]), with splats on any of them and a nameless `*`/trailing `,`.
Non-local targets populate MultiAssign.Targets (attribute/index
targets lower to their setter-call shape: x= / []=); the all-locals
fast path keeps Targets nil. A general bracket-aware lookahead
(scanMlhsTargetTail/scanBalanced) drives the disambiguation.
2. rescue/else/ensure without an explicit begin on do...end blocks and
class/module/singleton-class bodies (def bodies already supported),
folded into a Begin via the shared parseRescueTail. Brace blocks
still reject it, as MRI does.
3. Anonymous and ordered parameters: bare `*`, `**`, `&` in def and
lambda parameter lists (recorded with sentinel names *, **, &), and
kwargs / double-splat followed by a &block param (the **opts, &block
ordering that previously failed). `**nil` is recorded too.
4. Special global variables in the lexer ($$ $! $@ $/ $\ $; $, $. $< $>
$? $* $" $: $+ and the like), including inside string interpolation
("PID-#{$$}"); previously lexed as ILLEGAL.
5. Value-omitted shorthand keyword arguments (Ruby 3.4) in calls, super,
and array literals: foo(format:, name:) == foo(format: format,
name: name). Array literals now share the call-argument grammar so
trailing key: value pairs collapse into one implicit hash, and a
trailing comma is accepted in both calls and arrays.
6. Single-quoted symbols :'foo.bar' / :'data-remote' (no interpolation,
honoring \' and \\), alongside the existing :"..." form.
Rails parse-acceptance sweep: 21.12% -> 83.09% (723 -> 2844 / 3423
files), zero regressions. 100% coverage retained; gofmt + go vet clean;
CGO=0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Round 1 of the parse-conformance push toward 100% on real Ruby apps (Rails / Puppet / stdlib / RuboCop / Chef). Six high-impact front-end constructs, each verified valid against MRI 4.0 (
ruby -c) and covered by MRI-parity table tests.Rails parse-acceptance sweep: 21.12% → 83.09% (723 → 2844 of 3423
.rbfiles), zero regressions (every file that parsed before still parses).Constructs landed
masgn to non-local targets (the single biggest gap, ~1692 occurrences). The multiple-assignment LHS parser now accepts instance/class/global variables, constants, scoped constants, attribute targets (
obj.x), and index targets (arr[i]), with splats on any of them plus nameless*and trailing,. Non-local targets populateMultiAssign.Targets; attribute/index targets lower to their setter-call shape (x=/[]=). The all-locals fast path keepsTargetsnil so existing consumers are untouched. A bracket-aware lookahead (scanMlhsTargetTail/scanBalanced) drives the disambiguation.@a, @b, @c = x, y, z·@@a, @@b = …·$a, $b = …·obj.x, obj.y = …·arr[i], h[k] = …·@a, *@b = …·*@a, @b = …rescue/else/ensurewithout an explicitbeginondo…endblocks and class/module/singleton-class bodies (def bodies were already supported), folded into aBeginvia the sharedparseRescueTail. Brace blocks still reject it, as MRI does.Anonymous + ordered params: bare
*,**,&indefand lambda parameter lists (sentinel names*/**/&), and kwargs / double-splat followed by a&blockparam (def f(**options, &block),def f(*args, **opts, &block)).**nilis recorded too.Special global variables in the lexer (
$$ $! $@ $/ $\ $; $, $. $< $> $? $* $" $: $+…), including inside string interpolation ("PID-#{$$}"); previously lexed asILLEGAL.Value-omitted shorthand keyword arguments (Ruby 3.4) in calls,
super, and array literals:foo(format:, name:)⇒foo(format: format, name: name). Array literals now share the call-argument grammar, so trailingkey: valuepairs collapse into one implicit hash and a trailing comma is accepted in both calls and arrays.Single-quoted symbols
:'foo.bar'/:'data-remote'(no interpolation, honoring\'and\\), alongside the existing:"…"form.Quality
go test -racegreen; gofmt +go vetclean; CGO=0.masgn_targets_test.go,round1_features_test.go,lexer/lexer_round1_test.go.Downstream (rbgo) follow-ups
These constructs now parse; some need a matching rbgo compiler case to execute (out of scope here — no rbgo changes in this PR):
compiler.storeMultiTargetonly handlesVarRef/ConstRef. Add cases forIvarRef,CVarRef,GVarRef,ScopedConst, and attribute/index setterCalltargets; and guard a nilTargets[i](nameless*splat).*/**/&compile as ordinary local slots; forwarding them as call arguments needs compiler support.Begin/HashLit/SymbolLitlowering — no new compiler cases expected.🤖 Generated with Claude Code