diff --git a/src/main/java/org/perlonjava/backend/bytecode/CompileOperator.java b/src/main/java/org/perlonjava/backend/bytecode/CompileOperator.java index 0835c41b9..d3b015015 100644 --- a/src/main/java/org/perlonjava/backend/bytecode/CompileOperator.java +++ b/src/main/java/org/perlonjava/backend/bytecode/CompileOperator.java @@ -970,8 +970,9 @@ public static void visitOperator(BytecodeCompiler bytecodeCompiler, OperatorNode } case "rand" -> { int rd = bytecodeCompiler.allocateOutputRegister(); - if (node.operand != null) { - node.operand.accept(bytecodeCompiler); + if (node.operand != null + && !(node.operand instanceof ListNode listNode && listNode.elements.isEmpty())) { + compileScalarOperand(bytecodeCompiler, node, "rand"); int maxReg = bytecodeCompiler.lastResultReg; bytecodeCompiler.emit(Opcodes.RAND); bytecodeCompiler.emitReg(rd); diff --git a/src/main/java/org/perlonjava/backend/bytecode/InlineOpcodeHandler.java b/src/main/java/org/perlonjava/backend/bytecode/InlineOpcodeHandler.java index 45f0af12e..4210b465a 100644 --- a/src/main/java/org/perlonjava/backend/bytecode/InlineOpcodeHandler.java +++ b/src/main/java/org/perlonjava/backend/bytecode/InlineOpcodeHandler.java @@ -1003,7 +1003,7 @@ public static int executeRand(int[] bytecode, int pc, RuntimeBase[] registers) { int rd = bytecode[pc++]; int maxReg = bytecode[pc++]; - RuntimeScalar max = (RuntimeScalar) registers[maxReg]; + RuntimeScalar max = registers[maxReg].scalar(); registers[rd] = Random.rand(max); return pc; } diff --git a/src/test/resources/unit/rand_scalar_context.t b/src/test/resources/unit/rand_scalar_context.t new file mode 100644 index 000000000..73a5ff8f2 --- /dev/null +++ b/src/test/resources/unit/rand_scalar_context.t @@ -0,0 +1,28 @@ +use strict; +use warnings; +use Test::More tests => 4; + +my @values = qw(a b c d); +my $limit = rand @values; +ok($limit >= 0 && $limit < @values, 'rand uses array argument in scalar context'); + +my $aref = [qw(a b c d)]; +my $picked = $aref->[rand @$aref]; +my $found = grep { $_ eq $picked } @$aref; +ok($found, 'rand uses array dereference argument in scalar context'); + +my $code = q{ + sub { + my %retval = @_; + my $stuff; + $stuff = ["aaa".."aaj"]; + $retval{Alpha} ||= $stuff->[rand @$stuff]; + return \%retval; + } +}; + +my $generate = eval $code; +ok($generate, 'eval-generated sub with rand array dereference compiles'); + +my $thing = $generate->(); +like($thing->{Alpha}, qr/^aa[a-j]$/, 'eval-generated rand array dereference returns an element');