Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement bir, codegen and runtime changes for spread operator #35696

Merged
Show file tree
Hide file tree
Changes from 12 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 @@ -25,6 +25,8 @@
import io.ballerina.runtime.api.types.ArrayType.ArrayState;
import io.ballerina.runtime.api.types.Type;
import io.ballerina.runtime.api.utils.StringUtils;
import io.ballerina.runtime.api.values.BArray;
import io.ballerina.runtime.api.values.BIterator;
import io.ballerina.runtime.api.values.BLink;
import io.ballerina.runtime.api.values.BListInitialValueEntry;
import io.ballerina.runtime.api.values.BString;
Expand Down Expand Up @@ -266,9 +268,20 @@ public ArrayValueImpl(ArrayType type, long size, BListInitialValueEntry[] initia
if (size != -1) {
this.size = this.maxSize = (int) size;
}
for (int index = 0; index < initialValues.length; index++) {
addRefValue(index, ((ListInitialValueEntry.ExpressionEntry) initialValues[index]).value);

int index = 0;
pcnfernando marked this conversation as resolved.
Show resolved Hide resolved
for (BListInitialValueEntry listEntry : initialValues) {
if (listEntry instanceof ListInitialValueEntry.ExpressionEntry) {
addRefValue(index++, ((ListInitialValueEntry.ExpressionEntry) listEntry).value);
} else {
BArray values = ((ListInitialValueEntry.SpreadEntry) listEntry).values;
BIterator<?> iterator = values.getIterator();
while (iterator.hasNext()) {
addRefValue(index++, iterator.next());
}
}
}

this.typedesc = getTypedescValue(arrayType, this);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

package io.ballerina.runtime.internal.values;

import io.ballerina.runtime.api.values.BArray;
import io.ballerina.runtime.api.values.BListInitialValueEntry;

/**
Expand All @@ -40,4 +41,18 @@ public ExpressionEntry(Object value) {
this.value = value;
}
}

/**
* Represents an initial spread member entry in a list constructor expression.
*
* @since 2201.1.0
*/
public static class SpreadEntry extends ListInitialValueEntry {

public BArray values;

public SpreadEntry(BArray arrayValue) {
this.values = arrayValue;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import io.ballerina.runtime.api.types.Type;
import io.ballerina.runtime.api.utils.StringUtils;
import io.ballerina.runtime.api.values.BArray;
import io.ballerina.runtime.api.values.BIterator;
import io.ballerina.runtime.api.values.BLink;
import io.ballerina.runtime.api.values.BListInitialValueEntry;
import io.ballerina.runtime.api.values.BString;
Expand Down Expand Up @@ -146,7 +147,17 @@ public TupleValueImpl(TupleType type, long size, BListInitialValueEntry[] initia
List<Type> memTypes = this.tupleType.getTupleTypes();
int memCount = memTypes.size();

this.size = size < memCount ? memCount : (int) size;
int valueCount = 0;
for (BListInitialValueEntry listEntry : initialValues) {
lochana-chathura marked this conversation as resolved.
Show resolved Hide resolved
if (listEntry instanceof ListInitialValueEntry.ExpressionEntry) {
valueCount++;
} else {
BArray values = ((ListInitialValueEntry.SpreadEntry) listEntry).values;
valueCount += values.size();
}
}

this.size = Math.max(valueCount, memCount);
this.minSize = memCount;
this.hasRestElement = this.tupleType.getRestType() != null;

Expand All @@ -157,16 +168,25 @@ public TupleValueImpl(TupleType type, long size, BListInitialValueEntry[] initia
this.refValues = new Object[DEFAULT_ARRAY_SIZE];
}

for (int index = 0; index < initialValues.length; index++) {
addRefValue(index, ((ListInitialValueEntry.ExpressionEntry) initialValues[index]).value);
int index = 0;
for (BListInitialValueEntry listEntry : initialValues) {
if (listEntry instanceof ListInitialValueEntry.ExpressionEntry) {
addRefValue(index++, ((ListInitialValueEntry.ExpressionEntry) listEntry).value);
} else {
BArray values = ((ListInitialValueEntry.SpreadEntry) listEntry).values;
BIterator<?> iterator = values.getIterator();
while (iterator.hasNext()) {
addRefValue(index++, iterator.next());
}
}
}

if (size >= memCount) {
if (index >= memCount) {
this.typedesc = getTypedescValue(tupleType, this);
return;
}

for (int i = (int) size; i < memCount; i++) {
for (int i = index; i < memCount; i++) {
Type memType = memTypes.get(i);
if (!TypeChecker.hasFillerValue(memType)) {
continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@
import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr.BLangArrayLiteral;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr.BLangJSONArrayLiteral;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr.BLangListConstructorSpreadOpExpr;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr.BLangTupleLiteral;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangRecordLiteral;
Expand Down Expand Up @@ -2559,16 +2560,22 @@ private void generateListConstructorExpr(BLangListConstructorExpr listConstructo
literal.accept(this);
BIROperand sizeOp = this.env.targetOperand;

List<BIROperand> valueOperands = new ArrayList<>(exprs.size());
List<BIRNode.BIRListConstructorEntry> initialValues = new ArrayList<>(exprs.size());

for (BLangExpression expr : exprs) {
expr.accept(this);
valueOperands.add(this.env.targetOperand);
if (expr.getKind() == NodeKind.LIST_CONSTRUCTOR_SPREAD_OP) {
BLangListConstructorSpreadOpExpr spreadMember = (BLangListConstructorSpreadOpExpr) expr;
spreadMember.expr.accept(this);
initialValues.add(new BIRNode.BIRListConstructorSpreadMemberEntry(this.env.targetOperand));
} else {
expr.accept(this);
initialValues.add(new BIRNode.BIRListConstructorExprEntry(this.env.targetOperand));
}
}

setScopeAndEmit(
new BIRNonTerminator.NewArray(listConstructorExpr.pos, listConstructorExprType, toVarRef, sizeOp,
valueOperands));
initialValues));
this.env.targetOperand = toVarRef;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public class JvmConstants {
public static final String B_FUNCTION_POINTER = "io/ballerina/runtime/api/values/BFunctionPointer";
public static final String B_MAP = "io/ballerina/runtime/api/values/BMap";
public static final String B_OBJECT = "io/ballerina/runtime/api/values/BObject";
public static final String B_ARRAY = "io/ballerina/runtime/api/values/BArray";

// jvm runtime values related classes
public static final String MAP_VALUE = "io/ballerina/runtime/internal/values/MapValue";
Expand Down Expand Up @@ -89,6 +90,8 @@ public class JvmConstants {
public static final String LIST_INITIAL_VALUE_ENTRY = "io/ballerina/runtime/internal/values/ListInitialValueEntry";
public static final String LIST_INITIAL_EXPRESSION_ENTRY =
"io/ballerina/runtime/internal/values/ListInitialValueEntry$ExpressionEntry";
public static final String LIST_INITIAL_SPREAD_ENTRY =
"io/ballerina/runtime/internal/values/ListInitialValueEntry$SpreadEntry";

// types related classes
public static final String TYPE = "io/ballerina/runtime/api/types/Type";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.JVM_INIT_METHOD;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.JVM_TO_UNSIGNED_INT_METHOD;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.LIST_INITIAL_EXPRESSION_ENTRY;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.LIST_INITIAL_SPREAD_ENTRY;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.LIST_INITIAL_VALUE_ENTRY;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.LONG_STREAM;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.MAPPING_INITIAL_KEY_VALUE_ENTRY;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.MAPPING_INITIAL_SPREAD_FIELD_ENTRY;
Expand Down Expand Up @@ -194,6 +196,7 @@
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INIT_ARRAY_WITH_INITIAL_VALUES;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INIT_ERROR_WITH_TYPE;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INIT_LIST_INITIAL_EXPRESSION_ENTRY;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INIT_LIST_INITIAL_SPREAD_ENTRY;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INIT_MAPPING_INITIAL_SPREAD_FIELD_ENTRY;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INIT_TABLE_VALUE_IMPL;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INIT_TUPLE;
Expand Down Expand Up @@ -1996,32 +1999,51 @@ void generateConstantLoadIns(BIRNonTerminator.ConstantLoad loadIns) {
}

private void loadListInitialValues(BIRNonTerminator.NewArray arrayNewIns) {
List<BIROperand> initialValues = arrayNewIns.values;
List<BIRNode.BIRListConstructorEntry> initialValues = arrayNewIns.values;
mv.visitLdcInsn((long) initialValues.size());
mv.visitInsn(L2I);
mv.visitTypeInsn(ANEWARRAY, LIST_INITIAL_EXPRESSION_ENTRY);
mv.visitTypeInsn(ANEWARRAY, LIST_INITIAL_VALUE_ENTRY);

int i = 0;
for (BIROperand initialValueOp : initialValues) {
for (BIRNode.BIRListConstructorEntry initialValueOp : initialValues) {
mv.visitInsn(DUP);
mv.visitLdcInsn((long) i);
mv.visitInsn(L2I);
i += 1;

mv.visitTypeInsn(NEW, LIST_INITIAL_EXPRESSION_ENTRY);
mv.visitInsn(DUP);

BIRNode.BIRVariableDcl varDecl = initialValueOp.variableDcl;
this.loadVar(varDecl);
jvmCastGen.addBoxInsn(this.mv, varDecl.type);

mv.visitMethodInsn(INVOKESPECIAL, LIST_INITIAL_EXPRESSION_ENTRY, JVM_INIT_METHOD,
INIT_LIST_INITIAL_EXPRESSION_ENTRY, false);
if (initialValueOp instanceof BIRNode.BIRListConstructorExprEntry) {
createExprEntry(initialValueOp);
} else {
createSpreadEntry(initialValueOp);
}

mv.visitInsn(AASTORE);
}
}

private void createExprEntry(BIRNode.BIRListConstructorEntry initialValueOp) {
mv.visitTypeInsn(NEW, LIST_INITIAL_EXPRESSION_ENTRY);
mv.visitInsn(DUP);

BIRNode.BIRVariableDcl varDecl = initialValueOp.exprOp.variableDcl;
this.loadVar(varDecl);
jvmCastGen.addBoxInsn(this.mv, varDecl.type);

mv.visitMethodInsn(INVOKESPECIAL, LIST_INITIAL_EXPRESSION_ENTRY, JVM_INIT_METHOD,
INIT_LIST_INITIAL_EXPRESSION_ENTRY, false);
}

private void createSpreadEntry(BIRNode.BIRListConstructorEntry initialValueOp) {
mv.visitTypeInsn(NEW, LIST_INITIAL_SPREAD_ENTRY);
mv.visitInsn(DUP);

BIRNode.BIRVariableDcl varDecl = initialValueOp.exprOp.variableDcl;
this.loadVar(varDecl);

mv.visitMethodInsn(INVOKESPECIAL, LIST_INITIAL_SPREAD_ENTRY, JVM_INIT_METHOD, INIT_LIST_INITIAL_SPREAD_ENTRY,
false);
}

void generateInstructions(int localVarOffset, BIRInstruction inst) {
if (inst instanceof BIRNonTerminator.BinaryOp) {
generateBinaryOpIns((BIRNonTerminator.BinaryOp) inst);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.BOOLEAN_TYPE;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.BOOLEAN_VALUE;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.BYTE_TYPE;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.B_ARRAY;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.B_FUNCTION_POINTER;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.B_INITIAL_VALUE_ENTRY;
import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.B_LIST_INITIAL_VALUE_ENTRY;
Expand Down Expand Up @@ -273,6 +274,7 @@ public class JvmSignatures {
"(L" + MODULE + ";[L" + TYPE + ";L" + INTERSECTABLE_REFERENCE_TYPE + ";IZ)V";
public static final String INIT_INTERSECTION_TYPE_WITH_TYPE = "(L" + MODULE + ";[L" + TYPE + ";L" + TYPE + ";IZ)V";
public static final String INIT_LIST_INITIAL_EXPRESSION_ENTRY = "(L" + OBJECT + ";)V";
public static final String INIT_LIST_INITIAL_SPREAD_ENTRY = "(L" + B_ARRAY + ";)V";
public static final String INIT_LISTENER_REGISTRY = "(L" + JvmConstants.LISTENER_REGISTRY_CLASS + ";)V";
public static final String INIT_MAPPING_INITIAL_SPREAD_FIELD_ENTRY = "(L" + B_MAP + ";)V";
public static final String INIT_MODULE = "(L" + STRING_VALUE + ";L" + STRING_VALUE + ";L" + STRING_VALUE + ";)V";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,39 @@ public boolean isKeyValuePair() {
}
}

/**
* Represents a list member entry in a list constructor expression.
*
* @since 2201.1.0
*/
public abstract static class BIRListConstructorEntry {
public BIROperand exprOp;
}

/**
* Represents a spread member entry in a list constructor expression.
*
* @since 2201.1.0
*/
public static class BIRListConstructorSpreadMemberEntry extends BIRListConstructorEntry {

public BIRListConstructorSpreadMemberEntry(BIROperand exprOp) {
this.exprOp = exprOp;
}
}

/**
* Represents an expression member entry in a list constructor expression.
*
* @since 2201.1.0
*/
public static class BIRListConstructorExprEntry extends BIRListConstructorEntry {

public BIRListConstructorExprEntry(BIROperand exprOp) {
this.exprOp = exprOp;
}
}

/**
* Represents a service declaration.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,10 +286,10 @@ public BIROperand[] getRhsOperands() {
public static class NewArray extends BIRNonTerminator {
public BIROperand sizeOp;
public BType type;
public List<BIROperand> values;
public List<BIRListConstructorEntry> values;

public NewArray(Location location, BType type, BIROperand lhsOp, BIROperand sizeOp,
List<BIROperand> values) {
List<BIRListConstructorEntry> values) {
super(location, InstructionKind.NEW_ARRAY);
this.type = type;
this.lhsOp = lhsOp;
Expand All @@ -307,8 +307,8 @@ public BIROperand[] getRhsOperands() {
BIROperand[] operands = new BIROperand[values.size() + 1];
int i = 0;
operands[i++] = sizeOp;
for (BIROperand operand : values) {
operands[i++] = operand;
for (BIRListConstructorEntry listValueEntry : values) {
operands[i++] = listValueEntry.exprOp;
}
return operands;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -530,8 +530,8 @@ public void visit(BIRNonTerminator.NewArray birNewArray) {
this.optimizeNode(birNewArray.lhsOp, this.env);
this.optimizeNode(birNewArray.sizeOp, this.env);

for (BIROperand value : birNewArray.values) {
this.optimizeNode(value, this.env);
for (BIRNode.BIRListConstructorEntry listValueEntry : birNewArray.values) {
this.optimizeNode(listValueEntry.exprOp, this.env);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,8 +390,8 @@ public void visit(NewArray birNewArray) {
birNewArray.lhsOp.accept(this);
birNewArray.sizeOp.accept(this);
buf.writeInt(birNewArray.values.size());
for (BIROperand value : birNewArray.values) {
value.accept(this);
for (BIRNode.BIRListConstructorEntry listValueEntry : birNewArray.values) {
listValueEntry.exprOp.accept(this);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
import org.wso2.ballerinalang.compiler.tree.expressions.BLangIsLikeExpr;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangLambdaFunction;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr.BLangListConstructorSpreadOpExpr;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownDocumentationLine;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownParameterDocumentation;
Expand Down Expand Up @@ -1106,6 +1107,12 @@ public void visit(BLangLiteral literalExpr) {
result = literalExpr;
}

@Override
public void visit(BLangListConstructorSpreadOpExpr listConstructorSpreadOpExpr) {
rewriteExpr(listConstructorSpreadOpExpr.expr);
result = listConstructorSpreadOpExpr;
}

@Override
public void visit(BLangListConstructorExpr listConstructorExpr) {
rewriteExprs(listConstructorExpr.exprs);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
import org.wso2.ballerinalang.compiler.tree.expressions.BLangLambdaFunction;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangLetExpression;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr.BLangListConstructorSpreadOpExpr;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangNamedArgsExpression;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangNumericLiteral;
Expand Down Expand Up @@ -688,6 +689,12 @@ public void visit(BLangListConstructorExpr listConstructorExpr) {
result = listConstructorExpr;
}

@Override
public void visit(BLangListConstructorSpreadOpExpr listConstructorSpreadOpExpr) {
rewrite(listConstructorSpreadOpExpr.expr);
result = listConstructorSpreadOpExpr;
}

@Override
public void visit(BLangTableConstructorExpr tableConstructorExpr) {
rewrite(tableConstructorExpr.recordLiteralList);
Expand Down
Loading