Skip to content

fix: parse $$$a as chained dereferences, not $$ magic + $a - #428

Draft
toddr-bot wants to merge 2 commits into
masterfrom
koan.toddr.bot/fix-issue-60
Draft

fix: parse $$$a as chained dereferences, not $$ magic + $a#428
toddr-bot wants to merge 2 commits into
masterfrom
koan.toddr.bot/fix-issue-60

Conversation

@toddr-bot

@toddr-bot toddr-bot commented Apr 27, 2026

Copy link
Copy Markdown
Collaborator

Summary

$$$a was incorrectly parsed as $$ (Magic PID variable) + $a (Symbol), but Perl treats it as ${${$a}} — two scalar dereferences. The fix adds a lookahead in Token::Unknown when tentatively classifying $$ as Magic: if the next character is $ followed by a word character or another $, the first $ is finalized as a Cast (dereference) instead.

Fixes #60

Changes

  • Added lookahead in Unknown.pm's $ handler: when $$ would be Magic but is followed by $\w or $$$, emit the first $ as Cast and re-enter tokenization for the rest
  • Added regression test 52_triple_dollar_deref (code/dump pair)
  • Added explicit Cast/Symbol assertions in ppi_token_magic.t
  • Updated test plan counts in 08_regression.t and 25_increment.t

Test plan

  • Regression test verifies $$$a = 3; produces Cast($) + Cast($) + Symbol($a)
  • Unit test in ppi_token_magic.t verifies Cast count and Symbol content for $$$a
  • Full test suite (69 files, 53172 tests) passes with no regressions
  • Existing $$foo, $$, $${^MATCH} cases continue to work correctly

Generated by Kōan /fix


Quality Report

Changes: 6 files changed, 35 insertions(+), 3 deletions(-)

Code scan: clean

Tests: skipped

Branch hygiene: clean

Generated by Kōan post-mission quality pipeline

toddr-bot and others added 2 commits April 27, 2026 07:24
$$$a should be parsed as Cast($) + Cast($) + Symbol($a) representing
two scalar dereferences, but PPI currently produces Magic($$) + Symbol($a).

Add a regression test code/dump pair and TODO tests in ppi_token_magic.t
that demonstrate the expected tokenization.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When the tokenizer sees $$, it checks if the character after forms a
magic variable. For $$, since $$ is in %MAGIC, it was always classified
as Magic. But $$$a should be Cast($) + Cast($) + Symbol($a) — two
scalar dereferences.

The fix adds a lookahead in Unknown.pm: when $$ is tentatively Magic
and the character after is $ followed by a word char or another $,
the first $ is instead finalized as a Cast. The second $ then
re-enters Unknown resolution and the process recurses correctly
for any depth of chained dereferences.

This also improves $$0, $$1 etc. which now correctly produce
Cast($) + Magic($0) instead of Cast($) + Symbol($0).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.

RT 37352: $$$a parsed $$ magic plus $a

1 participant