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
Original file line number Diff line number Diff line change
Expand Up @@ -398,12 +398,14 @@ private static int resolveHashFromBinaryOp(BytecodeCompiler bc, BinaryOperatorNo
bc.emit(nameIdx);
return hashReg;
} else {
leftOp.operand.accept(bc);
// Compile operand in SCALAR context to ensure we get a result register
bc.compileNode(leftOp.operand, -1, RuntimeContextType.SCALAR);
int scalarReg = bc.lastResultReg;
return derefHash(bc, scalarReg, tokenIndex);
}
} else if (hashAccess.left instanceof BinaryOperatorNode) {
hashAccess.left.accept(bc);
// Compile in SCALAR context to ensure we get a result register
bc.compileNode(hashAccess.left, -1, RuntimeContextType.SCALAR);
int scalarReg = bc.lastResultReg;
return derefHash(bc, scalarReg, tokenIndex);
}
Expand Down
40 changes: 36 additions & 4 deletions src/main/java/org/perlonjava/backend/jvm/Dereference.java
Original file line number Diff line number Diff line change
Expand Up @@ -584,12 +584,28 @@ public static void handleHashElementOperator(EmitterVisitor emitterVisitor, Bina
Node elem = nodeRight.elements.getFirst();
elem.accept(scalarVisitor);
if (emitterVisitor.ctx.symbolTable.isStrictOptionEnabled(HINT_STRICT_REFS)) {
// Use strict version (throws error on symbolic references)
String methodName = switch (hashOperation) {
case "get" -> "hashDerefGet";
case "delete" -> "hashDerefDelete";
case "exists" -> "hashDerefExists";
default ->
throw new PerlCompilerException(node.tokenIndex, "Not implemented: hash operation: " + hashOperation, emitterVisitor.ctx.errorUtil);
};
emitterVisitor.ctx.mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/perlonjava/runtime/runtimetypes/RuntimeScalar",
"hashDerefGet", "(Lorg/perlonjava/runtime/runtimetypes/RuntimeScalar;)Lorg/perlonjava/runtime/runtimetypes/RuntimeScalar;", false);
methodName, "(Lorg/perlonjava/runtime/runtimetypes/RuntimeScalar;)Lorg/perlonjava/runtime/runtimetypes/RuntimeScalar;", false);
} else {
// Use non-strict version (allows symbolic references)
String methodName = switch (hashOperation) {
case "get" -> "hashDerefGetNonStrict";
case "delete" -> "hashDerefDeleteNonStrict";
case "exists" -> "hashDerefExistsNonStrict";
default ->
throw new PerlCompilerException(node.tokenIndex, "Not implemented: hash operation: " + hashOperation, emitterVisitor.ctx.errorUtil);
};
emitterVisitor.pushCurrentPackage();
emitterVisitor.ctx.mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/perlonjava/runtime/runtimetypes/RuntimeScalar",
"hashDerefGetNonStrict", "(Lorg/perlonjava/runtime/runtimetypes/RuntimeScalar;Ljava/lang/String;)Lorg/perlonjava/runtime/runtimetypes/RuntimeScalar;", false);
methodName, "(Lorg/perlonjava/runtime/runtimetypes/RuntimeScalar;Ljava/lang/String;)Lorg/perlonjava/runtime/runtimetypes/RuntimeScalar;", false);
}
} else {
// Multiple elements - this is a hash slice, but that's not commonly used with ${}
Expand All @@ -601,12 +617,28 @@ public static void handleHashElementOperator(EmitterVisitor emitterVisitor, Bina
emitterVisitor.ctx.mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/perlonjava/runtime/operators/StringOperators",
"join", "(Lorg/perlonjava/runtime/runtimetypes/RuntimeScalar;Lorg/perlonjava/runtime/runtimetypes/RuntimeBase;)Lorg/perlonjava/runtime/runtimetypes/RuntimeScalar;", false);
if (emitterVisitor.ctx.symbolTable.isStrictOptionEnabled(HINT_STRICT_REFS)) {
// Use strict version (throws error on symbolic references)
String methodName = switch (hashOperation) {
case "get" -> "hashDerefGet";
case "delete" -> "hashDerefDelete";
case "exists" -> "hashDerefExists";
default ->
throw new PerlCompilerException(node.tokenIndex, "Not implemented: hash operation: " + hashOperation, emitterVisitor.ctx.errorUtil);
};
emitterVisitor.ctx.mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/perlonjava/runtime/runtimetypes/RuntimeScalar",
"hashDerefGet", "(Lorg/perlonjava/runtime/runtimetypes/RuntimeScalar;)Lorg/perlonjava/runtime/runtimetypes/RuntimeScalar;", false);
methodName, "(Lorg/perlonjava/runtime/runtimetypes/RuntimeScalar;)Lorg/perlonjava/runtime/runtimetypes/RuntimeScalar;", false);
} else {
// Use non-strict version (allows symbolic references)
String methodName = switch (hashOperation) {
case "get" -> "hashDerefGetNonStrict";
case "delete" -> "hashDerefDeleteNonStrict";
case "exists" -> "hashDerefExistsNonStrict";
default ->
throw new PerlCompilerException(node.tokenIndex, "Not implemented: hash operation: " + hashOperation, emitterVisitor.ctx.errorUtil);
};
emitterVisitor.pushCurrentPackage();
emitterVisitor.ctx.mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/perlonjava/runtime/runtimetypes/RuntimeScalar",
"hashDerefGetNonStrict", "(Lorg/perlonjava/runtime/runtimetypes/RuntimeScalar;Ljava/lang/String;)Lorg/perlonjava/runtime/runtimetypes/RuntimeScalar;", false);
methodName, "(Lorg/perlonjava/runtime/runtimetypes/RuntimeScalar;Ljava/lang/String;)Lorg/perlonjava/runtime/runtimetypes/RuntimeScalar;", false);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/perlonjava/core/Configuration.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public final class Configuration {
* Automatically populated by Gradle/Maven during build.
* DO NOT EDIT MANUALLY - this value is replaced at build time.
*/
public static final String gitCommitId = "bef8bcb54";
public static final String gitCommitId = "0f1682f37";

/**
* Git commit date of the build (ISO format: YYYY-MM-DD).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ public RuntimeScalar remove(Object key) {
}

// Get references to all the slots before deleting
// Only remove from globalCodeRefs, NOT pinnedCodeRefs, to allow compiled code
// to continue calling the subroutine (Perl caches CVs at compile time)
RuntimeScalar code = GlobalVariable.globalCodeRefs.remove(fullKey);
RuntimeScalar scalar = GlobalVariable.globalVariables.remove(fullKey);
RuntimeArray array = GlobalVariable.globalArrays.remove(fullKey);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ private RuntimeScalar deleteGlob(String k) {
}

// Get the CODE slot before deleting (most common case)
// Only remove from globalCodeRefs, NOT pinnedCodeRefs, to allow compiled code
// to continue calling the subroutine (Perl caches CVs at compile time)
RuntimeScalar code = GlobalVariable.globalCodeRefs.remove(fullKey);

// Delete all other slots
Expand Down
Loading