Skip to content

Commit b43ab7b

Browse files
fglockclaude
andcommitted
feat: Add process control operators to interpreter (getpgrp, setpgrp, getpriority, atan2)
Add compiler support for process control and math operators in the interpreter: - getpgrp($pid) - get process group - setpgrp($pid, $pgrp) - set process group - getpriority($which, $who) - get process priority - atan2($y, $x) - arctangent of y/x Implementation: - Opcodes already existed (GETPGRP=136, SETPGRP=137, GETPRIORITY=138, ATAN2=241) - Execution handlers already in SlowOpcodeHandler and ScalarBinaryOpcodeHandler - Added compilation code generation in CompileOperator.java Test impact (with JPERL_EVAL_USE_INTERPRETER=1): - op/lex_assign.t: 320/353 → 323/353 (+3 tests) - Fixes tests that use these operators inside eval blocks Remaining unsupported operators in eval blocks: - qx, each, caller, fileno, getc, chmod, umask, unlink, utime - rename, link, readlink, system, localtime, gmtime, pack, vec, crypt Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 8fbcc05 commit b43ab7b

1 file changed

Lines changed: 78 additions & 0 deletions

File tree

src/main/java/org/perlonjava/interpreter/CompileOperator.java

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2636,6 +2636,84 @@ public static void visitOperator(BytecodeCompiler bytecodeCompiler, OperatorNode
26362636
bytecodeCompiler.emitWithToken(Opcodes.GETPPID, node.getIndex());
26372637
bytecodeCompiler.emitReg(rd);
26382638
bytecodeCompiler.lastResultReg = rd;
2639+
} else if (op.equals("getpgrp")) {
2640+
// getpgrp($pid) - returns process group
2641+
// Format: GETPGRP rd pidReg
2642+
if (node.operand != null) {
2643+
node.operand.accept(bytecodeCompiler);
2644+
int pidReg = bytecodeCompiler.lastResultReg;
2645+
int rd = bytecodeCompiler.allocateRegister();
2646+
bytecodeCompiler.emitWithToken(Opcodes.GETPGRP, node.getIndex());
2647+
bytecodeCompiler.emitReg(rd);
2648+
bytecodeCompiler.emitReg(pidReg);
2649+
bytecodeCompiler.lastResultReg = rd;
2650+
} else {
2651+
bytecodeCompiler.throwCompilerException("getpgrp requires an argument");
2652+
}
2653+
} else if (op.equals("setpgrp")) {
2654+
// setpgrp($pid, $pgrp) - sets process group
2655+
// Format: SETPGRP pidReg pgrpReg
2656+
if (node.operand instanceof ListNode) {
2657+
ListNode list = (ListNode) node.operand;
2658+
if (list.elements.size() >= 2) {
2659+
list.elements.get(0).accept(bytecodeCompiler);
2660+
int pidReg = bytecodeCompiler.lastResultReg;
2661+
list.elements.get(1).accept(bytecodeCompiler);
2662+
int pgrpReg = bytecodeCompiler.lastResultReg;
2663+
bytecodeCompiler.emitWithToken(Opcodes.SETPGRP, node.getIndex());
2664+
bytecodeCompiler.emitReg(pidReg);
2665+
bytecodeCompiler.emitReg(pgrpReg);
2666+
bytecodeCompiler.lastResultReg = -1; // No return value
2667+
} else {
2668+
bytecodeCompiler.throwCompilerException("setpgrp requires two arguments");
2669+
}
2670+
} else {
2671+
bytecodeCompiler.throwCompilerException("setpgrp requires two arguments");
2672+
}
2673+
} else if (op.equals("getpriority")) {
2674+
// getpriority($which, $who) - returns process priority
2675+
// Format: GETPRIORITY rd whichReg whoReg
2676+
if (node.operand instanceof ListNode) {
2677+
ListNode list = (ListNode) node.operand;
2678+
if (list.elements.size() >= 2) {
2679+
list.elements.get(0).accept(bytecodeCompiler);
2680+
int whichReg = bytecodeCompiler.lastResultReg;
2681+
list.elements.get(1).accept(bytecodeCompiler);
2682+
int whoReg = bytecodeCompiler.lastResultReg;
2683+
int rd = bytecodeCompiler.allocateRegister();
2684+
bytecodeCompiler.emitWithToken(Opcodes.GETPRIORITY, node.getIndex());
2685+
bytecodeCompiler.emitReg(rd);
2686+
bytecodeCompiler.emitReg(whichReg);
2687+
bytecodeCompiler.emitReg(whoReg);
2688+
bytecodeCompiler.lastResultReg = rd;
2689+
} else {
2690+
bytecodeCompiler.throwCompilerException("getpriority requires two arguments");
2691+
}
2692+
} else {
2693+
bytecodeCompiler.throwCompilerException("getpriority requires two arguments");
2694+
}
2695+
} else if (op.equals("atan2")) {
2696+
// atan2($y, $x) - returns arctangent of y/x
2697+
// Format: ATAN2 rd rs1 rs2
2698+
if (node.operand instanceof ListNode) {
2699+
ListNode list = (ListNode) node.operand;
2700+
if (list.elements.size() >= 2) {
2701+
list.elements.get(0).accept(bytecodeCompiler);
2702+
int rs1 = bytecodeCompiler.lastResultReg;
2703+
list.elements.get(1).accept(bytecodeCompiler);
2704+
int rs2 = bytecodeCompiler.lastResultReg;
2705+
int rd = bytecodeCompiler.allocateRegister();
2706+
bytecodeCompiler.emitWithToken(Opcodes.ATAN2, node.getIndex());
2707+
bytecodeCompiler.emitReg(rd);
2708+
bytecodeCompiler.emitReg(rs1);
2709+
bytecodeCompiler.emitReg(rs2);
2710+
bytecodeCompiler.lastResultReg = rd;
2711+
} else {
2712+
bytecodeCompiler.throwCompilerException("atan2 requires two arguments");
2713+
}
2714+
} else {
2715+
bytecodeCompiler.throwCompilerException("atan2 requires two arguments");
2716+
}
26392717
} else {
26402718
bytecodeCompiler.throwCompilerException("Unsupported operator: " + op);
26412719
}

0 commit comments

Comments
 (0)