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 @@ -3567,18 +3567,29 @@ public void visit(For3Node node) {
// Handle bare blocks (simple blocks) differently - they execute once, not loop
if (node.isSimpleBlock) {
// Simple bare block: { statements; }
// Create a new scope for the block
// Allocate a result register before entering scope when in non-VOID context,
// so the value is accessible after the scope exits (same pattern as BlockNode).
int outerResultReg = -1;
if (currentCallContext != RuntimeContextType.VOID) {
outerResultReg = allocateRegister();
}
enterScope();
try {
// Just execute the body once, no loop
if (node.body != null) {
node.body.accept(this);
}
lastResultReg = -1; // Block returns empty
// Save last statement result into outer register before exiting scope
if (outerResultReg >= 0 && lastResultReg >= 0) {
emit(Opcodes.MOVE);
emitReg(outerResultReg);
emitReg(lastResultReg);
}
} finally {
// Exit scope to clean up lexical variables
exitScope();
}
lastResultReg = outerResultReg;
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2083,6 +2083,19 @@ public static RuntimeList execute(InterpretedCode code, RuntimeArray args, int c
break;
}

case Opcodes.POP_PACKAGE:
// Scoped package block exit — restore handled by POP_LOCAL_LEVEL.
break;

case Opcodes.DO_FILE: {
int rd = bytecode[pc++];
int fileReg = bytecode[pc++];
int ctx = bytecode[pc++];
RuntimeScalar file = ((RuntimeBase) registers[fileReg]).scalar();
registers[rd] = ModuleOperators.doFile(file, ctx);
break;
}

default:
// Unknown opcode
int opcodeInt = opcode;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.perlonjava.backend.bytecode;

import org.perlonjava.frontend.analysis.LValueVisitor;
import org.perlonjava.frontend.astnode.*;
import org.perlonjava.runtime.runtimetypes.NameNormalizer;
import org.perlonjava.runtime.runtimetypes.RuntimeContextType;
Expand Down Expand Up @@ -1457,6 +1458,9 @@ public static void compileAssignmentOperator(BytecodeCompiler bytecodeCompiler,
// List assignment: ($a, $b) = ... or () = ...
// In scalar context, returns the number of elements on RHS
// In list context, returns the RHS list
// Validate lvalue context - throws PerlCompilerException for invalid LHS
// (e.g. "($a ? $x : ($y)) = 5" -> "Assignment to both a list and a scalar")
LValueVisitor.getContext(node.left);
ListNode listNode = (ListNode) node.left;

// Compile RHS in LIST context to get all elements
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/org/perlonjava/backend/bytecode/CompileOperator.java
Original file line number Diff line number Diff line change
Expand Up @@ -2862,6 +2862,20 @@ public static void visitOperator(BytecodeCompiler bytecodeCompiler, OperatorNode
bytecodeCompiler.emitReg(patternReg);
bytecodeCompiler.emit(bytecodeCompiler.currentCallContext);
bytecodeCompiler.lastResultReg = rd;
} else if (op.equals("doFile")) {
// do FILE: executes a Perl file
int savedContext = bytecodeCompiler.currentCallContext;
bytecodeCompiler.currentCallContext = RuntimeContextType.SCALAR;
node.operand.accept(bytecodeCompiler);
bytecodeCompiler.currentCallContext = savedContext;
int fileReg = bytecodeCompiler.lastResultReg;

int rd = bytecodeCompiler.allocateRegister();
bytecodeCompiler.emit(Opcodes.DO_FILE);
bytecodeCompiler.emitReg(rd);
bytecodeCompiler.emitReg(fileReg);
bytecodeCompiler.emit(bytecodeCompiler.currentCallContext);
bytecodeCompiler.lastResultReg = rd;
} else {
bytecodeCompiler.throwCompilerException("Unsupported operator: " + op);
}
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/org/perlonjava/backend/bytecode/InterpretedCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -1440,6 +1440,18 @@ public String disassemble() {
break;
// GENERATED_DISASM_END

case Opcodes.SET_PACKAGE:
sb.append("SET_PACKAGE '").append(stringPool[bytecode[pc++]]).append("'\n");
break;
case Opcodes.PUSH_PACKAGE:
sb.append("PUSH_PACKAGE '").append(stringPool[bytecode[pc++]]).append("'\n");
break;
case Opcodes.POP_PACKAGE:
sb.append("POP_PACKAGE\n");
break;
case Opcodes.DO_FILE:
sb.append("DO_FILE r").append(bytecode[pc++]).append(" = doFile(r").append(bytecode[pc++]).append(") ctx=").append(bytecode[pc++]).append("\n");
break;
default:
sb.append("UNKNOWN(").append(opcode).append(")\n");
break;
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/org/perlonjava/backend/bytecode/Opcodes.java
Original file line number Diff line number Diff line change
Expand Up @@ -1111,5 +1111,10 @@ public class Opcodes {
* Format: GLOB_OP rd globId patternReg ctx */
public static final short GLOB_OP = 339;

/** Execute a file: rd = ModuleOperators.doFile(fileReg, ctx)
* Implements Perl's do FILE operator.
* Format: DO_FILE rd fileReg ctx */
public static final short DO_FILE = 340;

private Opcodes() {} // Utility class - no instantiation
}