Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 100 additions & 52 deletions dev/modules/dbix_class.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -4659,6 +4659,10 @@ private void visitNamedSubroutine(SubroutineNode node) {
subCompiler.currentSubroutineBeginId = beginId;
subCompiler.currentSubroutineClosureVars = new HashSet<>(closureVarNames);

// Subroutine bodies should use RUNTIME context so the calling context
// (VOID/SCALAR/LIST) propagates correctly at runtime via register 2 (wantarray).
subCompiler.currentCallContext = RuntimeContextType.RUNTIME;

// Step 4: Compile the subroutine body
// Sub-compiler will use RETRIEVE_BEGIN opcodes for closure variables
InterpretedCode subCode = subCompiler.compile(node.block);
Expand Down Expand Up @@ -4761,6 +4765,12 @@ private void visitAnonymousSubroutine(SubroutineNode node) {
subCompiler.isInDeferBlock = true;
}

// Subroutine bodies should use RUNTIME context so the calling context
// (VOID/SCALAR/LIST) propagates correctly at runtime via register 2 (wantarray).
// Without this, the default LIST context is baked into all opcodes,
// causing incorrect behavior when the sub is called in VOID or SCALAR context.
subCompiler.currentCallContext = RuntimeContextType.RUNTIME;

// Step 4: Compile the subroutine body
// Sub-compiler will use parentRegistry to resolve captured variables
InterpretedCode subCode = subCompiler.compile(node.block);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,15 @@ public static RuntimeList execute(InterpretedCode code, RuntimeArray args, int c
int argsReg = bytecode[pc++];
int context = bytecode[pc++];

// Resolve RUNTIME context from register 2 (wantarray).
// When a subroutine body is compiled by the interpreter,
// the calling context is not known at compile time, so
// RUNTIME is baked into the bytecode. At execution time,
// resolve it from the actual calling context in register 2.
if (context == RuntimeContextType.RUNTIME) {
context = ((RuntimeScalar) registers[2]).getInt();
}

// Auto-convert coderef to scalar if needed
RuntimeBase codeRefBase = registers[coderefReg];
RuntimeScalar codeRef = (codeRefBase instanceof RuntimeScalar)
Expand Down Expand Up @@ -998,6 +1007,11 @@ public static RuntimeList execute(InterpretedCode code, RuntimeArray args, int c
int argsReg = bytecode[pc++];
int context = bytecode[pc++];

// Resolve RUNTIME context from register 2 (wantarray)
if (context == RuntimeContextType.RUNTIME) {
context = ((RuntimeScalar) registers[2]).getInt();
}

RuntimeScalar invocant = (RuntimeScalar) registers[invocantReg];
RuntimeScalar method = (RuntimeScalar) registers[methodReg];
RuntimeScalar currentSub = (RuntimeScalar) registers[currentSubReg];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -943,6 +943,8 @@ public static int executeMap(int[] bytecode, int pc, RuntimeBase[] registers) {
int closureReg = bytecode[pc++];
int ctx = bytecode[pc++];

if (ctx == RuntimeContextType.RUNTIME) ctx = ((RuntimeScalar) registers[2]).getInt();

RuntimeBase listBase = registers[listReg];
RuntimeList list = listBase.getList();
RuntimeScalar closure = (RuntimeScalar) registers[closureReg];
Expand All @@ -961,6 +963,8 @@ public static int executeGrep(int[] bytecode, int pc, RuntimeBase[] registers) {
int closureReg = bytecode[pc++];
int ctx = bytecode[pc++];

if (ctx == RuntimeContextType.RUNTIME) ctx = ((RuntimeScalar) registers[2]).getInt();

RuntimeBase listBase = registers[listReg];
RuntimeList list = listBase.getList();
RuntimeScalar closure = (RuntimeScalar) registers[closureReg];
Expand Down Expand Up @@ -1250,6 +1254,8 @@ public static int executeTie(int[] bytecode, int pc, RuntimeBase[] registers) {
int rd = bytecode[pc++];
int argsReg = bytecode[pc++];
int ctx = bytecode[pc++];

if (ctx == RuntimeContextType.RUNTIME) ctx = ((RuntimeScalar) registers[2]).getInt();
RuntimeList tieArgs = (RuntimeList) registers[argsReg];
registers[rd] = TieOperators.tie(ctx, tieArgs.elements.toArray(new RuntimeBase[0]));
return pc;
Expand All @@ -1259,6 +1265,8 @@ public static int executeUntie(int[] bytecode, int pc, RuntimeBase[] registers)
int rd = bytecode[pc++];
int argsReg = bytecode[pc++];
int ctx = bytecode[pc++];

if (ctx == RuntimeContextType.RUNTIME) ctx = ((RuntimeScalar) registers[2]).getInt();
RuntimeList untieArgs = (RuntimeList) registers[argsReg];
registers[rd] = TieOperators.untie(ctx, untieArgs.elements.toArray(new RuntimeBase[0]));
return pc;
Expand All @@ -1268,6 +1276,8 @@ public static int executeTied(int[] bytecode, int pc, RuntimeBase[] registers) {
int rd = bytecode[pc++];
int argsReg = bytecode[pc++];
int ctx = bytecode[pc++];

if (ctx == RuntimeContextType.RUNTIME) ctx = ((RuntimeScalar) registers[2]).getInt();
RuntimeList tiedArgs = (RuntimeList) registers[argsReg];
registers[rd] = TieOperators.tied(ctx, tiedArgs.elements.toArray(new RuntimeBase[0]));
return pc;
Expand Down Expand Up @@ -1337,6 +1347,8 @@ public static int executeDoFile(int[] bytecode, int pc, RuntimeBase[] registers)
int rd = bytecode[pc++];
int fileReg = bytecode[pc++];
int ctx = bytecode[pc++];

if (ctx == RuntimeContextType.RUNTIME) ctx = ((RuntimeScalar) registers[2]).getInt();
RuntimeScalar file = registers[fileReg].scalar();
registers[rd] = ModuleOperators.doFile(file, ctx);
return pc;
Expand All @@ -1354,6 +1366,8 @@ public static int executeGlobOp(int[] bytecode, int pc, RuntimeBase[] registers)
int globId = bytecode[pc++];
int patternReg = bytecode[pc++];
int ctx = bytecode[pc++];

if (ctx == RuntimeContextType.RUNTIME) ctx = ((RuntimeScalar) registers[2]).getInt();
registers[rd] = ScalarGlobOperator.evaluate(globId, (RuntimeScalar) registers[patternReg], ctx);
return pc;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public static int execute(int opcode, int[] bytecode, int pc, RuntimeBase[] regi
int argsReg = bytecode[pc++];
int ctx = bytecode[pc++];

if (ctx == RuntimeContextType.RUNTIME) ctx = ((RuntimeScalar) registers[2]).getInt();

// EACH receives the container directly (RuntimeHash or RuntimeArray), not a RuntimeList
if (opcode == Opcodes.EACH) {
registers[rd] = registers[argsReg].each(ctx);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ public static int executeSubstrVar(int[] bytecode, int pc, RuntimeBase[] registe
int argsListReg = bytecode[pc++];
int ctx = bytecode[pc++];

if (ctx == RuntimeContextType.RUNTIME) ctx = ((RuntimeScalar) registers[2]).getInt();

RuntimeList argsList = (RuntimeList) registers[argsListReg];
RuntimeBase[] substrArgs = argsList.elements.toArray(new RuntimeBase[0]);

Expand All @@ -114,6 +116,8 @@ public static int executeSubstrVarNoWarn(int[] bytecode, int pc, RuntimeBase[] r
int argsListReg = bytecode[pc++];
int ctx = bytecode[pc++];

if (ctx == RuntimeContextType.RUNTIME) ctx = ((RuntimeScalar) registers[2]).getInt();

RuntimeList argsList = (RuntimeList) registers[argsListReg];
RuntimeBase[] substrArgs = argsList.elements.toArray(new RuntimeBase[0]);

Expand Down Expand Up @@ -536,6 +540,8 @@ public static int executeStat(int[] bytecode, int pc, RuntimeBase[] registers) {
int rd = bytecode[pc++];
int rs = bytecode[pc++];
int ctx = bytecode[pc++];

if (ctx == RuntimeContextType.RUNTIME) ctx = ((RuntimeScalar) registers[2]).getInt();
registers[rd] = Stat.stat((RuntimeScalar) registers[rs], ctx);
return pc;
}
Expand All @@ -548,20 +554,26 @@ public static int executeLstat(int[] bytecode, int pc, RuntimeBase[] registers)
int rd = bytecode[pc++];
int rs = bytecode[pc++];
int ctx = bytecode[pc++];

if (ctx == RuntimeContextType.RUNTIME) ctx = ((RuntimeScalar) registers[2]).getInt();
registers[rd] = Stat.lstat((RuntimeScalar) registers[rs], ctx);
return pc;
}

public static int executeStatLastHandle(int[] bytecode, int pc, RuntimeBase[] registers) {
int rd = bytecode[pc++];
int ctx = bytecode[pc++];

if (ctx == RuntimeContextType.RUNTIME) ctx = ((RuntimeScalar) registers[2]).getInt();
registers[rd] = Stat.statLastHandle(ctx);
return pc;
}

public static int executeLstatLastHandle(int[] bytecode, int pc, RuntimeBase[] registers) {
int rd = bytecode[pc++];
int ctx = bytecode[pc++];

if (ctx == RuntimeContextType.RUNTIME) ctx = ((RuntimeScalar) registers[2]).getInt();
registers[rd] = Stat.lstatLastHandle(ctx);
return pc;
}
Expand Down Expand Up @@ -782,6 +794,8 @@ public static int executePostAutoDecrement(int[] bytecode, int pc, RuntimeBase[]
public static int executeOpen(int[] bytecode, int pc, RuntimeBase[] registers) {
int rd = bytecode[pc++];
int ctx = bytecode[pc++];

if (ctx == RuntimeContextType.RUNTIME) ctx = ((RuntimeScalar) registers[2]).getInt();
int argsReg = bytecode[pc++];
RuntimeArray argsArray = (RuntimeArray) registers[argsReg];
RuntimeBase[] argsVarargs = argsArray.elements.toArray(new RuntimeBase[0]);
Expand All @@ -797,6 +811,8 @@ public static int executeReadline(int[] bytecode, int pc, RuntimeBase[] register
int rd = bytecode[pc++];
int fhReg = bytecode[pc++];
int ctx = bytecode[pc++];

if (ctx == RuntimeContextType.RUNTIME) ctx = ((RuntimeScalar) registers[2]).getInt();
RuntimeScalar fh = (RuntimeScalar) registers[fhReg];
// Diamond operator <> passes a plain string scalar (not a glob/IO).
// Route to DiamondIO.readline which manages @ARGV / STDIN iteration.
Expand All @@ -817,6 +833,8 @@ public static int executeMatchRegex(int[] bytecode, int pc, RuntimeBase[] regist
int stringReg = bytecode[pc++];
int regexReg = bytecode[pc++];
int ctx = bytecode[pc++];

if (ctx == RuntimeContextType.RUNTIME) ctx = ((RuntimeScalar) registers[2]).getInt();
registers[rd] = RuntimeRegex.matchRegex(
(RuntimeScalar) registers[regexReg],
(RuntimeScalar) registers[stringReg],
Expand All @@ -834,6 +852,8 @@ public static int executeMatchRegexNot(int[] bytecode, int pc, RuntimeBase[] reg
int stringReg = bytecode[pc++];
int regexReg = bytecode[pc++];
int ctx = bytecode[pc++];

if (ctx == RuntimeContextType.RUNTIME) ctx = ((RuntimeScalar) registers[2]).getInt();
RuntimeBase matchResult = RuntimeRegex.matchRegex(
(RuntimeScalar) registers[regexReg],
(RuntimeScalar) registers[stringReg],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ public static int executeEvalString(
if (pc < bytecode.length) {
evalCallContext = bytecode[pc++];
}
if (evalCallContext == RuntimeContextType.RUNTIME) evalCallContext = ((RuntimeScalar) registers[2]).getInt();
int evalSiteIndex = -1;
if (pc < bytecode.length) {
evalSiteIndex = bytecode[pc++];
Expand Down Expand Up @@ -691,6 +692,7 @@ public static int executeSplice(
int arrayReg = bytecode[pc++];
int argsReg = bytecode[pc++];
int context = bytecode[pc++];
if (context == RuntimeContextType.RUNTIME) context = ((RuntimeScalar) registers[2]).getInt();

RuntimeArray array = (RuntimeArray) registers[arrayReg];
RuntimeList args = (RuntimeList) registers[argsReg];
Expand Down Expand Up @@ -747,6 +749,8 @@ public static int executeReverse(
int argsReg = bytecode[pc++];
int ctx = bytecode[pc++];

if (ctx == RuntimeContextType.RUNTIME) ctx = ((RuntimeScalar) registers[2]).getInt();

RuntimeList argsList = (RuntimeList) registers[argsReg];
RuntimeBase[] args = argsList.elements.toArray(new RuntimeBase[0]);

Expand Down Expand Up @@ -800,6 +804,8 @@ public static int executeSplit(
int argsReg = bytecode[pc++];
int ctx = bytecode[pc++];

if (ctx == RuntimeContextType.RUNTIME) ctx = ((RuntimeScalar) registers[2]).getInt();

RuntimeScalar pattern = (RuntimeScalar) registers[patternReg];
RuntimeBase argsBase = registers[argsReg];
RuntimeList args = (argsBase instanceof RuntimeList)
Expand Down Expand Up @@ -1266,6 +1272,7 @@ public static int executeTransliterate(

// Read context (1 int slot)
int context = bytecode[pc++];
if (context == RuntimeContextType.RUNTIME) context = ((RuntimeScalar) registers[2]).getInt();

RuntimeScalar search = (RuntimeScalar) registers[searchReg];
RuntimeScalar replace = (RuntimeScalar) registers[replaceReg];
Expand Down
Loading
Loading