@@ -36,8 +36,29 @@ private static RuntimeBase doFile(RuntimeScalar runtimeScalar, boolean setINC, b
3636 String code = null ;
3737 String actualFileName = null ;
3838
39+ // Check if the argument is an ARRAY reference (for @INC filter with state support)
40+ if (runtimeScalar .type == RuntimeScalarType .REFERENCE &&
41+ runtimeScalar .value instanceof RuntimeArray ) {
42+ // `do` ARRAY reference - array should contain [coderef, state...]
43+ RuntimeArray arr = (RuntimeArray ) runtimeScalar .value ;
44+ if (arr .size () > 0 ) {
45+ RuntimeScalar firstElem = arr .get (0 );
46+ // The first element should be a CODE ref or filehandle
47+ if (firstElem .type == RuntimeScalarType .CODE ||
48+ (firstElem .type == RuntimeScalarType .REFERENCE &&
49+ firstElem .scalarDeref () != null &&
50+ firstElem .scalarDeref ().type == RuntimeScalarType .CODE ) ||
51+ firstElem .type == RuntimeScalarType .GLOB ||
52+ firstElem .type == RuntimeScalarType .GLOBREFERENCE ) {
53+ // Recursively handle the first element
54+ // Pass remaining array elements as potential state
55+ RuntimeBase result = doFile (firstElem , setINC , isRequire , ctx );
56+ return result ;
57+ }
58+ }
59+ }
3960 // Check if the argument is a CODE reference (for @INC filter support)
40- if (runtimeScalar .type == RuntimeScalarType .CODE ||
61+ else if (runtimeScalar .type == RuntimeScalarType .CODE ||
4162 (runtimeScalar .type == RuntimeScalarType .REFERENCE &&
4263 runtimeScalar .scalarDeref () != null &&
4364 runtimeScalar .scalarDeref ().type == RuntimeScalarType .CODE )) {
@@ -66,20 +87,36 @@ private static RuntimeBase doFile(RuntimeScalar runtimeScalar, boolean setINC, b
6687 } else {
6788 // Save current $_
6889 RuntimeScalar savedDefaultVar = GlobalVariable .getGlobalVariable ("main::_" );
69- GlobalVariable . getGlobalVariable ( "main::_" ). set ( "" );
90+ StringBuilder accumulatedCode = new StringBuilder ( );
7091
7192 try {
72- // Call the CODE reference with no arguments
93+ // Call the CODE reference repeatedly as a generator
94+ // Each call should populate $_ with the next chunk of code
95+ // Continue until it returns 0/false (EOF)
7396 RuntimeArray args = new RuntimeArray ();
74- RuntimeBase result = codeRef .apply (args , RuntimeContextType .SCALAR );
75-
76- // Get the content from $_
77- RuntimeScalar defaultVar = GlobalVariable .getGlobalVariable ("main::_" );
78- code = defaultVar .toString ();
79-
80- // Return value of 0 means EOF (no MORE content after this call)
81- // But the content in $_ is still valid and should be used!
82- // Only set code to null if $_ is actually empty
97+ boolean continueReading = true ;
98+
99+ while (continueReading ) {
100+ GlobalVariable .getGlobalVariable ("main::_" ).set ("" );
101+
102+ // Call the CODE reference
103+ RuntimeBase result = codeRef .apply (args , RuntimeContextType .SCALAR );
104+
105+ // Get the content from $_
106+ RuntimeScalar defaultVar = GlobalVariable .getGlobalVariable ("main::_" );
107+ String chunk = defaultVar .toString ();
108+
109+ // Accumulate the chunk if not empty
110+ if (!chunk .isEmpty ()) {
111+ accumulatedCode .append (chunk );
112+ }
113+
114+ // Check if we should continue
115+ // Return value of 0/false means EOF
116+ continueReading = result .scalar ().getBoolean ();
117+ }
118+
119+ code = accumulatedCode .toString ();
83120 if (code .isEmpty ()) {
84121 code = null ;
85122 }
0 commit comments