Skip to content

Fix ::identifier bareword parsing and jcpan cpan script#322

Merged
fglock merged 5 commits into
masterfrom
fix/mo-bareword-parsing
Mar 16, 2026
Merged

Fix ::identifier bareword parsing and jcpan cpan script#322
fglock merged 5 commits into
masterfrom
fix/mo-bareword-parsing

Conversation

@fglock
Copy link
Copy Markdown
Owner

@fglock fglock commented Mar 16, 2026

Summary

Two fixes for Mo module support and jcpan functionality:

1. Parser fix for ::identifier barewords

In Perl, ::foo without parentheses is a bareword that stringifies to '::foo', while ::foo() with parens is a function call to main::foo. PerlOnJava was incorrectly treating all ::identifier patterns as main::identifier.

This broke the Mo module which uses patterns like $M.$_.::e to dynamically build package names.

Before:

./jperl -e 'my $M = "Mo::"; $_ = "build"; print $M.$_.::e'
Mo::buildmain::e  # WRONG - main:: inserted

After:

./jperl -e 'my $M = "Mo::"; $_ = "build"; print $M.$_.::e'
Mo::build::e  # CORRECT - bareword stringified

2. Added cpan script to sync config

The jcpan wrapper requires src/main/perl/bin/cpan to exist. Added import from perl5/cpan/CPAN/scripts/cpan to config.yaml so fresh checkouts work correctly.

Test Results

Mo module tests:

  • Before: 14/28 test programs failing, only 10 subtests ran
  • After: 6/28 test programs failing, 133/144 subtests passing (93%)

Unit tests: All passing

Test Plan

  • Unit tests pass (make)
  • ./jperl -e 'print $x.::e' outputs ::e (bareword)
  • ./jperl -e 'sub foo {"X"} print ::foo()' outputs X (function call)
  • ./jcpan --help works
  • Mo module tests significantly improved

Generated with Devin

fglock and others added 5 commits March 16, 2026 10:29
Two fixes:

1. Parser fix for ::identifier barewords (ParsePrimary.java):
   - In Perl, `::foo` without parens is a bareword string '::foo'
   - Only `::foo()` with parens is a function call to main::foo
   - PerlOnJava was incorrectly treating all `::identifier` as main::identifier
   - This broke Mo module which uses patterns like `$M.$_.::e`
   - Now: `::foo()` -> main::foo(), `::foo` -> '::foo' string

2. Added cpan script to sync config (config.yaml):
   - The jcpan wrapper requires src/main/perl/bin/cpan
   - Added import from perl5/cpan/CPAN/scripts/cpan
   - Fixes 'Unable to read file' error on fresh checkouts

Mo test improvement: 14/28 failing -> 6/28 failing (133/144 subtests pass)

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <noreply@cognition.ai>
- Added src/main/perl/bin/cpan to git (required by jcpan)
- Updated .gitignore to allow src/main/perl/bin/ directory

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <noreply@cognition.ai>
The hash was being cleared before iterating over the RHS list.
For self-referential assignments like `%h = (new_stuff, %h)`,
this caused the hash contents to be lost.

Fix: Materialize the entire RHS list into a temporary array before
clearing the hash, similar to how tied hashes are handled.

This fixes Mo module BUILD support - Mo uses:
  %e = (extends => sub{...}, has => sub{...}, %e)
to merge feature-provided exports with defaults.

Mo test improvement: 6/28 failing -> 1/28 failing (143/144 subtests pass)

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <noreply@cognition.ai>
The previous fix always treated `::foo` (without parens) as a bareword string.
But in Perl, `::foo` without parens calls `main::foo` if the sub exists at
compile time, and only becomes a bareword string if no such sub exists.

Now checks GlobalVariable.getGlobalCodeRef(fullSubName).getDefinedBoolean()
to determine if the sub exists, matching Perl's behavior.

This fixes tests that use `::is ::exception { }` patterns where `is` and
`exception` are imported subs that should be called.

Mo still works: `$M.$_.::e` correctly produces '::e' bareword because
no `main::e` sub exists at that point.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <noreply@cognition.ai>
- Phase 24: Fix ::identifier bareword parsing
- Phase 25: Fix self-referential hash assignment

Mo: 27/28 passing (99.3%)
Moo: 62/71 passing (87%), 768/829 subtests (93%)

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <noreply@cognition.ai>
@fglock fglock merged commit 892ae94 into master Mar 16, 2026
2 checks passed
@fglock fglock deleted the fix/mo-bareword-parsing branch March 16, 2026 09:51
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.

1 participant