fix: Type::Tiny Phase 6 — tie infrastructure, lexical sub parsing, splice context#481
Merged
fix: Type::Tiny Phase 6 — tie infrastructure, lexical sub parsing, splice context#481
Conversation
Two fixes for Type::Tiny test improvements: 1. splice replacement values now evaluated in LIST context in interpreter backend. Previously, function calls in splice replacement positions got scalar context, causing only one value to be inserted instead of the full list. (fixes Type-Tie/01basic.t splice tests) 2. Lexical subs (my sub) now recognized as function calls before statement modifier keywords (if/unless/while/until/for/foreach/when). Previously, `quuux if 1` with a lexical sub treated `quuux` as a bareword because the parser's indirect method call heuristic saw `if` as an identifier. (fixes Eval-TypeTiny/lexical-subs.t test 6) Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Two fixes that unblock tie-based aliasing in Eval::TypeTiny: 1. Backslash prototype \[$@%*] now correctly handles my(@arr) and my(%hash) parenthesized declarations. Previously, the extra ListNode wrapper from parentheses caused tie() to see an unsupported variable type instead of an array/hash reference. Added unwrapMyListDeclaration helper in PrototypeArgs.java. 2. materializeSpecialVarsInResult now handles tied arrays and hashes. Previously, it iterated arr.elements directly (the empty ArrayList backing TieArray), bypassing FETCHSIZE/FETCH. Now dispatches through getList() for tied containers, which correctly calls tie methods. Test improvements: - aliases-tie.t: 6/11 -> 10/11 (remaining 1 is DESTROY) - Type-Tie/basic.t: 1/2 -> 3/3 - Type-Tie/01basic.t: already 17/17 Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Phase 6 improvements: - Splice list context in interpreter backend - Lexical sub + statement modifier parsing - tie(my(@arr),...) backslash prototype parsing - return @tied_array in eval STRING context - materializeSpecialVarsInResult tied array/hash support Test results: 3029/3038 tests passing (99.7%), 5 files with real failures (all due to DESTROY/B::Deparse/Clone limitations, not runtime bugs) Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
All sprintf/printf warnings (Invalid conversion, Missing argument,
Redundant argument) were unconditionally emitted via WarnDie.warn().
Changed to WarnDie.warnWithCategory() with the printf category,
matching Perl 5 behavior where these warnings only fire under
use warnings or use warnings printf.
Also updated type_tiny.md with analysis of remaining jcpan issues:
- builtin::export_lexically: 2 tests (PerlOnJava reports 5.042)
- Math::BigFloat: 1 test (core module not bundled)
- sprintf %{ warning: cosmetic, now properly gated
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Three related fixes for `local` variable restoration:
1. JVM backend (EmitStatement.java): Add Local.localSetup/localTeardown
wrapping For3Node (while/for loops) so `last` exits that jump past the
body block's own cleanup still restore `local` variables.
2. JVM backend (EmitControlFlow.java): Route non-local last/next/redo
through returnLabel instead of using direct ARETURN. This ensures
the subroutine's localTeardown (popToLocalLevel) runs when `last LABEL`
crosses subroutine boundaries (e.g. `sub skip { local $^W=0; last SKIP }`).
3. Bytecode interpreter (BytecodeCompiler.java): Add GET_LOCAL_LEVEL /
POP_LOCAL_LEVEL wrapping For3Node for both bare blocks and while/for
loops, matching the JVM backend fix.
Also fixes:
- Remove debug trace from WarnDie.java
- Fix spurious "Argument isn't numeric" warning in SprintfOperator when
checking for Inf/NaN on invalid format specifiers with string arguments.
Test impact: op/sprintf2.t recovers 1 test (1651->1652), restoring the
pre-regression baseline.
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
e9d1d9c to
3c034f9
Compare
Phase 7 of Type::Tiny support: Clone/Storable tie preservation.
- Replace custom Clone::PP (77 lines) with CPAN Clone::PP 1.08
which supports tied variables, clone_self/clone_init hooks,
depth limiting, and circular reference detection.
- Create Java-based Clone module (Clone.java) as XS replacement
that properly deep-clones tied hashes, arrays, and scalars by
cloning the tie handler and re-tying the clone.
- Fix Storable::dclone to handle tied variables:
- Detect TieHash/TieArray/TieScalar in deepClone()
- Deep-clone the handler and copy data via FETCH/STORE
- Add TIED_SCALAR case for tied scalar elements
- Fix STORABLE_freeze/thaw to create correct ref type
(ARRAY vs HASH) for the thaw object
- Add bundled tests:
- Clone-PP: 7 tests from CPAN Clone::PP 1.08
- Type-Tie: 9 tests from Type-Tiny 2.010001
Test impact: Type-Tie/06clone.t 3/6 → 6/6,
Type-Tie/06storable.t 3/6 → 6/6
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
ba65237 to
4ccba36
Compare
…slash
In Perl, \$hash{key} auto-vivifies the hash entry so that subsequent
\$hash{key} references point to the same scalar slot. PerlOnJava was
returning references to temporary proxy objects instead, causing each
\$hash{key} to create a different reference.
Fix by overriding createReference() in RuntimeBaseProxy to vivify the
entry first and return a reference to the actual lvalue. Also override
in RuntimeScalarReadOnly to avoid triggering the read-only vivify()
which would throw.
This fixes Clone-PP/t/dclone.t test 7 and improves reference identity
semantics for hash and array element references.
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ct syntax Two fixes: 1. The .= operator was incorrectly dropping the UTF-8 flag when the target was a BYTE_STRING. The setPreservingByteString logic (JVM backend) and executeStringConcatAssign (interpreter backend) would downgrade STRING back to BYTE_STRING whenever the result fit in Latin-1, even when the RHS was UTF-8. Now we only preserve BYTE_STRING when the concat result itself is BYTE_STRING (meaning both operands were non-UTF-8). This fixes all 27 utf8_handling.t tests for XML::Parser. 2. LWPExternEnt.pl used indirect object syntax (new LWP::UserAgent()) which was misinterpreted as a function call since XML::Parser has its own sub new. Changed to direct method syntax (LWP::UserAgent->new()). This fixes external_ent.t and parament.t for XML::Parser. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
When the current package defines a subroutine (e.g., sub new in XML::Parser), new LWP::UserAgent() was incorrectly parsed as new(LWP::UserAgent()) instead of LWP::UserAgent->new(). The parser rejection rule for indirect object syntax with qualified names (::) was too aggressive - it rejected ALL qualified names when the calling sub existed, regardless of whether the name was a known package. Now it only rejects when the qualified name is NOT a known package (isPackage != true), preserving correct behavior for: - new LWP::UserAgent() -> indirect object (package is known) - is MojoMonkeyTest::bar() -> function call (sub is known) Also reverts the LWPExternEnt.pl workaround from the previous commit, since the parser now handles the original indirect object syntax correctly. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…vification Move the createReference override from RuntimeBaseProxy (which affected all proxy types including substr, vec, and tied lvalues) to only RuntimeHashProxyEntry and RuntimeArrayProxyEntry where auto-vivification on backslash-ref is actually needed. The array proxy version safely checks for existing elements before vivifying, to avoid overwriting tied or special elements that may already exist at that index. Also fix autovivification of tied scalars: when a tied scalar is array/hash-dereferenced and FETCH returns undef, the auto-vivified reference is now STOREd back to the tied variable (matching Perl behavior). Previously the auto-vivified value was stored in a temporary and lost. This fixes all 6 test regressions from the original createReference commit, and improves gmagic.t from 31/42 to 42/56 (+11 tests). Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The split function was creating results with STRING type (UTF-8 flagged) for all inputs because new RuntimeScalar(String) always sets STRING type. The fixup code only converted results to BYTE_STRING when the input was explicitly BYTE_STRING, but missed INTEGER, DOUBLE, UNDEF, etc. Changed the condition from checking type == BYTE_STRING to type != STRING so that split results are only UTF-8 flagged when the input string itself was UTF-8 flagged. This matches Perl behavior. This fixes ExifTool PNG.t test 3 where WriteInfo to a scalar reference produced UTF-8 flagged binary data (via split in ConvInv propagating UTF-8 flag from integer 8), causing Unknown file type on read-back. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.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
Phase 6 of Type::Tiny support, improving the pass rate from 99.0% to 99.7% (3029/3038 individual tests).
Fixes
my sub name) now recognized as function calls before statement modifier keywords (if/unless/while/until/for/foreach/when). Previouslyquuux if 1with a lexical sub treatedquuuxas a bareword.tie(my(@arr), ...)backslash prototype parsing: The\[$@%*]prototype now correctly handles parenthesizedmydeclarations. AddedunwrapMyListDeclaration()helper to unwrap the extra ListNode frommy(@bar).return @tied_arrayin eval STRING:materializeSpecialVarsInResultwas iteratingarr.elementsdirectly (the empty ArrayList backing TieArray), bypassing FETCHSIZE/FETCH. Now dispatches throughgetList()for tied arrays and hashes.Test improvements
Eval-TypeTiny/lexical-subs.tEval-TypeTiny/aliases-tie.tType-Tie/basic.tType-Tie/01basic.tTypes-Standard/tied.tType-Library/exportables.tType-Library/exportables-duplicated.tType-Tiny-Enum/basic.tMoo/basic.tMoo/coercion.tMoo/exceptions.tMoo/inflation.tMoo/coercion-inlining-avoidance.tRemaining 5 failing test files (all known limitations)
Error-TypeTiny-Assertion/basic.t(28/29): B::Deparse outputEval-TypeTiny/basic.t(11/12): DESTROY not implementedEval-TypeTiny/aliases-tie.t(10/11): DESTROY not implementedType-Tie/06clone.t(3/6): Clone doesn't preserve tie magicType-Tie/06storable.t(3/6): Storable doesn't preserve tie magicTest plan
makepasses (all unit tests)Generated with Devin