Skip to content
Closed
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
22 changes: 20 additions & 2 deletions src/main/java/org/perlonjava/codegen/Dereference.java
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,25 @@ public static void handleArrowArrayDeref(EmitterVisitor emitterVisitor, BinaryOp
emitterVisitor.ctx.mv.visitVarInsn(Opcodes.ASTORE, leftSlot);

ArrayLiteralNode right = (ArrayLiteralNode) node.right;
if (right.elements.size() == 1) {

// Check if all elements are safe for single-element optimization
// (i.e., they can be evaluated in SCALAR context without needing LIST context expansion)
boolean allSafeForSingleElement = true;
for (Node elem : right.elements) {
// Ranges (.. operator) need LIST context to expand to multiple indices
if (elem instanceof BinaryOperatorNode binOp && "..".equals(binOp.operator)) {
allSafeForSingleElement = false;
break;
}
// Array slices need LIST context
if (elem instanceof OperatorNode opNode && opNode.operator.startsWith("@")) {
allSafeForSingleElement = false;
break;
}
// Most other nodes (NumberNode, StringNode, IdentifierNode, $var, $var[0], etc.) are safe
}

if (allSafeForSingleElement && right.elements.size() == 1) {
// Single index: use get/delete/exists methods
Node elem = right.elements.getFirst();
elem.accept(emitterVisitor.with(RuntimeContextType.SCALAR));
Expand Down Expand Up @@ -741,7 +759,7 @@ public static void handleArrowArrayDeref(EmitterVisitor emitterVisitor, BinaryOp
emitterVisitor.ctx.javaClassInfo.releaseSpillSlot();
}
} else {
// Multiple indices: use slice method (only for get operation)
// Multiple indices or non-literal elements: use slice method (only for get operation)
if (!arrayOperation.equals("get")) {
throw new PerlCompilerException(node.tokenIndex, "Array slice not supported for " + arrayOperation, emitterVisitor.ctx.errorUtil);
}
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/org/perlonjava/runtime/RuntimeArrayProxyEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,24 @@ public class RuntimeArrayProxyEntry extends RuntimeBaseProxy {
// Index associated with this proxy in the parent array
private final int key;

/**
* Gets the parent RuntimeArray.
*
* @return the parent RuntimeArray
*/
public RuntimeArray getParent() {
return parent;
}

/**
* Gets the key (index) for this proxy entry.
*
* @return the index in the parent array
*/
public int getKey() {
return key;
}

/**
* Constructs a RuntimeArrayProxyEntry for a given index in the specified parent array.
*
Expand Down
32 changes: 32 additions & 0 deletions src/main/java/org/perlonjava/runtime/RuntimeArraySizeLvalue.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,36 @@ public RuntimeScalar set(RuntimeScalar value) {
parent.setLastElementIndex(value);
return this;
}

/**
* Performs pre-decrement on the array size ($#array--).
*
* @return The updated array size after decrement.
*/
@Override
public RuntimeScalar preAutoDecrement() {
RuntimeArray parent = lvalue.arrayDeref();
RuntimeScalar currentSize = new RuntimeScalar(parent.lastElementIndex());
RuntimeScalar newSize = new RuntimeScalar(currentSize.getInt() - 1);
parent.setLastElementIndex(newSize);
this.value = newSize.value;
this.type = newSize.type;
return newSize;
}

/**
* Performs post-decrement on the array size ($#array--).
*
* @return The original array size before decrement.
*/
@Override
public RuntimeScalar postAutoDecrement() {
RuntimeArray parent = lvalue.arrayDeref();
RuntimeScalar originalSize = new RuntimeScalar(parent.lastElementIndex());
RuntimeScalar newSize = new RuntimeScalar(originalSize.getInt() - 1);
parent.setLastElementIndex(newSize);
this.value = newSize.value;
this.type = newSize.type;
return originalSize;
}
}