Skip to content

Commit fa477fd

Browse files
committed
Fix interpreter: glob assignment lvalue, DEREF error propagation, each/chop
- CompileAssignment: handle '*' as glob lvalue (e.g. 'foo'->** = 'bar'->**) Fixes: op/postfixderef.t tests 27-29 (glob access syntax) - BytecodeInterpreter DEREF: always call scalarDeref() so non-reference types (IO, FORMAT, etc.) correctly throw 'Not a SCALAR reference' Fixes: op/postfixderef.t tests 59, 63 - CompileOperator each: force LIST context on operand so %h remains a RuntimeHash instead of being converted to ARRAY_SIZE via scalar context Fixes: op/lex_assign.t test 86 (each %h inside scalar assignment) - OpcodeHandlerExtended.executeChop: use polymorphic .chop() instead of hard-casting to RuntimeScalar - MiscOpcodeHandler: handle EACH before RuntimeList cast since EACH now receives the container (RuntimeHash/RuntimeArray) directly
1 parent 3b55221 commit fa477fd

2 files changed

Lines changed: 20 additions & 9 deletions

File tree

src/main/java/org/perlonjava/backend/bytecode/BytecodeInterpreter.java

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,15 +1405,10 @@ public static RuntimeList execute(InterpretedCode code, RuntimeArray args, int c
14051405
int rs = bytecode[pc++];
14061406
RuntimeBase value = registers[rs];
14071407

1408-
// Only dereference if it's a RuntimeScalar with REFERENCE type
1409-
if (value instanceof RuntimeScalar) {
1410-
RuntimeScalar scalar = (RuntimeScalar) value;
1411-
if (scalar.type == RuntimeScalarType.REFERENCE) {
1412-
registers[rd] = scalar.scalarDeref();
1413-
} else {
1414-
// Non-reference scalar, just copy
1415-
registers[rd] = value;
1416-
}
1408+
if (value instanceof RuntimeScalar scalar) {
1409+
// Always go through scalarDeref() so non-reference types throw
1410+
// "Not a SCALAR reference" (matches JVM path behaviour)
1411+
registers[rd] = scalar.scalarDeref();
14171412
} else {
14181413
// RuntimeList or other types, pass through
14191414
registers[rd] = value;

src/main/java/org/perlonjava/backend/bytecode/CompileAssignment.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,22 @@ public static void compileAssignmentOperator(BytecodeCompiler bytecodeCompiler,
991991
} else {
992992
bytecodeCompiler.throwCompilerException("Assignment to unsupported array dereference");
993993
}
994+
} else if (leftOp.operator.equals("*")) {
995+
// Glob assignment: *foo = *bar or 'foo'->** = ...
996+
// Compile LHS glob, compile RHS, emit STORE_GLOB
997+
int savedCtx = bytecodeCompiler.currentCallContext;
998+
bytecodeCompiler.currentCallContext = RuntimeContextType.LIST;
999+
node.left.accept(bytecodeCompiler);
1000+
bytecodeCompiler.currentCallContext = savedCtx;
1001+
int globReg = bytecodeCompiler.lastResultReg;
1002+
1003+
node.right.accept(bytecodeCompiler);
1004+
int valueReg2 = bytecodeCompiler.lastResultReg;
1005+
1006+
bytecodeCompiler.emit(Opcodes.STORE_GLOB);
1007+
bytecodeCompiler.emitReg(globReg);
1008+
bytecodeCompiler.emitReg(valueReg2);
1009+
bytecodeCompiler.lastResultReg = globReg;
9941010
} else {
9951011
// chop/chomp cannot be used as lvalues (matches JVM compiler message)
9961012
if (leftOp.operator.equals("chop") || leftOp.operator.equals("chomp")) {

0 commit comments

Comments
 (0)