diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/TypeChecker.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/TypeChecker.java index 6717bf6a8d1b..9a7ec4dfae5e 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/TypeChecker.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/TypeChecker.java @@ -544,6 +544,11 @@ public static Object getAnnotValue(TypedescValue typedescValue, BString annotTag if (!(describingType instanceof BAnnotatableType)) { return null; } + if (typedescValue instanceof TypedescValueImpl && ((TypedescValueImpl) typedescValue).annotations != null) { + if (((TypedescValueImpl) typedescValue).annotations.containsKey(annotTag)) { + return ((TypedescValueImpl) typedescValue).annotations.get(annotTag); + } + } return ((BAnnotatableType) describingType).getAnnotation(annotTag); } @@ -2151,7 +2156,7 @@ private static boolean checkIsNeverTypeOrStructureTypeWithARequiredNeverMember(T private static boolean checkIsLikeType(List errors, Object sourceValue, Type targetType, List unresolvedValues, boolean allowNumericConversion, String varName) { - Type sourceType = getType(sourceValue); + Type sourceType = getImpliedType(getType(sourceValue)); if (checkIsType(sourceType, targetType, new ArrayList<>())) { return true; } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BTypeReferenceType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BTypeReferenceType.java index f43cd540dc0e..698780123445 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BTypeReferenceType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BTypeReferenceType.java @@ -47,6 +47,11 @@ public BTypeReferenceType(String typeName, Module pkg, int typeFlags, boolean re this.readOnly = readOnly; } + public BTypeReferenceType(Type referredType, boolean readOnly) { + this(referredType.getName(), referredType.getPkg(), (int) referredType.getFlags(), readOnly); + setReferredType(referredType); + } + public void setReferredType(Type referredType) { this.referredType = referredType; } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/util/RuntimeUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/util/RuntimeUtils.java index c914ad6242aa..c2bb50dd77c9 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/util/RuntimeUtils.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/util/RuntimeUtils.java @@ -29,6 +29,7 @@ import io.ballerina.runtime.internal.TypeConverter; import io.ballerina.runtime.internal.diagnostics.RuntimeDiagnosticLog; import io.ballerina.runtime.internal.types.BArrayType; +import io.ballerina.runtime.internal.types.BIntersectionType; import io.ballerina.runtime.internal.values.ArrayValue; import io.ballerina.runtime.internal.values.ArrayValueImpl; import io.ballerina.runtime.internal.values.ErrorValue; @@ -247,4 +248,11 @@ private static boolean isInvalidBallerinaValue(Object value) { private RuntimeUtils() { } + + public static Type getEffectiveType(Type type) { + if (type.getTag() == TypeTags.INTERSECTION_TAG) { + return ((BIntersectionType) type).getEffectiveType(); + } + return type; + } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/MapValueImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/MapValueImpl.java index b04c29edc370..d942d46bd8c0 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/MapValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/MapValueImpl.java @@ -70,6 +70,7 @@ import static io.ballerina.runtime.internal.errors.ErrorReasons.INVALID_UPDATE_ERROR_IDENTIFIER; import static io.ballerina.runtime.internal.errors.ErrorReasons.MAP_KEY_NOT_FOUND_ERROR; import static io.ballerina.runtime.internal.errors.ErrorReasons.getModulePrefixedReason; +import static io.ballerina.runtime.internal.util.RuntimeUtils.getEffectiveType; import static io.ballerina.runtime.internal.util.StringUtils.getExpressionStringVal; import static io.ballerina.runtime.internal.util.StringUtils.getStringVal; import static io.ballerina.runtime.internal.values.ReadOnlyUtils.handleInvalidUpdate; @@ -303,8 +304,8 @@ public void populateInitialValue(K key, V value) { putValue(key, value); } else { BString fieldName = (BString) key; - if (MapUtils.handleInherentTypeViolatingRecordUpdate(this, fieldName, value, (BRecordType) referredType, - true)) { + if (MapUtils.handleInherentTypeViolatingRecordUpdate(this, fieldName, value, + (BRecordType) getEffectiveType(referredType), true)) { putValue(key, value); } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java index 6d014bcf16ed..10a1899a1dac 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java @@ -28,11 +28,13 @@ import io.ballerina.runtime.api.values.BTypedesc; import io.ballerina.runtime.internal.scheduling.Strand; import io.ballerina.runtime.internal.types.BAnnotatableType; +import io.ballerina.runtime.internal.types.BTypeReferenceType; import io.ballerina.runtime.internal.types.BTypedescType; import java.util.Map; import static io.ballerina.runtime.api.utils.TypeUtils.getImpliedType; +import static io.ballerina.runtime.internal.util.RuntimeUtils.getEffectiveType; /** *

@@ -102,6 +104,11 @@ public Object instantiate(Strand s, BInitialValueEntry[] initialValues) { } else if (referredType.getTag() == TypeTags.TUPLE_TAG) { return new TupleValueImpl(this.describingType, (BListInitialValueEntry[]) initialValues, this); } + Type effectiveType = getEffectiveType(referredType); + if (effectiveType.getTag() == TypeTags.TUPLE_TAG) { + return new TupleValueImpl(new BTypeReferenceType(effectiveType, true), + (BListInitialValueEntry[]) initialValues); + } // This method will be overridden for user-defined types, therefore this line shouldn't be reached. throw ErrorCreator.createError(StringUtils.fromString( "Given type can't be instantiated at runtime : " + this.describingType)); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java index da3c31f9d93b..dcdf43376d8b 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java @@ -98,6 +98,7 @@ import org.wso2.ballerinalang.compiler.tree.BLangResourceFunction; import org.wso2.ballerinalang.compiler.tree.BLangService; import org.wso2.ballerinalang.compiler.tree.BLangSimpleVariable; +import org.wso2.ballerinalang.compiler.tree.BLangTableKeyTypeConstraint; import org.wso2.ballerinalang.compiler.tree.BLangTypeDefinition; import org.wso2.ballerinalang.compiler.tree.BLangVariable; import org.wso2.ballerinalang.compiler.tree.BLangXMLNS; @@ -188,8 +189,23 @@ import org.wso2.ballerinalang.compiler.tree.statements.BLangStatement; import org.wso2.ballerinalang.compiler.tree.statements.BLangWhile; import org.wso2.ballerinalang.compiler.tree.statements.BLangXMLNSStatement; +import org.wso2.ballerinalang.compiler.tree.types.BLangArrayType; +import org.wso2.ballerinalang.compiler.tree.types.BLangBuiltInRefTypeNode; +import org.wso2.ballerinalang.compiler.tree.types.BLangConstrainedType; +import org.wso2.ballerinalang.compiler.tree.types.BLangErrorType; +import org.wso2.ballerinalang.compiler.tree.types.BLangFiniteTypeNode; +import org.wso2.ballerinalang.compiler.tree.types.BLangFunctionTypeNode; +import org.wso2.ballerinalang.compiler.tree.types.BLangIntersectionTypeNode; +import org.wso2.ballerinalang.compiler.tree.types.BLangObjectTypeNode; +import org.wso2.ballerinalang.compiler.tree.types.BLangRecordTypeNode; +import org.wso2.ballerinalang.compiler.tree.types.BLangStreamType; import org.wso2.ballerinalang.compiler.tree.types.BLangStructureTypeNode; +import org.wso2.ballerinalang.compiler.tree.types.BLangTableTypeNode; +import org.wso2.ballerinalang.compiler.tree.types.BLangTupleTypeNode; import org.wso2.ballerinalang.compiler.tree.types.BLangType; +import org.wso2.ballerinalang.compiler.tree.types.BLangUnionTypeNode; +import org.wso2.ballerinalang.compiler.tree.types.BLangUserDefinedType; +import org.wso2.ballerinalang.compiler.tree.types.BLangValueType; import org.wso2.ballerinalang.compiler.util.BArrayState; import org.wso2.ballerinalang.compiler.util.ClosureVarSymbol; import org.wso2.ballerinalang.compiler.util.CompilerContext; @@ -249,6 +265,9 @@ public class BIRGen extends BLangNodeVisitor { // This map is used to create dependencies for imported module global variables private Map dummyGlobalVarMapForLocks = new HashMap<>(); + private Map localTypedescMap = new HashMap<>(); + private Map globalTypedescMap = new HashMap<>(); + // This is to cache the lockstmt to BIR Lock private Map lockStmtMap = new HashMap<>(); @@ -577,6 +596,9 @@ public void visit(BLangFunction astFunc) { this.env.unlockVars.push(new BIRLockDetailsHolder()); Name funcName; + List requiredParams = astFunc.requiredParams; + BLangSimpleVariable restParam = astFunc.restParam; + BLangType returnTypeNode = astFunc.returnTypeNode; if (isTypeAttachedFunction) { funcName = names.fromString(astFunc.symbol.name.value); } else { @@ -614,12 +636,11 @@ public void visit(BLangFunction astFunc) { // Populate annotation attachments on return type BTypeSymbol tsymbol = astFunc.symbol.type.tsymbol; - if (astFunc.returnTypeNode != null && tsymbol != null) { + if (returnTypeNode != null && tsymbol != null) { birFunc.returnTypeAnnots.addAll(getBIRAnnotAttachments(((BInvokableTypeSymbol) tsymbol).returnTypeAnnots)); } - birFunc.argsCount = astFunc.requiredParams.size() - + (astFunc.restParam != null ? 1 : 0) + astFunc.paramClosureMap.size(); + birFunc.argsCount = requiredParams.size() + (restParam != null ? 1 : 0) + astFunc.paramClosureMap.size(); if (astFunc.flagSet.contains(Flag.ATTACHED) && typeDefs.containsKey(astFunc.receiver.getBType().tsymbol)) { typeDefs.get(astFunc.receiver.getBType().tsymbol).attachedFuncs.add(birFunc); } else { @@ -639,9 +660,9 @@ public void visit(BLangFunction astFunc) { astFunc.paramClosureMap.forEach((k, v) -> addRequiredParam(birFunc, v, astFunc.pos)); // Create variable declaration for function params - astFunc.requiredParams.forEach(requiredParam -> addParam(birFunc, requiredParam)); - if (astFunc.restParam != null) { - addRestParam(birFunc, astFunc.restParam.symbol, astFunc.restParam.pos); + requiredParams.forEach(requiredParam -> addParam(birFunc, requiredParam)); + if (restParam != null) { + addRestParam(birFunc, restParam.symbol, restParam.pos); } if (astFunc.flagSet.contains(Flag.RESOURCE)) { @@ -694,8 +715,9 @@ public void visit(BLangFunction astFunc) { this.env.enclBasicBlocks = birFunc.basicBlocks; birFunc.basicBlocks.add(entryBB); this.env.enclBB = entryBB; + this.localTypedescMap = new HashMap<>(); addToTrapStack(entryBB); - + analyzeParametersAndReturnType(requiredParams, restParam, returnTypeNode); astFunc.body.accept(this); birFunc.basicBlocks.add(this.env.returnBB); @@ -728,6 +750,26 @@ private BIRVariableDcl getSelf(BSymbol receiver) { return self; } + private void analyzeParametersAndReturnType(List requiredParams, BLangVariable restParam, + BLangType returnTypeNode) { + BLangType typeNode; + for (BLangSimpleVariable parameter : requiredParams) { + typeNode = parameter.typeNode; + if (typeNode != null) { + typeNode.accept(this); + } + } + if (restParam != null) { + typeNode = restParam.typeNode; + if (typeNode != null) { + typeNode.accept(this); + } + } + if (returnTypeNode != null) { + returnTypeNode.accept(this); + } + } + @Override public void visit(BLangBlockFunctionBody astBody) { BIRBasicBlock endLoopEndBB = this.env.enclLoopEndBB; @@ -1054,12 +1096,18 @@ public void visit(BLangSimpleVariableDef astVarDefStmt) { birVarDcl.insScope = newScope; this.currentScope = newScope; - if (astVarDefStmt.var.expr == null) { + BLangSimpleVariable simpleVariable = astVarDefStmt.var; + BLangType typeNode = simpleVariable.typeNode; + if (typeNode != null) { + typeNode.accept(this); + } + + if (simpleVariable.expr == null) { return; } // Visit the rhs expression. - astVarDefStmt.var.expr.accept(this); + simpleVariable.expr.accept(this); // Create a variable reference and BIROperand varRef = new BIROperand(birVarDcl); @@ -1069,6 +1117,10 @@ public void visit(BLangSimpleVariableDef astVarDefStmt) { @Override public void visit(BLangSimpleVariable varNode) { + BLangType typeNode = varNode.typeNode; + if (typeNode != null) { + typeNode.accept(this); + } String name = ANNOTATION_DATA.equals(varNode.symbol.name.value) ? ANNOTATION_DATA : varNode.name.value; String originalName = ANNOTATION_DATA.equals(varNode.symbol.getOriginalName().value) ? ANNOTATION_DATA : varNode.name.originalValue; @@ -1087,6 +1139,125 @@ public void visit(BLangSimpleVariable varNode) { env.enclPkg.isListenerAvailable |= Symbols.isFlagOn(varNode.symbol.flags, Flags.LISTENER); } + @Override + public void visit(BLangUserDefinedType userDefinedType) { + } + + @Override + public void visit(BLangTupleTypeNode tupleTypeNode) { + BType type = tupleTypeNode.getBType(); + createNewTypedescInst(type, tupleTypeNode.pos); + BLangType typeNode; + for (BLangSimpleVariable member : tupleTypeNode.members) { + typeNode = member.typeNode; + if (member.typeNode != null) { + typeNode.accept(this); + } + } + typeNode = tupleTypeNode.restParamType; + if (typeNode != null) { + typeNode.accept(this); + } + } + + @Override + public void visit(BLangValueType valueType) { + } + + @Override + public void visit(BLangUnionTypeNode unionTypeNode) { + } + + @Override + public void visit(BLangRecordTypeNode recordTypeNode) { + BType type = recordTypeNode.getBType(); + createNewTypedescInst(type, recordTypeNode.pos); + BLangType typeNode; + for (BLangSimpleVariable field : recordTypeNode.fields) { + typeNode = field.typeNode; + if (typeNode != null) { + typeNode.accept(this); + } + } + typeNode = recordTypeNode.restFieldType; + if (typeNode != null) { + typeNode.accept(this); + } + } + + @Override + public void visit(BLangArrayType arrayType) { + arrayType.elemtype.accept(this); + } + + @Override + public void visit(BLangConstrainedType constrainedType) { + constrainedType.constraint.accept(this); + } + + @Override + public void visit(BLangErrorType errorType) { + if (errorType.detailType != null) { + errorType.detailType.accept(this); + } + } + + @Override + public void visit(BLangFunctionTypeNode functionTypeNode) { + analyzeParametersAndReturnType(functionTypeNode.params, functionTypeNode.restParam, + functionTypeNode.returnTypeNode); + } + + @Override + public void visit(BLangBuiltInRefTypeNode builtInRefTypeNode) { + } + + @Override + public void visit(BLangTableTypeNode tableTypeNode) { + tableTypeNode.constraint.accept(this); + BLangTableKeyTypeConstraint tableKeyTypeConstraint = tableTypeNode.tableKeyTypeConstraint; + if (tableKeyTypeConstraint != null) { + tableKeyTypeConstraint.accept(this); + } + } + + @Override + public void visit(BLangStreamType streamType) { + streamType.type.accept(this); + streamType.constraint.accept(this); + BLangType error = streamType.error; + if (error != null) { + error.accept(this); + } + } + + @Override + public void visit(BLangTableKeyTypeConstraint keyTypeConstraint) { + keyTypeConstraint.keyType.accept(this); + } + + @Override + public void visit(BLangObjectTypeNode objectTypeNode) { + for (BLangSimpleVariable field : objectTypeNode.fields) { + BLangType typeNode = field.typeNode; + if (typeNode != null) { + typeNode.accept(this); + } + } + } + + @Override + public void visit(BLangFiniteTypeNode finiteTypeNode) { + } + + @Override + public void visit(BLangIntersectionTypeNode intersectionTypeNode) { + BType effectiveType = Types.getImpliedType(intersectionTypeNode.getBType()); + if (effectiveType.tag == TypeTags.RECORD || effectiveType.tag == TypeTags.TUPLE) { + createNewTypedescInst(effectiveType, intersectionTypeNode.pos); + } + } + @Override public void visit(BLangAssignment astAssignStmt) { astAssignStmt.expr.accept(this); @@ -1550,15 +1721,14 @@ public void visit(BLangLiteral astLiteralExpr) { @Override public void visit(BLangMapLiteral astMapLiteralExpr) { this.env.isInArrayOrStructure++; - visitTypedesc(astMapLiteralExpr.pos, astMapLiteralExpr.getBType(), Collections.emptyList()); + BType type = astMapLiteralExpr.getBType(); BIRVariableDcl tempVarDcl = - new BIRVariableDcl(astMapLiteralExpr.getBType(), this.env.nextLocalVarId(names), + new BIRVariableDcl(type, this.env.nextLocalVarId(names), VarScope.FUNCTION, VarKind.TEMP); this.env.enclFunc.localVars.add(tempVarDcl); BIROperand toVarRef = new BIROperand(tempVarDcl); - - setScopeAndEmit(new BIRNonTerminator.NewStructure(astMapLiteralExpr.pos, toVarRef, this.env.targetOperand, - generateMappingConstructorEntries(astMapLiteralExpr.fields))); + setScopeAndEmit(createNewStructureInst(generateMappingConstructorEntries(astMapLiteralExpr.fields), toVarRef, + Types.getImpliedType(type), astMapLiteralExpr.pos)); this.env.targetOperand = toVarRef; this.env.isInArrayOrStructure--; } @@ -1582,26 +1752,35 @@ public void visit(BLangTypeConversionExpr astTypeConversionExpr) { @Override public void visit(BLangStructLiteral astStructLiteralExpr) { this.env.isInArrayOrStructure++; - List varDcls = mapToVarDcls(astStructLiteralExpr.enclMapSymbols); - BType type = astStructLiteralExpr.getBType(); - visitTypedesc(astStructLiteralExpr.pos, type, varDcls); - - BIRVariableDcl tempVarDcl = new BIRVariableDcl(astStructLiteralExpr.getBType(), - this.env.nextLocalVarId(names), VarScope.FUNCTION, VarKind.TEMP); + BType type = Types.getReferredType(astStructLiteralExpr.getBType()); + BIRVariableDcl tempVarDcl = new BIRVariableDcl(type, this.env.nextLocalVarId(names), VarScope.FUNCTION, + VarKind.TEMP); this.env.enclFunc.localVars.add(tempVarDcl); BIROperand toVarRef = new BIROperand(tempVarDcl); - - - BIRNonTerminator.NewStructure instruction = - new BIRNonTerminator.NewStructure(astStructLiteralExpr.pos, toVarRef, this.env.targetOperand, - generateMappingConstructorEntries(astStructLiteralExpr.fields)); - setScopeAndEmit(instruction); + List fields = + generateMappingConstructorEntries(astStructLiteralExpr.fields); + setScopeAndEmit(createNewStructureInst(fields, toVarRef, type, astStructLiteralExpr.pos)); this.env.targetOperand = toVarRef; this.env.isInArrayOrStructure--; } - private List mapToVarDcls(TreeMap enclMapSymbols) { + private BIRNonTerminator.NewStructure createNewStructureInst(List fields, + BIROperand toVarRef, BType type, Location pos) { + if (localTypedescMap.containsKey(type)) { + return new BIRNonTerminator.NewStructure(pos, toVarRef, localTypedescMap.get(type), fields, type); + } else { + createNewTypedescInst(type, pos); + return new BIRNonTerminator.NewStructure(pos, toVarRef, this.env.targetOperand, fields, type); + } + } + + private List mapToVarDcls(BType type) { + BType referredType = Types.getReferredType(type); + if (referredType.tag != TypeTags.RECORD) { + return Collections.emptyList(); + } + TreeMap enclMapSymbols = ((BRecordType) referredType).enclMapSymbols; if (enclMapSymbols == null || enclMapSymbols.size() == 0) { return Collections.emptyList(); } @@ -1646,32 +1825,22 @@ public void visit(BLangSimpleVarRef.BLangFieldVarRef fieldVarRef) { @Override public void visit(BLangArrayLiteral astArrayLiteralExpr) { - BType bType = astArrayLiteralExpr.getBType(); - if (bType.tag == TypeTags.TUPLE) { - visitTypedesc(astArrayLiteralExpr.pos, bType, Collections.emptyList()); - } generateListConstructorExpr(astArrayLiteralExpr); } @Override public void visit(BLangTupleLiteral tupleLiteral) { - BType type = tupleLiteral.getBType(); - visitTypedesc(tupleLiteral.pos, type, Collections.emptyList()); generateListConstructorExpr(tupleLiteral); } @Override - public void visit(BLangGroupExpr groupExpr) { - groupExpr.expression.accept(this); + public void visit(BLangJSONArrayLiteral jsonArrayLiteralExpr) { + generateListConstructorExpr(jsonArrayLiteralExpr); } @Override - public void visit(BLangJSONArrayLiteral jsonArrayLiteralExpr) { - BType bType = jsonArrayLiteralExpr.getBType(); - if (bType.tag == TypeTags.TUPLE) { - visitTypedesc(jsonArrayLiteralExpr.pos, bType, Collections.emptyList()); - } - generateListConstructorExpr(jsonArrayLiteralExpr); + public void visit(BLangGroupExpr groupExpr) { + groupExpr.expression.accept(this); } @Override @@ -1957,14 +2126,13 @@ public void visit(BLangWaitExpr waitExpr) { @Override public void visit(BLangWaitForAllExpr.BLangWaitLiteral waitLiteral) { this.env.isInArrayOrStructure++; - visitTypedesc(waitLiteral.pos, waitLiteral.getBType(), Collections.emptyList()); BIRBasicBlock thenBB = new BIRBasicBlock(this.env.nextBBId()); addToTrapStack(thenBB); BIRVariableDcl tempVarDcl = new BIRVariableDcl(waitLiteral.getBType(), this.env.nextLocalVarId(names), VarScope.FUNCTION, VarKind.TEMP); this.env.enclFunc.localVars.add(tempVarDcl); BIROperand toVarRef = new BIROperand(tempVarDcl); - setScopeAndEmit(new BIRNonTerminator.NewStructure(waitLiteral.pos, toVarRef, this.env.targetOperand)); + setScopeAndEmit(createNewStructureInst(new ArrayList<>(), toVarRef, waitLiteral.getBType(), waitLiteral.pos)); this.env.targetOperand = toVarRef; List keys = new ArrayList<>(); @@ -2172,9 +2340,8 @@ public void visit(BLangXMLAccessExpr xmlAccessExpr) { @Override public void visit(BLangTypedescExpr accessExpr) { - BIRVariableDcl tempVarDcl = - new BIRVariableDcl(accessExpr.getBType(), this.env.nextLocalVarId(names), VarScope.FUNCTION, - VarKind.TEMP); + BIRVariableDcl tempVarDcl = new BIRVariableDcl(accessExpr.getBType(), this.env.nextLocalVarId(names), + VarScope.FUNCTION, VarKind.TEMP); this.env.enclFunc.localVars.add(tempVarDcl); BIROperand toVarRef = new BIROperand(tempVarDcl); setScopeAndEmit(new BIRNonTerminator.NewTypeDesc(accessExpr.pos, toVarRef, accessExpr.resolvedType, @@ -2228,23 +2395,39 @@ public void visit(BLangTableConstructorExpr tableConstructorExpr) { public void visit(BLangSimpleVarRef.BLangTypeLoad typeLoad) { BType type = typeLoad.symbol.tag == SymTag.TYPE_DEF ? ((BTypeDefinitionSymbol) typeLoad.symbol).referenceType : typeLoad.symbol.type; - visitTypedesc(typeLoad.pos, type, Collections.emptyList()); + createNewTypedescInst(type, typeLoad.pos); } - private void visitTypedesc(Location pos, BType type, List varDcls) { - BIRVariableDcl tempVarDcl = new BIRVariableDcl(symTable.typeDesc, this.env.nextLocalVarId(names), - VarScope.FUNCTION, VarKind.TEMP); - BIRGenEnv env = this.env; - env.enclFunc.localVars.add(tempVarDcl); - BIROperand toVarRef = new BIROperand(tempVarDcl); - BIROperand annotations = getAnnotations(type.tsymbol, env); - if (annotations != null) { - setScopeAndEmit(new BIRNonTerminator.NewTypeDesc(pos, toVarRef, type, varDcls, annotations)); - env.targetOperand = toVarRef; + private void createNewTypedescInst(BType type, Location position) { + if (this.env.enclFunc == null) { return; } - setScopeAndEmit(new BIRNonTerminator.NewTypeDesc(pos, toVarRef, type, varDcls)); - env.targetOperand = toVarRef; + List varDcls = mapToVarDcls(type); + BTypeSymbol typeSymbol = type.tsymbol; + BIRVariableDcl tempVarDcl; + BIROperand toVarRef; + BIRNonTerminator.NewTypeDesc newTypeDesc; + tempVarDcl = + new BIRVariableDcl(symTable.typeDesc, this.env.nextLocalVarId(names), VarScope.FUNCTION, VarKind.TEMP); + this.env.enclFunc.localVars.add(tempVarDcl); + toVarRef = new BIROperand(tempVarDcl); + BIRVariableDcl annotationVarDcl = new BIRVariableDcl(symTable.mapType, this.env.nextLocalVarId(names), + VarScope.FUNCTION, VarKind.TEMP); + this.env.enclFunc.localVars.add(annotationVarDcl); + if (typeSymbol != null && typeSymbol.annotations != null) { + if (this.env.symbolVarMap.containsKey(typeSymbol.annotations)) { + newTypeDesc = new BIRNonTerminator.NewTypeDesc(position, toVarRef, type, varDcls, + new BIROperand(this.env.symbolVarMap.get(typeSymbol.annotations))); + } else { + newTypeDesc = new BIRNonTerminator.NewTypeDesc(position, toVarRef, type, varDcls, + new BIROperand(this.globalVarMap.get(typeSymbol.annotations))); + } + } else { + newTypeDesc = new BIRNonTerminator.NewTypeDesc(position, toVarRef, type, varDcls); + } + this.env.targetOperand = toVarRef; + setScopeAndEmit(newTypeDesc); + localTypedescMap.put(type, toVarRef); } @Override @@ -2670,20 +2853,19 @@ private void generateListConstructorExpr(BLangListConstructorExpr listConstructo BIROperand toVarRef = new BIROperand(tempVarDcl); long size = -1L; - BIROperand typedescOp = null; List exprs = listConstructorExpr.exprs; - BType listConstructorExprType = listConstructorExpr.getBType(); - BType referredType = Types.getImpliedType(listConstructorExprType); + BType type = listConstructorExpr.getBType(); + BType referredType = Types.getImpliedType(type); if (referredType.tag == TypeTags.ARRAY && ((BArrayType) referredType).state != BArrayState.OPEN) { size = ((BArrayType) referredType).size; } else if (referredType.tag == TypeTags.TUPLE) { - typedescOp = this.env.targetOperand; size = exprs.size(); } BLangLiteral literal = new BLangLiteral(); - literal.pos = listConstructorExpr.pos; + Location pos = listConstructorExpr.pos; + literal.pos = pos; literal.value = size; literal.setBType(symTable.intType); literal.accept(this); @@ -2701,18 +2883,26 @@ private void generateListConstructorExpr(BLangListConstructorExpr listConstructo initialValues.add(new BIRNode.BIRListConstructorExprEntry(this.env.targetOperand)); } } + setScopeAndEmit(createNewArrayInst(initialValues, type, sizeOp, toVarRef, referredType, pos)); + this.env.targetOperand = toVarRef; + this.env.isInArrayOrStructure--; + } + private BIRNonTerminator.NewArray createNewArrayInst(List initialValues, + BType listConstructorExprType, BIROperand sizeOp, + BIROperand toVarRef, BType referredType, Location pos) { if (referredType.tag == TypeTags.TUPLE) { - setScopeAndEmit( - new BIRNonTerminator.NewArray(listConstructorExpr.pos, listConstructorExprType, toVarRef, - typedescOp, sizeOp, initialValues)); + if (localTypedescMap.containsKey(referredType)) { + return new BIRNonTerminator.NewArray(pos, listConstructorExprType, toVarRef, + localTypedescMap.get(referredType), sizeOp, initialValues); + } else { + createNewTypedescInst(referredType, pos); + return new BIRNonTerminator.NewArray(pos, listConstructorExprType, toVarRef, + localTypedescMap.get(referredType), sizeOp, initialValues); + } } else { - setScopeAndEmit( - new BIRNonTerminator.NewArray(listConstructorExpr.pos, listConstructorExprType, toVarRef, sizeOp, - initialValues)); + return new BIRNonTerminator.NewArray(pos, listConstructorExprType, toVarRef, sizeOp, initialValues); } - this.env.targetOperand = toVarRef; - this.env.isInArrayOrStructure--; } private void generateArrayAccess(BLangIndexBasedAccess astArrayAccessExpr) { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGenEnv.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGenEnv.java index 2ddf4a1b69c5..a9b4437d3ecc 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGenEnv.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGenEnv.java @@ -50,6 +50,7 @@ class BIRGenEnv { Map symbolVarMap = new HashMap<>(); private int currentBBId = -1; private int currentLocalVarId = -1; + private int currentTypedescId = -1; private int currentLambdaVarId = -1; BIRBasicBlock enclBB; @@ -89,6 +90,11 @@ Name nextLocalVarId(Names names) { return names.merge(Names.BIR_LOCAL_VAR_PREFIX, names.fromString(Integer.toString(currentLocalVarId))); } + Name nextTypedescId(Names names) { + currentTypedescId++; + return names.merge(Names.TYPEDESC, Names.fromString(Integer.toString(currentTypedescId))); + } + Name nextLambdaVarId(Names names) { currentLambdaVarId++; return names.merge(Names.BIR_LOCAL_VAR_PREFIX, names.fromString(Integer.toString(currentLambdaVarId))); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmConstants.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmConstants.java index b0d9a5c91e8d..dd97ba0c4ba3 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmConstants.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmConstants.java @@ -367,6 +367,7 @@ public class JvmConstants { public static final String CREATE_TYPES_METHOD = "$createTypes"; public static final String CREATE_TYPE_CONSTANTS_METHOD = "$createTypeConstants"; public static final String CREATE_TYPE_INSTANCES_METHOD = "$createTypeInstances"; + public static final String CREATE_TYPEDESC_INSTANCES_METHOD = "$createTypedescInstances"; public static final String GLOBAL_LOCK_NAME = "lock"; public static final String SERVICE_EP_AVAILABLE = "$serviceEPAvailable"; public static final String LOCK_STORE_VAR_NAME = "$LOCK_STORE"; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmInstructionGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmInstructionGen.java index f92ebdd2de34..b6f874635dd8 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmInstructionGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmInstructionGen.java @@ -48,7 +48,6 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BIntersectionType; import org.wso2.ballerinalang.compiler.semantics.model.types.BObjectType; import org.wso2.ballerinalang.compiler.semantics.model.types.BType; -import org.wso2.ballerinalang.compiler.semantics.model.types.BTypeReferenceType; import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.util.Flags; @@ -626,7 +625,8 @@ private void generateJLargeArrayIns(int localVarOffset, JLargeArrayInstruction i BType elementType = JvmCodeGenUtil.getImpliedType(((BArrayType) instType).eType); if (elementType.tag == TypeTags.RECORD || (elementType.tag == TypeTags.INTERSECTION && ((BIntersectionType) elementType).effectiveType.tag == TypeTags.RECORD)) { - visitNewRecordArray(elementType); + // TODO: +// visitNewRecordArray(elementType); } else { this.mv.visitMethodInsn(INVOKESPECIAL, ARRAY_VALUE_IMPL, JVM_INIT_METHOD, INIT_ARRAY, false); @@ -1369,8 +1369,15 @@ private int getJVMIndexOfVarRef(BIRNode.BIRVariableDcl varDcl) { } void generateMapNewIns(BIRNonTerminator.NewStructure mapNewIns, int localVarOffset) { - - this.loadVar(mapNewIns.rhsOp.variableDcl); + BType type = mapNewIns.type; + if (Types.isUserDefinedTypeDefinition(type)) { + PackageID packageID = type.tsymbol.pkgID; + String typeOwner = JvmCodeGenUtil.getPackageName(packageID) + MODULE_INIT_CLASS_NAME; + String fieldName = jvmTypeGen.getTypedescFieldName(toNameString(type)); + mv.visitFieldInsn(GETSTATIC, typeOwner, fieldName, GET_TYPEDESC); + } else { + this.loadVar(mapNewIns.rhsOp.variableDcl); + } this.mv.visitVarInsn(ALOAD, localVarOffset); List initialValues = mapNewIns.initialValues; @@ -1561,14 +1568,21 @@ void generateArrayNewIns(BIRNonTerminator.NewArray inst, int localVarOffset) { BType elementType = JvmCodeGenUtil.getImpliedType(((BArrayType) instType).eType); if (elementType.tag == TypeTags.RECORD) { - visitNewRecordArray(elementType); + visitNewRecordArray(elementType, inst); } else { this.mv.visitMethodInsn(INVOKESPECIAL, ARRAY_VALUE_IMPL, JVM_INIT_METHOD, INIT_ARRAY, false); } this.storeToVar(inst.lhsOp.variableDcl); } else { - this.loadVar(inst.typedescOp.variableDcl); + if (Types.isUserDefinedTypeDefinition(instType)) { + PackageID packageID = instType.tsymbol.pkgID; + String typeOwner = JvmCodeGenUtil.getPackageName(packageID) + MODULE_INIT_CLASS_NAME; + String fieldName = jvmTypeGen.getTypedescFieldName(toNameString(instType)); + mv.visitFieldInsn(GETSTATIC, typeOwner, fieldName, GET_TYPEDESC); + } else { + this.loadVar(inst.typedescOp.variableDcl); + } this.mv.visitVarInsn(ALOAD, localVarOffset); loadListInitialValues(inst); this.mv.visitMethodInsn(INVOKEINTERFACE, TYPEDESC_VALUE, INSTANTIATE_FUNCTION, INSTANTIATE, true); @@ -1576,12 +1590,17 @@ void generateArrayNewIns(BIRNonTerminator.NewArray inst, int localVarOffset) { } } - private void visitNewRecordArray(BType type) { + private void visitNewRecordArray(BType type, BIRNonTerminator.NewArray inst) { BType elementType = JvmCodeGenUtil.getImpliedType(type); - String typeOwner = JvmCodeGenUtil.getPackageName(type.tsymbol.pkgID) + MODULE_INIT_CLASS_NAME; - String typedescFieldName = - jvmTypeGen.getTypedescFieldName(toNameString(elementType)); - this.mv.visitFieldInsn(GETSTATIC, typeOwner, typedescFieldName, "L" + TYPEDESC_VALUE + ";"); + elementType = elementType.tag == TypeTags.INTERSECTION ? + ((BIntersectionType) elementType).effectiveType : elementType; + if (inst.typedescOp == null) { + String typeOwner = JvmCodeGenUtil.getPackageName(type.tsymbol.pkgID) + MODULE_INIT_CLASS_NAME; + String typedescFieldName = jvmTypeGen.getTypedescFieldName(toNameString(elementType)); + this.mv.visitFieldInsn(GETSTATIC, typeOwner, typedescFieldName, "L" + TYPEDESC_VALUE + ";"); + } else { + this.loadVar(inst.typedescOp.variableDcl); + } this.mv.visitMethodInsn(INVOKESPECIAL, ARRAY_VALUE_IMPL, JVM_INIT_METHOD, INIT_ARRAY_WITH_INITIAL_VALUES, false); } @@ -2130,11 +2149,12 @@ void generateNegateIns(BIRNonTerminator.UnaryOP unaryOp) { void generateNewTypedescIns(BIRNonTerminator.NewTypeDesc newTypeDesc) { List closureVars = newTypeDesc.closureVars; - if (isNonReferredRecord(newTypeDesc.type)) { - BType type = JvmCodeGenUtil.getImpliedType(newTypeDesc.type); + if (Types.isUserDefinedTypeDefinition(newTypeDesc.type)) { + BType type = newTypeDesc.type; PackageID packageID = type.tsymbol.pkgID; String typeOwner = JvmCodeGenUtil.getPackageName(packageID) + MODULE_INIT_CLASS_NAME; String fieldName = jvmTypeGen.getTypedescFieldName(toNameString(type)); + createTypedescInstance(mv, newTypeDesc.type, newTypeDesc, typeOwner); mv.visitFieldInsn(GETSTATIC, typeOwner, fieldName, GET_TYPEDESC); } else { generateNewTypedescCreate(newTypeDesc.type, closureVars, newTypeDesc.annotations); @@ -2142,13 +2162,31 @@ void generateNewTypedescIns(BIRNonTerminator.NewTypeDesc newTypeDesc) { this.storeToVar(newTypeDesc.lhsOp.variableDcl); } - private boolean isNonReferredRecord(BType type) { - if (type.tag != TypeTags.TYPEREFDESC) { - return false; + private void createTypedescInstance(MethodVisitor mv, BType bType, BIRNonTerminator.NewTypeDesc typedesc, + String moduleInitClass) { + String className; + BType effectiveType = JvmCodeGenUtil.getImpliedType(bType); + if (bType.tag == TypeTags.RECORD) { + PackageID pkgID = bType.tsymbol.pkgID; + String packageName = JvmCodeGenUtil.getPackageName(pkgID); + className = getTypeDescClassName(packageName, toNameString(bType)); + } else if (effectiveType.tag == TypeTags.TUPLE) { + bType = effectiveType; + className = TYPEDESC_VALUE_IMPL; + } else { + return; } - BType referredType = ((BTypeReferenceType) type).referredType; - return referredType.tag == TypeTags.RECORD && - type.getQualifiedTypeName().equals(referredType.getQualifiedTypeName()); + + mv.visitTypeInsn(NEW, className); + mv.visitInsn(DUP); + jvmTypeGen.loadType(mv, JvmCodeGenUtil.getImpliedType(bType)); + + mv.visitInsn(ACONST_NULL); + String constructorDesc = + typedesc.annotations != null ? TYPE_DESC_CONSTRUCTOR_WITH_ANNOTATIONS : TYPE_DESC_CONSTRUCTOR; + mv.visitMethodInsn(INVOKESPECIAL, className, JVM_INIT_METHOD, constructorDesc, false); + mv.visitFieldInsn(PUTSTATIC, moduleInitClass, + jvmTypeGen.getTypedescFieldName(typedesc.type.tsymbol.name.getValue()), GET_TYPEDESC); } private void generateNewTypedescCreate(BType btype, List closureVars, BIROperand annotations) { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTypeGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTypeGen.java index 205bc5b5779e..d2bcf41cd402 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTypeGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTypeGen.java @@ -32,6 +32,7 @@ import org.wso2.ballerinalang.compiler.semantics.analyzer.IsAnydataUniqueVisitor; import org.wso2.ballerinalang.compiler.semantics.analyzer.IsPureTypeUniqueVisitor; import org.wso2.ballerinalang.compiler.semantics.analyzer.TypeHashVisitor; +import org.wso2.ballerinalang.compiler.semantics.analyzer.Types; import org.wso2.ballerinalang.compiler.semantics.model.SymbolTable; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableTypeSymbol; @@ -227,15 +228,14 @@ public JvmTypeGen(JvmConstantsGen jvmConstantsGen, PackageID packageID, TypeHash void generateUserDefinedTypeFields(ClassWriter cw, List typeDefs) { // create the type for (BIRTypeDefinition typeDef : typeDefs) { - BType bType = typeDef.type; - int bTypeTag = bType.tag; - if (JvmCodeGenUtil.needNoTypeGeneration(bTypeTag)) { - // do not generate anything for other types (e.g.: finite type, type reference types etc.) - continue; + BType bType = JvmCodeGenUtil.getImpliedType(typeDef.type); + if (bType.tag == TypeTags.RECORD || bType.tag == TypeTags.ERROR || bType.tag == TypeTags.OBJECT + || bType.tag == TypeTags.UNION || Types.getImpliedType(bType).tag == TypeTags.TUPLE) { + String name = typeDef.internalName.value; + generateTypeField(cw, name); + generateTypedescField(cw, name); } - String name = typeDef.internalName.value; - generateTypeField(cw, name); - generateTypedescField(cw, name); + // do not generate anything for other types (e.g.: finite type, unions, etc.) } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/JvmCreateTypeGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/JvmCreateTypeGen.java index 0bca9e875dd0..443456094aff 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/JvmCreateTypeGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/JvmCreateTypeGen.java @@ -38,6 +38,7 @@ import org.wso2.ballerinalang.compiler.bir.codegen.split.types.JvmUnionTypeGen; import org.wso2.ballerinalang.compiler.bir.model.BIRNode; import org.wso2.ballerinalang.compiler.bir.model.BIRNode.BIRTypeDefinition; +import org.wso2.ballerinalang.compiler.bir.model.BIRNonTerminator; import org.wso2.ballerinalang.compiler.parser.BLangAnonymousModelHelper; import org.wso2.ballerinalang.compiler.semantics.analyzer.TypeHashVisitor; import org.wso2.ballerinalang.compiler.semantics.analyzer.Types; @@ -51,6 +52,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BTupleType; import org.wso2.ballerinalang.compiler.semantics.model.types.BType; import org.wso2.ballerinalang.compiler.semantics.model.types.BTypeIdSet; +import org.wso2.ballerinalang.compiler.semantics.model.types.BTypeReferenceType; import org.wso2.ballerinalang.compiler.semantics.model.types.BUnionType; import org.wso2.ballerinalang.compiler.semantics.model.types.NamedNode; import org.wso2.ballerinalang.compiler.util.TypeTags; @@ -72,8 +74,11 @@ import static org.objectweb.asm.Opcodes.ACC_PUBLIC; import static org.objectweb.asm.Opcodes.ACC_STATIC; import static org.objectweb.asm.Opcodes.ACC_SUPER; +import static org.objectweb.asm.Opcodes.ACONST_NULL; import static org.objectweb.asm.Opcodes.ALOAD; +import static org.objectweb.asm.Opcodes.ANEWARRAY; import static org.objectweb.asm.Opcodes.ARETURN; +import static org.objectweb.asm.Opcodes.BIPUSH; import static org.objectweb.asm.Opcodes.DUP; import static org.objectweb.asm.Opcodes.GETSTATIC; import static org.objectweb.asm.Opcodes.GOTO; @@ -91,7 +96,9 @@ import static org.objectweb.asm.Opcodes.RETURN; import static org.objectweb.asm.Opcodes.V17; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmCodeGenUtil.createDefaultCase; +import static org.wso2.ballerinalang.compiler.bir.codegen.JvmCodeGenUtil.getImpliedType; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmCodeGenUtil.getModuleLevelClassName; +import static org.wso2.ballerinalang.compiler.bir.codegen.JvmCodeGenUtil.toNameString; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.ADD_METHOD; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.B_ARRAY_TYPE_INIT_METHOD; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.B_ARRAY_TYPE_POPULATE_METHOD; @@ -103,6 +110,7 @@ import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.B_TYPEREF_TYPE_POPULATE_METHOD; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.B_UNION_TYPE_INIT_METHOD; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.B_UNION_TYPE_POPULATE_METHOD; +import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.CREATE_TYPEDESC_INSTANCES_METHOD; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.CREATE_TYPES_METHOD; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.CREATE_TYPE_CONSTANTS_METHOD; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.CREATE_TYPE_INSTANCES_METHOD; @@ -110,6 +118,7 @@ import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.GET_ANON_TYPE_METHOD; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.JVM_INIT_METHOD; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.MAP; +import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.MAP_VALUE; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.MAX_FIELDS_PER_SPLIT_METHOD; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.MAX_TYPES_PER_METHOD; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.MODULE_ANON_TYPES_CLASS_NAME; @@ -119,17 +128,22 @@ import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.SET_IMMUTABLE_TYPE_METHOD; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.STRING_VALUE; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.TYPE; +import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.TYPEDESC_VALUE_IMPL; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.TYPE_ID_SET; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.VISIT_MAX_SAFE_MARGIN; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.ADD_TYPE_ID; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.ANY_TO_JBOOLEAN; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.GET_TYPE; +import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.GET_TYPEDESC; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INIT_FIELD_IMPL; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.MAP_PUT; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.SET_IMMUTABLE_TYPE; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.SET_LINKED_HASH_MAP; +import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.TYPE_DESC_CONSTRUCTOR; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.VOID_METHOD_DESC; +import static org.wso2.ballerinalang.compiler.bir.codegen.JvmTypeGen.getTypeDesc; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmTypeGen.getTypeFieldName; +import static org.wso2.ballerinalang.compiler.bir.codegen.JvmValueGen.getTypeDescClassName; /** * BIR types to JVM byte code generation class. @@ -152,11 +166,13 @@ public class JvmCreateTypeGen { private final String typesClass; private final String anonTypesClass; private final ClassWriter typesCw; + private final JvmPackageGen jvmPackageGen; public JvmCreateTypeGen(JvmTypeGen jvmTypeGen, JvmConstantsGen jvmConstantsGen, PackageID packageID, - TypeHashVisitor typeHashVisitor) { + TypeHashVisitor typeHashVisitor, JvmPackageGen jvmPackageGen) { this.jvmTypeGen = jvmTypeGen; this.jvmConstantsGen = jvmConstantsGen; + this.jvmPackageGen = jvmPackageGen; this.typesClass = getModuleLevelClassName(packageID, MODULE_TYPES_CLASS_NAME); this.anonTypesClass = getModuleLevelClassName(packageID, MODULE_ANON_TYPES_CLASS_NAME); this.jvmRecordTypeGen = new JvmRecordTypeGen(this, jvmTypeGen, jvmConstantsGen, packageID); @@ -175,7 +191,7 @@ public JvmCreateTypeGen(JvmTypeGen jvmTypeGen, JvmConstantsGen jvmConstantsGen, public void generateTypeClass(JvmPackageGen jvmPackageGen, BIRNode.BIRPackage module, Map jarEntries, String moduleInitClass, SymbolTable symbolTable) { - generateCreateTypesMethod(typesCw, module.typeDefs, moduleInitClass, symbolTable); + generateCreateTypesMethod(typesCw, module.typeDefs, moduleInitClass, symbolTable, module.typedescs); typesCw.visitEnd(); jvmRecordTypeGen.visitEnd(jvmPackageGen, module, jarEntries); jvmObjectTypeGen.visitEnd(jvmPackageGen, module, jarEntries); @@ -215,10 +231,11 @@ void createTypeConstants(ClassWriter cw, String moduleInitClass) { mv.visitEnd(); } - void generateCreateTypesMethod(ClassWriter cw, List typeDefs, - String moduleInitClass, SymbolTable symbolTable) { + void generateCreateTypesMethod(ClassWriter cw, List typeDefs, String moduleInitClass, + SymbolTable symbolTable, List typesecs) { createTypeConstants(cw, moduleInitClass); createTypesInstance(cw, typeDefs, moduleInitClass); + createTypedescInstances(cw, typeDefs, moduleInitClass, typesecs); Map populateTypeFuncNames = populateTypes(cw, typeDefs, moduleInitClass, symbolTable); MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, CREATE_TYPES_METHOD, VOID_METHOD_DESC, null, null); @@ -230,6 +247,9 @@ void generateCreateTypesMethod(ClassWriter cw, List typeDefs, // Invoke create-type-constants method mv.visitMethodInsn(INVOKESTATIC, typesClass, CREATE_TYPE_CONSTANTS_METHOD, VOID_METHOD_DESC, false); + // Invoke create-typedesc-instances method + mv.visitMethodInsn(INVOKESTATIC, typesClass, CREATE_TYPEDESC_INSTANCES_METHOD, "()V", false); + // Invoke the populate-type functions for (Map.Entry entry : populateTypeFuncNames.entrySet()) { String funcName = entry.getKey(); @@ -254,6 +274,85 @@ private void createTypesInstance(ClassWriter cw, List typeDef mv.visitEnd(); } + private void createTypedescInstances(ClassWriter cw, List typeDefs, String moduleInitClass, + List typesecs) { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, CREATE_TYPEDESC_INSTANCES_METHOD, + "()V", null, null); + mv.visitCode(); + for (BIRTypeDefinition typeDefinition : typeDefs) { + BType bType = getImpliedType(typeDefinition.type); + if (bType.tag == TypeTags.RECORD) { + continue; + } + createTypedescInstance(mv, bType, typeDefinition, moduleInitClass); + } + + for (BIRNonTerminator.NewTypeDesc typedesc : typesecs) { + createTypedescInstances(mv, typedesc); + } + mv.visitInsn(RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + + private void createTypedescInstances(MethodVisitor mv, BIRNonTerminator.NewTypeDesc typeDesc) { + BType type = getImpliedType(typeDesc.type); + String className = TYPEDESC_VALUE_IMPL; + if (type.tag == TypeTags.RECORD) { + className = getTypeDescClassName(JvmCodeGenUtil.getPackageName(type.tsymbol.pkgID), toNameString(type)); + } + mv.visitTypeInsn(NEW, className); + mv.visitInsn(DUP); + jvmTypeGen.loadType(mv, typeDesc.type); + mv.visitIntInsn(BIPUSH, typeDesc.closureVars.size()); + mv.visitTypeInsn(ANEWARRAY, MAP_VALUE); + mv.visitMethodInsn(INVOKESPECIAL, className, JVM_INIT_METHOD, TYPE_DESC_CONSTRUCTOR, false); + generateGlobalVarStore(mv, typeDesc.lhsOp.variableDcl); + } + + public void generateGlobalVarStore(MethodVisitor mv, BIRNode.BIRVariableDcl varDcl) { + BType bType = getImpliedType(varDcl.type); + String varName = varDcl.name.value; + PackageID moduleId = ((BIRNode.BIRGlobalVariableDcl) varDcl).pkgId; + String pkgName = JvmCodeGenUtil.getPackageName(moduleId); + String className = jvmPackageGen.lookupGlobalVarClassName(pkgName, varName); + String typeSig = getTypeDesc(bType); + mv.visitFieldInsn(PUTSTATIC, className, varName, typeSig); + } + + private void createTypedescInstance(MethodVisitor mv, BType bType, BIRTypeDefinition typeDefinition, + String moduleInitClass) { + String className; + if (bType.tag == TypeTags.RECORD) { + PackageID pkgID = bType.tsymbol.pkgID; + String packageName = JvmCodeGenUtil.getPackageName(pkgID); + className = getTypeDescClassName(packageName, toNameString(bType)); + } else if (getImpliedType(bType).tag == TypeTags.TUPLE) { + bType = getImpliedType(bType); + className = TYPEDESC_VALUE_IMPL; + } else { + return; + } + + mv.visitTypeInsn(NEW, className); + mv.visitInsn(DUP); + BType referenceType = typeDefinition.referenceType; + if (referenceType == null) { + jvmTypeGen.loadType(mv, getImpliedType(bType)); + } else { + BType referredType = ((BTypeReferenceType) referenceType).referredType; + if (referredType.tag == TypeTags.TYPEREFDESC || bType.tag == TypeTags.TUPLE) { + jvmTypeGen.loadType(mv, referenceType); + } else { + jvmTypeGen.loadType(mv, referredType); + } + } + mv.visitInsn(ACONST_NULL); + mv.visitMethodInsn(INVOKESPECIAL, className, JVM_INIT_METHOD, TYPE_DESC_CONSTRUCTOR, false); + mv.visitFieldInsn(PUTSTATIC, moduleInitClass, + jvmTypeGen.getTypedescFieldName(typeDefinition.internalName.value), GET_TYPEDESC); + } + private int createTypesInstanceSplits(ClassWriter cw, List typeDefs, String typeOwnerClass) { if (typeDefs.isEmpty()) { @@ -266,11 +365,12 @@ private int createTypesInstanceSplits(ClassWriter cw, List ty // Create the type for (BIRTypeDefinition optionalTypeDef : typeDefs) { String name = optionalTypeDef.internalName.value; - BType bType = optionalTypeDef.type; - int bTypeTag = bType.tag; - if (JvmCodeGenUtil.needNoTypeGeneration(bTypeTag)) { - continue; - } else { + BType bType = getImpliedType(optionalTypeDef.type); + if (bType.tag != TypeTags.RECORD && bType.tag != TypeTags.OBJECT && bType.tag != TypeTags.ERROR && + bType.tag != TypeTags.UNION && getImpliedType(bType).tag != TypeTags.TUPLE) { + // do not generate anything for other types (e.g.: finite type, etc.) + continue; + } else { if (bTypesCount % MAX_TYPES_PER_METHOD == 0) { mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, CREATE_TYPE_INSTANCES_METHOD + methodCount++, VOID_METHOD_DESC, @@ -278,9 +378,9 @@ private int createTypesInstanceSplits(ClassWriter cw, List ty mv.visitCode(); } } - switch (bTypeTag) { + switch (getImpliedType(bType).tag) { case TypeTags.RECORD: - jvmRecordTypeGen.createRecordType(mv, (BRecordType) bType, typeOwnerClass, name); + jvmRecordTypeGen.createRecordType(mv, (BRecordType) bType, name); break; case TypeTags.OBJECT: jvmObjectTypeGen.createObjectType(mv, (BObjectType) bType); @@ -289,7 +389,7 @@ private int createTypesInstanceSplits(ClassWriter cw, List ty jvmErrorTypeGen.createErrorType(mv, (BErrorType) bType, bType.tsymbol.name.value); break; case TypeTags.TUPLE: - jvmTupleTypeGen.createTupleType(mv, (BTupleType) bType); + jvmTupleTypeGen.createTupleType(mv, (BTupleType) getImpliedType(bType)); break; default: jvmUnionTypeGen.createUnionType(mv, (BUnionType) bType); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/JvmMethodsSplitter.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/JvmMethodsSplitter.java index 6b8eb8afc570..95003be6fc4c 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/JvmMethodsSplitter.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/JvmMethodsSplitter.java @@ -47,7 +47,8 @@ public JvmMethodsSplitter(JvmPackageGen jvmPackageGen, JvmConstantsGen jvmConsta this.module = module; this.jvmPackageGen = jvmPackageGen; this.moduleInitClass = moduleInitClass; - this.jvmCreateTypeGen = new JvmCreateTypeGen(jvmTypeGen, jvmConstantsGen, module.packageID, typeHashVisitor); + this.jvmCreateTypeGen = new JvmCreateTypeGen(jvmTypeGen, jvmConstantsGen, module.packageID, typeHashVisitor, + jvmPackageGen); this.jvmAnnotationsGen = new JvmAnnotationsGen(module, jvmPackageGen, jvmTypeGen, jvmConstantsGen); this.jvmValueCreatorGen = new JvmValueCreatorGen(module.packageID, jvmTypeGen); jvmConstantsGen.setJvmCreateTypeGen(jvmCreateTypeGen); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/types/JvmRecordTypeGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/types/JvmRecordTypeGen.java index 217f636fa71c..1e0e236a55ce 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/types/JvmRecordTypeGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/types/JvmRecordTypeGen.java @@ -22,7 +22,6 @@ import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import org.wso2.ballerinalang.compiler.bir.codegen.BallerinaClassWriter; -import org.wso2.ballerinalang.compiler.bir.codegen.JvmCodeGenUtil; import org.wso2.ballerinalang.compiler.bir.codegen.JvmPackageGen; import org.wso2.ballerinalang.compiler.bir.codegen.JvmTypeGen; import org.wso2.ballerinalang.compiler.bir.codegen.split.JvmConstantsGen; @@ -38,21 +37,16 @@ import static org.objectweb.asm.ClassWriter.COMPUTE_FRAMES; import static org.objectweb.asm.Opcodes.ACC_PUBLIC; import static org.objectweb.asm.Opcodes.ACC_SUPER; -import static org.objectweb.asm.Opcodes.ACONST_NULL; import static org.objectweb.asm.Opcodes.CHECKCAST; import static org.objectweb.asm.Opcodes.DUP; -import static org.objectweb.asm.Opcodes.DUP_X1; import static org.objectweb.asm.Opcodes.GETSTATIC; import static org.objectweb.asm.Opcodes.INVOKESPECIAL; import static org.objectweb.asm.Opcodes.INVOKESTATIC; import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL; import static org.objectweb.asm.Opcodes.NEW; import static org.objectweb.asm.Opcodes.PUTFIELD; -import static org.objectweb.asm.Opcodes.PUTSTATIC; -import static org.objectweb.asm.Opcodes.SWAP; import static org.objectweb.asm.Opcodes.V17; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmCodeGenUtil.getModuleLevelClassName; -import static org.wso2.ballerinalang.compiler.bir.codegen.JvmCodeGenUtil.toNameString; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.JVM_INIT_METHOD; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.LINKED_HASH_MAP; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.MODULE_RECORD_TYPES_CLASS_NAME; @@ -60,13 +54,10 @@ import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.RECORD_TYPE_IMPL; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.GET_MODULE; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.GET_TYPE; -import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.GET_TYPEDESC; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.RECORD_TYPE_IMPL_INIT; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.SET_LINKED_HASH_MAP; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.SET_MAP; -import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.TYPE_DESC_CONSTRUCTOR; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.VOID_METHOD_DESC; -import static org.wso2.ballerinalang.compiler.bir.codegen.JvmValueGen.getTypeDescClassName; /** * BIR record type to JVM byte code generation class. @@ -143,10 +134,8 @@ private void addRecordRestField(MethodVisitor mv, BType restFieldType) { * * @param mv method visitor * @param recordType record type - * @param typeOwnerClass record type owner class - * @param internalName record type internal name */ - public void createRecordType(MethodVisitor mv, BRecordType recordType, String typeOwnerClass, String internalName) { + public void createRecordType(MethodVisitor mv, BRecordType recordType, String internalName) { // Create the record type mv.visitTypeInsn(NEW, RECORD_TYPE_IMPL); mv.visitInsn(DUP); @@ -174,16 +163,6 @@ public void createRecordType(MethodVisitor mv, BRecordType recordType, String ty // initialize the record type mv.visitMethodInsn(INVOKESPECIAL, RECORD_TYPE_IMPL, JVM_INIT_METHOD, RECORD_TYPE_IMPL_INIT, false); - - mv.visitInsn(DUP); - String packageName = JvmCodeGenUtil.getPackageName(recordType.tsymbol.pkgID); - String className = getTypeDescClassName(packageName, toNameString(recordType)); - mv.visitTypeInsn(NEW, className); - mv.visitInsn(DUP_X1); - mv.visitInsn(SWAP); - mv.visitInsn(ACONST_NULL); - mv.visitMethodInsn(INVOKESPECIAL, className, JVM_INIT_METHOD, TYPE_DESC_CONSTRUCTOR, false); - mv.visitFieldInsn(PUTSTATIC, typeOwnerClass, jvmTypeGen.getTypedescFieldName(internalName), GET_TYPEDESC); } private String getFullName(BRecordType recordType) { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRNode.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRNode.java index d2862f16aa9a..aaf1a587d504 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRNode.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRNode.java @@ -58,6 +58,7 @@ public static class BIRPackage extends BIRNode { public final List importModules; public final List typeDefs; public final List globalVars; + public final List typedescs; public final Set importedGlobalVarsDummyVarDcls; public final List functions; public final List annotations; @@ -82,6 +83,7 @@ public BIRPackage(Location pos, Name org, Name pkgName, Name name, Name version, this.annotations = new ArrayList<>(); this.constants = new ArrayList<>(); this.serviceDecls = new ArrayList<>(); + this.typedescs = new ArrayList<>(); } @Override @@ -230,6 +232,15 @@ public BIRGlobalVariableDcl(Location pos, long flags, BType type, PackageID pkgI this.annotAttachments = new ArrayList<>(); } + public BIRGlobalVariableDcl(BType type, Name name, VarScope scope, VarKind kind, long flags, PackageID pkgId, + SymbolOrigin origin) { + super(type, name, scope, kind); + this.flags = flags; + this.pkgId = pkgId; + this.origin = origin; + this.annotAttachments = new ArrayList<>(); + } + @Override public void accept(BIRVisitor visitor) { visitor.visit(this); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRNonTerminator.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRNonTerminator.java index 99dde8d801da..c736a9322897 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRNonTerminator.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRNonTerminator.java @@ -208,20 +208,23 @@ public void setRhsOperands(BIROperand[] operands) { public static class NewStructure extends BIRNonTerminator { public BIROperand rhsOp; public List initialValues; + public BType type; - public NewStructure(Location pos, BIROperand lhsOp, BIROperand rhsOp) { + public NewStructure(Location pos, BIROperand lhsOp, BIROperand rhsOp, BType type) { super(pos, InstructionKind.NEW_STRUCTURE); this.lhsOp = lhsOp; this.rhsOp = rhsOp; this.initialValues = new ArrayList<>(); + this.type = type; } public NewStructure(Location pos, BIROperand lhsOp, BIROperand rhsOp, - List initialValues) { + List initialValues, BType type) { super(pos, InstructionKind.NEW_STRUCTURE); this.lhsOp = lhsOp; this.rhsOp = rhsOp; this.initialValues = initialValues; + this.type = type; } @Override diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ASTBuilderUtil.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ASTBuilderUtil.java index 3d39deb5d241..51ce4e421ac9 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ASTBuilderUtil.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ASTBuilderUtil.java @@ -289,6 +289,12 @@ static BLangAssignment createAssignmentStmt(Location pos, BlockNode target) { return assignment; } + static BLangAssignment createAssignmentStmt(Location pos) { + final BLangAssignment assignment = (BLangAssignment) TreeBuilder.createAssignmentNode(); + assignment.pos = pos; + return assignment; + } + static BLangAssignment createAssignmentStmt(Location pos, BLangExpression varRef, BLangExpression rhsExpr) { final BLangAssignment assignment = (BLangAssignment) TreeBuilder.createAssignmentNode(); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java index 6fe4551aa68d..26dae3700de1 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java @@ -160,25 +160,22 @@ private AnnotationDesugar(CompilerContext context) { this.closureGenerator = ClosureGenerator.getInstance(context); } - /** - * Initialize annotation map. - * - * @param pkgNode package node - */ - void initializeAnnotationMap(BLangPackage pkgNode) { - annotationMap = createGlobalAnnotationMapVar(pkgNode); + void initializeAnnotationMap(BLangPackage pkgNode, BLangBlockFunctionBody initFnBody) { + annotationMap = createGlobalAnnotationMapVar(pkgNode, initFnBody); } - void rewritePackageAnnotations(BLangPackage pkgNode, SymbolEnv env) { + BLangBlockStmt rewritePackageAnnotations(BLangPackage pkgNode, SymbolEnv env) { BLangFunction initFunction = pkgNode.initFunction; - - defineTypeAnnotations(pkgNode, env, initFunction); - defineClassAnnotations(pkgNode, env, initFunction); - defineFunctionAnnotations(pkgNode, env, initFunction); + BLangBlockStmt blockStmt = (BLangBlockStmt) TreeBuilder.createBlockNode(); + blockStmt.stmts.addAll(defineTypeAnnotations(pkgNode, env, initFunction).stmts); + blockStmt.stmts.addAll(defineClassAnnotations(pkgNode, env, initFunction).stmts); + blockStmt.stmts.addAll(defineFunctionAnnotations(pkgNode, env, initFunction).stmts); + return blockStmt; } - private void defineClassAnnotations(BLangPackage pkgNode, SymbolEnv env2, BLangFunction initFunction) { + private BLangBlockStmt defineClassAnnotations(BLangPackage pkgNode, SymbolEnv env2, BLangFunction initFunction) { List topLevelNodes = pkgNode.topLevelNodes; + BLangBlockStmt blockStmt = (BLangBlockStmt) TreeBuilder.createBlockNode(); for (int i = 0, topLevelNodesSize = topLevelNodes.size(); i < topLevelNodesSize; i++) { TopLevelNode topLevelNode = topLevelNodes.get(i); @@ -227,28 +224,27 @@ private void defineClassAnnotations(BLangPackage pkgNode, SymbolEnv env2, BLangF // Add the lambda/invocation in a temporary block. BLangBlockStmt target = (BLangBlockStmt) TreeBuilder.createBlockNode(); target.pos = initBody.pos; - addLambdaToGlobalAnnotMap(classDef.name.value, lambdaFunction, target); - int index = calculateIndex((initBody).stmts, type.tsymbol); - for (BLangStatement stmt : target.stmts) { - initBody.stmts.add(index++, stmt); - } + blockStmt.stmts.addAll(target.stmts); + blockStmt.stmts.add(addLambdaToGlobalAnnotMap(classDef.name.value, lambdaFunction, target)); } else { // Add the lambda/invocation in a temporary block. LocationData locationData = new LocationData(pkgID, owner, pos, initBody); addAnnotationLambdaToGlobalAnnotationMapWithBlockDef(pkgNode, classDef, locationData, - lambdaFunction); + lambdaFunction, blockStmt); } } else { - addInvocationToGlobalAnnotMap(classDef.name.value, lambdaFunction, initBody); + blockStmt.stmts.add(addInvocationToGlobalAnnotMap(classDef.name.value, lambdaFunction, initBody)); } } } + return blockStmt; } private void addAnnotationLambdaToGlobalAnnotationMapWithBlockDef(BLangPackage pkgNode, BLangClassDefinition classDef, LocationData location, - BLangLambdaFunction lambdaFunction) { + BLangLambdaFunction lambdaFunction, + BLangBlockStmt allStmt) { BLangBlockStmt target = (BLangBlockStmt) TreeBuilder.createBlockNode(); PackageID pkgID = location.pkgID; Location pos = location.pos; @@ -282,19 +278,15 @@ private void addAnnotationLambdaToGlobalAnnotationMapWithBlockDef(BLangPackage p StringEscapeUtils.unescapeJava(classDef.name.value)); indexAccessNode.expr = ASTBuilderUtil.createVariableRef(pos, annotationMap.symbol); indexAccessNode.setBType(((BMapType) annotationMap.getBType()).constraint); - + allStmt.stmts.addAll(target.stmts); // $annotation_data[$anonType$_1] = $anon$anonType$_1_lamda - BLangAssignment assignmentStmt = ASTBuilderUtil.createAssignmentStmt(pos, target); + BLangAssignment assignmentStmt = ASTBuilderUtil.createAssignmentStmt(pos); + allStmt.stmts.add(assignmentStmt); assignmentStmt.expr = simpleVarRef; assignmentStmt.varRef = indexAccessNode; simpleVarRef.parent = initBody; assignmentStmt.parent = initBody; - - int index = calculateOCEExprIndex(initBody.stmts, classDef.getBType().tsymbol); - for (BLangStatement stmt : target.stmts) { - initBody.stmts.add(index++, stmt); - } } private boolean isServiceDeclaration(BLangClassDefinition serviceClass) { @@ -455,7 +447,8 @@ void defineStatementAnnotations(List attachments, addAnnotsToLiteral(attachments, mapLiteral, location, env, false); } - private void defineTypeAnnotations(BLangPackage pkgNode, SymbolEnv env, BLangFunction initFunction) { + private BLangBlockStmt defineTypeAnnotations(BLangPackage pkgNode, SymbolEnv env, BLangFunction initFunction) { + BLangBlockStmt blockStmt = (BLangBlockStmt) TreeBuilder.createBlockNode(); for (BLangTypeDefinition typeDef : pkgNode.typeDefinitions) { if (typeDef.isBuiltinTypeDef) { continue; @@ -475,14 +468,17 @@ private void defineTypeAnnotations(BLangPackage pkgNode, SymbolEnv env, BLangFun } if (lambdaFunction != null) { - addInvocationToGlobalAnnotMap(typeDef.name.value, lambdaFunction, initFunction.body); + blockStmt.stmts.add(addInvocationToGlobalAnnotMap(typeDef.name.value, lambdaFunction, + initFunction.body)); } } + return blockStmt; } - private void defineFunctionAnnotations(BLangPackage pkgNode, SymbolEnv env, BLangFunction initFunction) { + private BLangBlockStmt defineFunctionAnnotations(BLangPackage pkgNode, SymbolEnv env, BLangFunction initFunction) { BLangBlockFunctionBody initFnBody = (BLangBlockFunctionBody) initFunction.body; BLangFunction[] functions = pkgNode.functions.toArray(new BLangFunction[pkgNode.functions.size()]); + BLangBlockStmt blockStmt = (BLangBlockStmt) TreeBuilder.createBlockNode(); for (BLangFunction function : functions) { PackageID pkgID = function.symbol.pkgID; BSymbol owner = function.symbol.owner; @@ -500,23 +496,17 @@ private void defineFunctionAnnotations(BLangPackage pkgNode, SymbolEnv env, BLan BLangBlockStmt target = (BLangBlockStmt) TreeBuilder.createBlockNode(); target.pos = initFnBody.pos; String identifier = function.attachedFunction ? function.symbol.name.value : function.name.value; - - int index; + // Add the annotation assignment for resources to immediately before the service init. + blockStmt.stmts.addAll(target.stmts); if (function.attachedFunction && Symbols.isFlagOn(function.receiver.getBType().flags, Flags.OBJECT_CTOR)) { - addLambdaToGlobalAnnotMap(identifier, lambdaFunction, target); - index = calculateIndex(initFnBody.stmts, function.receiver.getBType().tsymbol); + blockStmt.stmts.add(addLambdaToGlobalAnnotMap(identifier, lambdaFunction, target)); } else { - addInvocationToGlobalAnnotMap(identifier, lambdaFunction, target); - index = initFnBody.stmts.size(); - } - - // Add the annotation assignment for resources to immediately before the service init. - for (BLangStatement stmt : target.stmts) { - initFnBody.stmts.add(index++, stmt); + blockStmt.stmts.add(addInvocationToGlobalAnnotMap(identifier, lambdaFunction, target)); } } } + return blockStmt; } private void attachSchedulerPolicy(BLangFunction function) { @@ -930,6 +920,18 @@ private BLangSimpleVariable createGlobalAnnotationMapVar(BLangPackage pkgNode) { return annotationMap; } + private BLangSimpleVariable createGlobalAnnotationMapVar(BLangPackage pkgNode, BLangBlockFunctionBody initFnBody) { + BLangSimpleVariable annotationMap = ASTBuilderUtil.createVariable(pkgNode.pos, ANNOTATION_DATA, + symTable.mapType, + ASTBuilderUtil.createEmptyRecordLiteral( + pkgNode.pos, symTable.mapType), null); + ASTBuilderUtil.defineVariable(annotationMap, pkgNode.symbol, names); + pkgNode.globalVars.add(0, annotationMap); // TODO fix this + pkgNode.topLevelNodes.add(0, annotationMap); + desugar.addToInitFunction(annotationMap, initFnBody); + return annotationMap; + } + private void addTrueAnnot(BLangAnnotationAttachment attachment, BLangRecordLiteral recordLiteral, boolean isLocalObjectCtor) { // Handle scenarios where type is a subtype of `true` explicitly or implicitly (by omission). @@ -966,24 +968,24 @@ private void addAnnotArray(Location pos, String name, BType annotType, addAnnotValueToLiteral(recordLiteral, name, arrayLiteral, pos); } - private void addInvocationToGlobalAnnotMap(String identifier, BLangLambdaFunction lambdaFunction, + private BLangAssignment addInvocationToGlobalAnnotMap(String identifier, BLangLambdaFunction lambdaFunction, BLangBlockStmt target) { // create: $annotation_data["identifier"] = $annot_func$.call(); - addAnnotValueAssignmentToMap(annotationMap, identifier, target, + return addAnnotValueAssignmentToMap(annotationMap, identifier, target, getInvocation(lambdaFunction)); } - private void addInvocationToGlobalAnnotMap(String identifier, BLangLambdaFunction lambdaFunction, + private BLangAssignment addInvocationToGlobalAnnotMap(String identifier, BLangLambdaFunction lambdaFunction, BLangFunctionBody target) { // create: $annotation_data["identifier"] = $annot_func$.call(); - addAnnotValueAssignmentToMap(annotationMap, identifier, (BLangBlockFunctionBody) target, + return addAnnotValueAssignmentToMap(annotationMap, identifier, (BLangBlockFunctionBody) target, getInvocation(lambdaFunction)); } - private void addLambdaToGlobalAnnotMap(String identifier, BLangLambdaFunction lambdaFunction, + private BLangAssignment addLambdaToGlobalAnnotMap(String identifier, BLangLambdaFunction lambdaFunction, BLangBlockStmt target) { // create: $annotation_data["identifier"] = $annot_func$; - addAnnotValueAssignmentToMap(annotationMap, identifier, target, + return addAnnotValueAssignmentToMap(annotationMap, identifier, target, ASTBuilderUtil.createVariableRef(lambdaFunction.pos, lambdaFunction.function.symbol)); } @@ -1011,10 +1013,10 @@ private BLangInvocation getInvocation(BInvokableSymbol symbol) { return funcInvocation; } - private void addAnnotValueAssignmentToMap(BLangSimpleVariable mapVar, String identifier, + private BLangAssignment addAnnotValueAssignmentToMap(BLangSimpleVariable mapVar, String identifier, BlockNode target, Location targetPos, BLangExpression expression) { - BLangAssignment assignmentStmt = ASTBuilderUtil.createAssignmentStmt(targetPos, target); + BLangAssignment assignmentStmt = ASTBuilderUtil.createAssignmentStmt(targetPos); assignmentStmt.expr = expression; BLangIndexBasedAccess indexAccessNode = (BLangIndexBasedAccess) TreeBuilder.createIndexBasedAccessNode(); @@ -1024,16 +1026,17 @@ private void addAnnotValueAssignmentToMap(BLangSimpleVariable mapVar, String ide indexAccessNode.expr = ASTBuilderUtil.createVariableRef(targetPos, mapVar.symbol); indexAccessNode.setBType(((BMapType) mapVar.getBType()).constraint); assignmentStmt.varRef = indexAccessNode; + return assignmentStmt; } - private void addAnnotValueAssignmentToMap(BLangSimpleVariable mapVar, String identifier, + private BLangAssignment addAnnotValueAssignmentToMap(BLangSimpleVariable mapVar, String identifier, BLangBlockFunctionBody target, BLangExpression expression) { - addAnnotValueAssignmentToMap(mapVar, identifier, target, target.pos, expression); + return addAnnotValueAssignmentToMap(mapVar, identifier, target, target.pos, expression); } - private void addAnnotValueAssignmentToMap(BLangSimpleVariable mapVar, String identifier, + private BLangAssignment addAnnotValueAssignmentToMap(BLangSimpleVariable mapVar, String identifier, BLangBlockStmt target, BLangExpression expression) { - addAnnotValueAssignmentToMap(mapVar, identifier, target, target.pos, expression); + return addAnnotValueAssignmentToMap(mapVar, identifier, target, target.pos, expression); } private void addAnnotValueToLiteral(BLangRecordLiteral recordLiteral, String identifier, diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureDesugar.java index b2585c126b53..4cdf75cea157 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureDesugar.java @@ -40,6 +40,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BInvokableType; import org.wso2.ballerinalang.compiler.semantics.model.types.BMapType; import org.wso2.ballerinalang.compiler.semantics.model.types.BObjectType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BRecordType; import org.wso2.ballerinalang.compiler.semantics.model.types.BType; import org.wso2.ballerinalang.compiler.tree.BLangAnnotation; import org.wso2.ballerinalang.compiler.tree.BLangAnnotationAttachment; @@ -747,8 +748,8 @@ public void visit(BLangSimpleVariableDef varDefNode) { // If its a variable declaration with a RHS value, and also a closure. varDefNode.var.typeNode = rewrite(varDefNode.var.typeNode, env); if (varDefNode.var.expr != null) { - BLangAssignment stmt = createAssignmentToClosureMap(varDefNode); - result = rewrite(stmt, env); + BLangBlockStmt stmt = createAssignmentToClosureMap(varDefNode); + result = stmt; } else { // Note: Although it's illegal to use a closure variable without initializing it in it's declared scope, // when we access (initialize) a variable from outer scope, since we desugar transaction block into a @@ -764,7 +765,9 @@ public void visit(BLangSimpleVariableDef varDefNode) { * @param varDefNode variable definition node * @return assignment statement created */ - private BLangAssignment createAssignmentToClosureMap(BLangSimpleVariableDef varDefNode) { + private BLangBlockStmt createAssignmentToClosureMap(BLangSimpleVariableDef varDefNode) { + BLangBlockStmt blockStmt = ASTBuilderUtil.createBlockStmt(varDefNode.pos); + blockStmt.addStatement(createSimpleVarDef(varDefNode)); BVarSymbol mapSymbol = createMapSymbolIfAbsent(env.node, blockClosureMapCount); // Add the variable to the created map. @@ -776,7 +779,20 @@ private BLangAssignment createAssignmentToClosureMap(BLangSimpleVariableDef varD accessExpr.setBType(((BMapType) mapSymbol.type).constraint); accessExpr.isLValue = true; // Written to: 'map["x"] = 8'. - return ASTBuilderUtil.createAssignmentStmt(varDefNode.pos, accessExpr, varDefNode.var.expr); + blockStmt.addStatement(rewrite(ASTBuilderUtil.createAssignmentStmt(varDefNode.pos, accessExpr, + varDefNode.var.expr), env)); + return blockStmt; + } + + private BLangSimpleVariableDef createSimpleVarDef(BLangSimpleVariableDef varDefNode) { + BLangSimpleVariable variable = varDefNode.var; + BLangSimpleVariable simpleVariable = ASTBuilderUtil.createVariable(variable.pos, variable.name.value, + variable.getBType(), null, variable.symbol); + BLangSimpleVariableDef simpleVariableDef = ASTBuilderUtil.createVariableDef(varDefNode.pos); + simpleVariableDef.var = simpleVariable; + simpleVariable.typeNode = variable.typeNode; + simpleVariableDef.setBType(simpleVariable.getBType()); + return simpleVariableDef; } private BVarSymbol createMapSymbolIfAbsent(BLangNode node, int closureMapCount) { @@ -934,6 +950,7 @@ public void visit(BLangObjectTypeNode objectTypeNode) { @Override public void visit(BLangRecordTypeNode recordTypeNode) { + ((BRecordType) recordTypeNode.getBType()).enclMapSymbols = collectClosureMapSymbols(env, false); for (BLangSimpleVariable field : recordTypeNode.fields) { field.typeNode = rewrite(field.typeNode, env); } @@ -1413,16 +1430,17 @@ public void visit(BLangLambdaFunction bLangLambdaFunction) { // Save param closure map of the encl invokable. bLangLambdaFunction.paramMapSymbolsOfEnclInvokable = enclInvokable.paramClosureMap; boolean isWorker = bLangLambdaFunction.function.flagSet.contains(Flag.WORKER); - bLangLambdaFunction.enclMapSymbols = collectClosureMapSymbols(symbolEnv, enclInvokable, isWorker); + bLangLambdaFunction.enclMapSymbols = collectClosureMapSymbols(env, isWorker); } result = bLangLambdaFunction; } - private TreeMap collectClosureMapSymbols(SymbolEnv symbolEnv, BLangInvokableNode enclInvokable, - boolean isWorker) { + private TreeMap collectClosureMapSymbols(SymbolEnv env, boolean isWorker) { // Recursively iterate back to the encl invokable and get all map symbols visited. + SymbolEnv symbolEnv = env.createClone(); + BLangFunction enclInvokable = (BLangFunction) symbolEnv.enclInvokable; TreeMap enclMapSymbols = new TreeMap<>(); - while (symbolEnv != null && symbolEnv.enclInvokable == enclInvokable) { + while (symbolEnv != null && symbolEnv.node != null && symbolEnv.enclInvokable == enclInvokable) { BVarSymbol mapSym = getMapSymbol(symbolEnv.node); // Skip non-block bodies @@ -1961,10 +1979,6 @@ public void visit(BLangRecordLiteral.BLangMapLiteral mapLiteral) { @Override public void visit(BLangRecordLiteral.BLangStructLiteral structLiteral) { - SymbolEnv symbolEnv = env.createClone(); - BLangFunction enclInvokable = (BLangFunction) symbolEnv.enclInvokable; - structLiteral.enclMapSymbols = collectClosureMapSymbols(symbolEnv, enclInvokable, false); - for (RecordLiteralNode.RecordField field : structLiteral.fields) { if (field.isKeyValueField()) { BLangRecordLiteral.BLangRecordKeyValueField keyValueField = diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java index 38a81d2fd0f7..5d9c0fde5484 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java @@ -260,10 +260,14 @@ private void addClosuresToGlobalVariableList(SymbolEnv pkgEnv) { BLangSimpleVariable simpleVariable = queue.poll().var; simpleVariable.flagSet.add(Flag.PUBLIC); simpleVariable.symbol.flags |= Flags.PUBLIC; - pkgEnv.enclPkg.globalVars.add(0, rewrite(simpleVariable, pkgEnv)); + BLangSimpleVariable variableDef = rewrite(simpleVariable, pkgEnv); + pkgEnv.enclPkg.globalVars.add(0, variableDef); + pkgEnv.enclPkg.topLevelNodes.add(0, variableDef); } for (BLangSimpleVariableDef closureReference : annotationClosureReferences) { - pkgEnv.enclPkg.globalVars.add(rewrite(closureReference.var, pkgEnv)); + BLangSimpleVariable simpleVariable = rewrite(closureReference.var, pkgEnv); + pkgEnv.enclPkg.globalVars.add(simpleVariable); + pkgEnv.enclPkg.topLevelNodes.add(simpleVariable); } } @@ -1610,7 +1614,9 @@ private List rewrite(List nodeList, SymbolEnv env) { E node = rewrite(nodeList.remove(0), env); Iterator iterator = annotationClosureReferences.iterator(); while (iterator.hasNext()) { - nodeList.add(rewrite((E) annotationClosureReferences.poll().var, env)); + E simpleVariable = rewrite((E) annotationClosureReferences.poll().var, env); + nodeList.add(simpleVariable); + env.enclPkg.topLevelNodes.add((BLangSimpleVariable) simpleVariable); } nodeList.add(node); } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java index ede19f45b6d4..75cb1b1b0f16 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java @@ -776,9 +776,6 @@ public void visit(BLangPackage pkgNode) { // create closures for default values closureGenerator.visit(pkgNode); - // Initialize the annotation map - annotationDesugar.initializeAnnotationMap(pkgNode); - pkgNode.constants.stream() .filter(constant -> (constant.expr.getKind() == NodeKind.LITERAL || constant.expr.getKind() == NodeKind.NUMERIC_LITERAL) @@ -788,16 +785,16 @@ public void visit(BLangPackage pkgNode) { BLangBlockStmt serviceAttachments = serviceDesugar.rewriteServiceVariables(pkgNode.services, env); BLangBlockFunctionBody initFnBody = (BLangBlockFunctionBody) pkgNode.initFunction.body; - rewriteConstants(pkgNode, initFnBody); + // Initialize the annotation map + annotationDesugar.initializeAnnotationMap(pkgNode, initFnBody); pkgNode.constants = removeDuplicateConstants(pkgNode); - pkgNode.globalVars = desugarGlobalVariables(pkgNode, initFnBody); - pkgNode.services.forEach(service -> serviceDesugar.engageCustomServiceDesugar(service, env)); - desugarAnnotations(pkgNode); - + BLangBlockStmt bLangBlockStmt = desugarAnnotations(pkgNode); + desugarTopLevelNodes(pkgNode, initFnBody); + initFnBody.stmts.addAll(bLangBlockStmt.stmts); // Add invocation for user specified module init function (`init()`) if present and return. addUserDefinedModuleInitInvocationAndReturn(pkgNode); @@ -845,12 +842,13 @@ public void visit(BLangPackage pkgNode) { result = pkgNode; } - private void desugarAnnotations(BLangPackage pkgNode) { + private BLangBlockStmt desugarAnnotations(BLangPackage pkgNode) { List prevTypeDefinitions = new ArrayList<>(pkgNode.typeDefinitions); - annotationDesugar.rewritePackageAnnotations(pkgNode, env); + BLangBlockStmt bLangBlockStmt = annotationDesugar.rewritePackageAnnotations(pkgNode, env); addInitFunctionForRecordTypeNodeInTypeDef(pkgNode, prevTypeDefinitions); + return bLangBlockStmt; } private void addInitFunctionForRecordTypeNodeInTypeDef(BLangPackage pkgNode, @@ -993,65 +991,148 @@ private List getConfigurableLangLibInvocationParam(BLangSimpleV return new ArrayList<>(Arrays.asList(orgLiteral, moduleNameLiteral, versionLiteral, configNameLiteral, typedescExpr)); } + private BLangSimpleVariableDef createSimpleVarDef(BLangPackage pkgNode, String name, + BLangRecordTypeNode recordTypeNode) { + BType type = recordTypeNode.getBType(); + BVarSymbol varSymbol = new BVarSymbol(0, Names.fromString(name), pkgNode.packageID, type, + pkgNode.symbol, pkgNode.pos, VIRTUAL); + BLangSimpleVariable simpleVariable = ASTBuilderUtil.createVariable(pkgNode.pos, name, type, null, varSymbol); + BLangSimpleVariableDef simpleVariableDef = ASTBuilderUtil.createVariableDef(pkgNode.pos); + simpleVariableDef.var = simpleVariable; + simpleVariable.typeNode = recordTypeNode; + simpleVariableDef.setBType(simpleVariable.getBType()); + return simpleVariableDef; + } + + private BLangSimpleVariableDef createSimpleVarDefForTupleType(BLangPackage pkgNode, String name, + BLangTupleTypeNode tupleTypeNode) { + BType type = tupleTypeNode.getBType(); + BVarSymbol varSymbol = new BVarSymbol(0, Names.fromString(name), pkgNode.packageID, type, + pkgNode.symbol, pkgNode.pos, VIRTUAL); + BLangSimpleVariable simpleVariable = ASTBuilderUtil.createVariable(pkgNode.pos, name, type, null, varSymbol); + BLangSimpleVariableDef simpleVariableDef = ASTBuilderUtil.createVariableDef(pkgNode.pos); + simpleVariableDef.var = simpleVariable; + simpleVariable.typeNode = tupleTypeNode; + simpleVariableDef.setBType(simpleVariable.getBType()); + return simpleVariableDef; + } - private List desugarGlobalVariables(BLangPackage pkgNode, BLangBlockFunctionBody initFnBody) { + private void desugarTopLevelNodes(BLangPackage pkgNode, BLangBlockFunctionBody initFnBody) { List desugaredGlobalVarList = new ArrayList<>(); SymbolEnv initFunctionEnv = SymbolEnv.createFunctionEnv(pkgNode.initFunction, pkgNode.initFunction.symbol.scope, env); - for (BLangVariable globalVar : pkgNode.globalVars) { - this.env.enclPkg.topLevelNodes.remove(globalVar); - // This will convert complex variables to simple variables. - switch (globalVar.getKind()) { - case TUPLE_VARIABLE: - BLangNode blockStatementNode = rewrite(globalVar, initFunctionEnv); - List statements = ((BLangBlockStmt) blockStatementNode).stmts; - - int statementSize = statements.size(); - for (int i = 0; i < statementSize; i++) { - addToGlobalVariableList(statements.get(i), initFnBody, globalVar, desugaredGlobalVarList); - } - break; - case RECORD_VARIABLE: - case ERROR_VARIABLE: - blockStatementNode = rewrite(globalVar, initFunctionEnv); - for (BLangStatement statement : ((BLangBlockStmt) blockStatementNode).stmts) { - addToGlobalVariableList(statement, initFnBody, globalVar, desugaredGlobalVarList); - } - break; - default: - long globalVarFlags = globalVar.symbol.flags; - BLangSimpleVariable simpleGlobalVar = (BLangSimpleVariable) globalVar; - if (Symbols.isFlagOn(globalVarFlags, Flags.CONFIGURABLE)) { - if (Symbols.isFlagOn(globalVarFlags, Flags.REQUIRED)) { - // If it is required configuration get directly - List args = getConfigurableLangLibInvocationParam(simpleGlobalVar); - BLangInvocation getValueInvocation = createLangLibInvocationNode("getConfigurableValue", - args, symTable.anydataType, simpleGlobalVar.pos); - simpleGlobalVar.expr = getValueInvocation; - } else { - // If it is optional configuration create if else - simpleGlobalVar.expr = createIfElseFromConfigurable(simpleGlobalVar, initFunctionEnv); - } - } + int size = pkgNode.topLevelNodes.size(); + for (int j = 0; j < size; j++) { + TopLevelNode topLevelNode = pkgNode.topLevelNodes.remove(0); + if (topLevelNode.getKind() == NodeKind.TYPE_DEFINITION) { + desugarTypeDefinitions((BLangTypeDefinition) topLevelNode, pkgNode, initFnBody); + } else if (topLevelNode.getKind() == NodeKind.CONSTANT) { + desugarConstantVariables((BLangConstant) topLevelNode, initFunctionEnv, initFnBody); + } + if (!(pkgNode.globalVars.contains(topLevelNode))) { + pkgNode.topLevelNodes.add(topLevelNode); + continue; + } - // Module init should fail if listener is a error value. - if (Symbols.isFlagOn(globalVarFlags, Flags.LISTENER) - && types.containsErrorType(globalVar.expr.getBType())) { - globalVar.expr = ASTBuilderUtil.createCheckExpr(globalVar.expr.pos, globalVar.expr, - globalVar.getBType()); - } + BLangVariable globalVar = (BLangVariable) topLevelNode; + desugaredGlobalVarList.addAll(desugarGlobalVariables(globalVar, initFunctionEnv, initFnBody)); - addToInitFunction(simpleGlobalVar, initFnBody); - desugaredGlobalVarList.add(simpleGlobalVar); - break; - } } this.env.enclPkg.topLevelNodes.addAll(desugaredGlobalVarList); - return desugaredGlobalVarList; + this.env.enclPkg.globalVars = desugaredGlobalVarList; } + private void desugarTypeDefinitions(BLangTypeDefinition typeDefinition , BLangPackage pkgNode, + BLangBlockFunctionBody initFnBody) { + BLangType typeNode = typeDefinition.getTypeNode(); + if (typeDefinition.symbol.origin == VIRTUAL) { + return; + } + if (typeNode != null && typeNode.getKind() == NodeKind.RECORD_TYPE) { + BLangRecordTypeNode recordTypeNode = (BLangRecordTypeNode) typeNode; + BLangSimpleVariableDef bLangSimpleVariableDef = + createSimpleVarDef(pkgNode, recordTypeNode.getBType().tsymbol.name.getValue(), recordTypeNode); + initFnBody.stmts.add(bLangSimpleVariableDef); + } + + if (typeNode != null && typeNode.getKind() == NodeKind.TUPLE_TYPE_NODE) { + BLangTupleTypeNode tupleTypeNode = (BLangTupleTypeNode) typeNode; + BLangSimpleVariableDef bLangSimpleVariableDef = createSimpleVarDefForTupleType(pkgNode, + tupleTypeNode.getBType().tsymbol.name.getValue(), tupleTypeNode); + initFnBody.stmts.add(bLangSimpleVariableDef); + } + } + + private void desugarConstantVariables(BLangConstant constant, SymbolEnv initFunctionEnv, + BLangBlockFunctionBody initFnBody) { + BType constType = Types.getReferredType(constant.symbol.type); + if (constType.tag != TypeTags.INTERSECTION) { + return; + } + for (BType memberType : ((BIntersectionType) constType).getConstituentTypes()) { + if (memberType.tag == TypeTags.RECORD || memberType.tag == TypeTags.TUPLE) { + BLangSimpleVarRef constVarRef = ASTBuilderUtil.createVariableRef(constant.pos, constant.symbol); + constant.expr = rewrite(constant.expr, initFunctionEnv); + BLangAssignment constInit = ASTBuilderUtil.createAssignmentStmt(constant.pos, constVarRef, + constant.expr); + initFnBody.stmts.add(constInit); + } + } + } + +private List desugarGlobalVariables(BLangVariable globalVar, SymbolEnv initFunctionEnv, + BLangBlockFunctionBody initFnBody) { + List desugaredGlobalVarList = new ArrayList<>(); + // This will convert complex variables to simple variables. + switch (globalVar.getKind()) { + case TUPLE_VARIABLE: + BLangNode blockStatementNode = rewrite(globalVar, initFunctionEnv); + List statements = ((BLangBlockStmt) blockStatementNode).stmts; + + int statementSize = statements.size(); + for (int i = 0; i < statementSize; i++) { + addToGlobalVariableList(statements.get(i), initFnBody, globalVar, desugaredGlobalVarList); + } + break; + case RECORD_VARIABLE: + case ERROR_VARIABLE: + blockStatementNode = rewrite(globalVar, initFunctionEnv); + for (BLangStatement statement : ((BLangBlockStmt) blockStatementNode).stmts) { + addToGlobalVariableList(statement, initFnBody, globalVar, desugaredGlobalVarList); + } + break; + default: + long globalVarFlags = globalVar.symbol.flags; + BLangSimpleVariable simpleGlobalVar = (BLangSimpleVariable) globalVar; + if (Symbols.isFlagOn(globalVarFlags, Flags.CONFIGURABLE)) { + if (Symbols.isFlagOn(globalVarFlags, Flags.REQUIRED)) { + // If it is required configuration get directly + List args = getConfigurableLangLibInvocationParam(simpleGlobalVar); + BLangInvocation getValueInvocation = createLangLibInvocationNode("getConfigurableValue", + args, symTable.anydataType, simpleGlobalVar.pos); + simpleGlobalVar.expr = getValueInvocation; + } else { + // If it is optional configuration create if else + simpleGlobalVar.expr = createIfElseFromConfigurable(simpleGlobalVar, initFunctionEnv); + } + } + + // Module init should fail if listener is a error value. + if (Symbols.isFlagOn(globalVarFlags, Flags.LISTENER) + && types.containsErrorType(globalVar.expr.getBType())) { + globalVar.expr = ASTBuilderUtil.createCheckExpr(globalVar.expr.pos, globalVar.expr, + globalVar.getBType()); + } + + addToInitFunction(simpleGlobalVar, initFnBody); + desugaredGlobalVarList.add(simpleGlobalVar); + break; + } + return desugaredGlobalVarList; +} + private void addToGlobalVariableList(BLangStatement bLangStatement, BLangBlockFunctionBody initFnBody, BLangVariable globalVar, List desugaredGlobalVarList) { if (bLangStatement.getKind() == NodeKind.ASSIGNMENT || bLangStatement.getKind() == NodeKind.BLOCK) { @@ -1070,7 +1151,7 @@ private void addToGlobalVariableList(BLangStatement bLangStatement, BLangBlockFu } } - private void addToInitFunction(BLangSimpleVariable globalVar, BLangBlockFunctionBody initFnBody) { + public void addToInitFunction(BLangSimpleVariable globalVar, BLangBlockFunctionBody initFnBody) { if (globalVar.expr == null) { return; } @@ -1253,20 +1334,34 @@ public void visit(BLangRecordTypeNode recordTypeNode) { // referenced types are invoked on the current record type. if (recordTypeNode.isAnonymous && recordTypeNode.isLocal) { - BLangUserDefinedType userDefinedType = desugarLocalAnonRecordTypeNode(recordTypeNode); - TypeDefBuilderHelper.createTypeDefinitionForTSymbol(recordTypeNode.getBType(), - recordTypeNode.getBType().tsymbol, recordTypeNode, env); + // TODO: + BLangTypeDefinition typeDefinition = + TypeDefBuilderHelper.createTypeDefinitionForTSymbol(recordTypeNode.getBType(), + recordTypeNode.getBType().tsymbol, recordTypeNode, env); + BLangTypedescExpr typedescExpr = + ASTBuilderUtil.createTypedescExpr(recordTypeNode.pos, recordTypeNode.getBType(), + recordTypeNode.getBType()); + typedescExpr.typeNode = typeDefinition.getTypeNode(); + BType typedescType = new BTypedescType(recordTypeNode.getBType(), symTable.typeDesc.tsymbol); + BVarSymbol varSymbol = new BVarSymbol(0, recordTypeNode.symbol.name, this.env.scope.owner.pkgID, + typedescType, this.env.scope.owner, recordTypeNode.pos, VIRTUAL); + BLangSimpleVariableDef simpleVariableDef = createSimpleVariableDef(recordTypeNode.pos, + recordTypeNode.symbol.name.value, typedescType, typedescExpr, varSymbol); recordTypeNode.desugared = true; - result = userDefinedType; + result = recordTypeNode; return; } result = recordTypeNode; } - private BLangUserDefinedType desugarLocalAnonRecordTypeNode(BLangRecordTypeNode recordTypeNode) { - return ASTBuilderUtil.createUserDefineTypeNode(recordTypeNode.symbol.name.value, recordTypeNode.getBType(), - recordTypeNode.pos); + private BLangSimpleVariableDef createSimpleVariableDef(Location pos, String name, BType type, BLangExpression expr, + BVarSymbol varSymbol) { + BLangSimpleVariable simpleVariable = ASTBuilderUtil.createVariable(pos, name, type, expr, varSymbol); + BLangSimpleVariableDef variableDef = ASTBuilderUtil.createVariableDef(pos); + variableDef.var = simpleVariable; + variableDef.setBType(type); + return variableDef; } @Override @@ -1339,11 +1434,10 @@ public void visit(BLangErrorType errorType) { // Error without type param is either a user-defined-type or a default error, they don't need a type-def. // We need to create type-defs for local anonymous types with type param. if (errorType.isLocal && errorType.isAnonymous && hasTypeParam) { - BLangUserDefinedType userDefinedType = desugarLocalAnonRecordTypeNode(errorType); TypeDefBuilderHelper.createTypeDefinitionForTSymbol(errorType.getBType(), errorType.getBType().tsymbol, errorType, env); errorType.desugared = true; - result = userDefinedType; + result = errorType; return; } result = errorType; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ServiceDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ServiceDesugar.java index 05071332fb9f..4ddf6f14ccd6 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ServiceDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ServiceDesugar.java @@ -157,7 +157,7 @@ void rewriteServiceVariable(BLangService service, SymbolEnv env, BLangBlockStmt ASTBuilderUtil.defineVariable(service.serviceVariable, env.enclPkg.symbol, names); env.enclPkg.globalVars.add(service.serviceVariable); - + env.enclPkg.topLevelNodes.add(service.serviceVariable); int count = 0; for (BLangExpression attachExpr : service.attachedExprs) { // if y is anonymous -> y = y(expr) @@ -173,6 +173,7 @@ void rewriteServiceVariable(BLangService service, SymbolEnv env, BLangBlockStmt ASTBuilderUtil.defineVariable(listenerVar, env.enclPkg.symbol, names); listenerVar.symbol.flags |= Flags.LISTENER; env.enclPkg.globalVars.add(listenerVar); + env.enclPkg.topLevelNodes.add(listenerVar); listenerVarRef = ASTBuilderUtil.createVariableRef(pos, listenerVar.symbol); } @@ -187,6 +188,7 @@ void rewriteServiceVariable(BLangService service, SymbolEnv env, BLangBlockStmt null); ASTBuilderUtil.defineVariable(listenerWithoutErrors, env.enclPkg.symbol, names); env.enclPkg.globalVars.add(listenerWithoutErrors); + env.enclPkg.topLevelNodes.add(listenerWithoutErrors); BLangSimpleVarRef checkedRef = ASTBuilderUtil.createVariableRef(pos, listenerWithoutErrors.symbol); listenerVarRef = checkedRef; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/DataflowAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/DataflowAnalyzer.java index d20fdefbfe2e..6e53d71a0196 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/DataflowAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/DataflowAnalyzer.java @@ -525,9 +525,8 @@ public void visit(BLangTypeDefinition typeDefinition) { if (typeDefinition.symbol.kind == SymbolKind.TYPE_DEF) { symbol = symbol.type.tsymbol; } - typeDefEnv = SymbolEnv.createTypeEnv(typeDefinition.typeNode, symbol.scope, env); this.currDependentSymbolDeque.push(symbol); - analyzeNode(typeDefinition.typeNode, typeDefEnv); + analyzeNode(typeDefinition.typeNode, env); this.currDependentSymbolDeque.pop(); } @@ -656,18 +655,20 @@ public void visit(BLangSimpleVariableDef varDefNode) { @Override public void visit(BLangSimpleVariable variable) { BVarSymbol symbol = variable.symbol; - analyzeNode(variable.typeNode, env); if (symbol == null) { if (variable.expr != null) { analyzeNode(variable.expr, env); } return; } - - this.currDependentSymbolDeque.push(symbol); + if (!variable.flagSet.contains(Flag.FIELD)) { + this.currDependentSymbolDeque.push(symbol); + } + BLangType typeNode = variable.typeNode; + analyzeNode(typeNode, env); if (variable.typeNode != null && variable.typeNode.getBType() != null) { BType type = variable.typeNode.getBType(); - recordGlobalVariableReferenceRelationship(Types.getImpliedType(type).tsymbol); + recordGlobalVariableReferenceRelationship(Types.getReferredType(type).tsymbol); } boolean withInModuleVarLetExpr = symbol.owner.tag == SymTag.LET && isGlobalVarSymbol(env.enclVarSym); if (withInModuleVarLetExpr) { @@ -707,7 +708,9 @@ public void visit(BLangSimpleVariable variable) { if (withInModuleVarLetExpr) { // double pop this.currDependentSymbolDeque.pop(); } - this.currDependentSymbolDeque.pop(); + if (!variable.flagSet.contains(Flag.FIELD)) { + this.currDependentSymbolDeque.pop(); + } } } @@ -1915,7 +1918,6 @@ private boolean isGlobalVarSymbol(BSymbol symbol) { } else if (symbol.owner.tag != SymTag.PACKAGE) { return false; } - return isVariableOrConstant(symbol); } @@ -2245,6 +2247,8 @@ public void visit(BLangObjectTypeNode objectTypeNode) { @Override public void visit(BLangRecordTypeNode recordTypeNode) { BTypeSymbol tsymbol = Types.getImpliedType(recordTypeNode.getBType()).tsymbol; + BSymbol symbol = recordTypeNode.symbol; + recordGlobalVariableReferenceRelationship(symbol); for (TypeNode type : recordTypeNode.getTypeReferences()) { BLangType bLangType = (BLangType) type; analyzeNode(bLangType, env); @@ -2259,6 +2263,7 @@ public void visit(BLangRecordTypeNode recordTypeNode) { } recordGlobalVariableReferenceRelationship(field.symbol); } + analyzeNode(recordTypeNode.restFieldType, env); } private void addTypeDependency(BTypeSymbol dependentTypeSymbol, BType providerType, Set unresolvedTypes) { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/Types.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/Types.java index bf564c232bea..e9ad27b3acda 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/Types.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/Types.java @@ -24,6 +24,7 @@ import org.ballerinalang.model.TreeBuilder; import org.ballerinalang.model.elements.Flag; import org.ballerinalang.model.elements.PackageID; +import org.ballerinalang.model.symbols.SymbolKind; import org.ballerinalang.model.tree.NodeKind; import org.ballerinalang.model.tree.OperatorKind; import org.ballerinalang.model.types.SelectivelyImmutableReferenceType; @@ -149,6 +150,7 @@ import static org.wso2.ballerinalang.compiler.util.TypeTags.NEVER; import static org.wso2.ballerinalang.compiler.util.TypeTags.OBJECT; import static org.wso2.ballerinalang.compiler.util.TypeTags.RECORD; +import static org.wso2.ballerinalang.compiler.util.TypeTags.TUPLE; import static org.wso2.ballerinalang.compiler.util.TypeTags.UNION; import static org.wso2.ballerinalang.compiler.util.TypeTags.isSimpleBasicType; @@ -5383,6 +5385,19 @@ private BType getIntersectionForErrorTypes(IntersectionContext intersectionConte return intersectionErrorType; } + public static boolean isUserDefinedTypeDefinition(BType type) { + type = Types.getReferredType(type); + BTypeSymbol typeSymbol = type.tsymbol; + switch (type.tag) { + case RECORD: + return typeSymbol != null && typeSymbol.owner.getKind() == SymbolKind.PACKAGE; + case TUPLE: + return typeSymbol != null && typeSymbol.name != Names.EMPTY; + default: + return false; + } + } + private BType createRecordIntersection(IntersectionContext intersectionContext, BRecordType recordTypeOne, BRecordType recordTypeTwo, SymbolEnv env, LinkedHashSet visitedTypes) { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/cyclefind/GlobalVariableRefAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/cyclefind/GlobalVariableRefAnalyzer.java index 44910048288e..3570d9ec08f8 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/cyclefind/GlobalVariableRefAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/cyclefind/GlobalVariableRefAnalyzer.java @@ -27,13 +27,21 @@ import org.wso2.ballerinalang.compiler.semantics.model.symbols.BSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BVarSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.SymTag; +import org.wso2.ballerinalang.compiler.tree.BLangAnnotation; import org.wso2.ballerinalang.compiler.tree.BLangClassDefinition; +import org.wso2.ballerinalang.compiler.tree.BLangErrorVariable; import org.wso2.ballerinalang.compiler.tree.BLangFunction; import org.wso2.ballerinalang.compiler.tree.BLangIdentifier; +import org.wso2.ballerinalang.compiler.tree.BLangImportPackage; import org.wso2.ballerinalang.compiler.tree.BLangPackage; +import org.wso2.ballerinalang.compiler.tree.BLangRecordVariable; +import org.wso2.ballerinalang.compiler.tree.BLangResourceFunction; +import org.wso2.ballerinalang.compiler.tree.BLangService; import org.wso2.ballerinalang.compiler.tree.BLangSimpleVariable; +import org.wso2.ballerinalang.compiler.tree.BLangTupleVariable; import org.wso2.ballerinalang.compiler.tree.BLangTypeDefinition; import org.wso2.ballerinalang.compiler.tree.BLangVariable; +import org.wso2.ballerinalang.compiler.tree.BLangXMLNS; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; import org.wso2.ballerinalang.compiler.tree.types.BLangStructureTypeNode; import org.wso2.ballerinalang.compiler.tree.types.BLangType; @@ -241,8 +249,6 @@ public void analyzeAndReOrder(BLangPackage pkgNode, Map> g List globalVarsAndDependentFuncs = getGlobalVariablesAndDependentFunctions(); - pruneDependencyRelations(); - Set sorted = new LinkedHashSet<>(); LinkedList dependencies = new LinkedList<>(); @@ -275,7 +281,7 @@ public void analyzeAndReOrder(BLangPackage pkgNode, Map> g sortConstants(sorted); projectSortToGlobalVarsList(sorted); - projectSortToTopLevelNodesList(); + projectSortToTopLevelNodesList(sorted); } private List analyzeDependenciesStartingFrom(BSymbol symbol) { @@ -298,45 +304,6 @@ private List analyzeDependenciesStartingFrom(BSymbol symbol) { return new ArrayList<>(); } - private void pruneDependencyRelations() { - List dependents = new ArrayList<>(this.globalNodeDependsOn.keySet()); - Set visited = new HashSet<>(); - for (BSymbol dependent : dependents) { - // Taking a copy as we need to modify the original list. - List providers = new ArrayList<>(this.globalNodeDependsOn.get(dependent)); - for (BSymbol provider : providers) { - pruneFunctions(dependent, provider, this.globalNodeDependsOn, visited); - } - } - } - - private void pruneFunctions(BSymbol dependent, BSymbol provider, Map> globalNodeDependsOn, - Set visited) { - if (visited.contains(provider)) { - return; - } else { - visited.add(provider); - } - - // Dependent has a dependency on a global var. - if (provider.tag != SymTag.FUNCTION) { - return; - } - - // Provider is a function. - // And doesn't have dependency on a global variable. We can prune provider. - if (!globalNodeDependsOn.containsKey(provider) || globalNodeDependsOn.get(provider).isEmpty()) { - globalNodeDependsOn.get(dependent).remove(provider); - return; - } - - // Taking a copy as we need to modify the original list. - List providersProviders = new ArrayList<>(globalNodeDependsOn.get(provider)); - for (BSymbol prov : providersProviders) { - pruneFunctions(provider, prov, globalNodeDependsOn, visited); - } - } - private void addDependenciesDependencies(LinkedList dependencies, Set sorted) { // For each dependency if they satisfy their dependencies in sorted list, then add them to sorted list. ArrayList depCopy = new ArrayList<>(dependencies); @@ -348,26 +315,66 @@ private void addDependenciesDependencies(LinkedList dependencies, Set topLevelPositions = new ArrayList<>(); - for (BLangVariable globalVar : pkgNode.globalVars) { - topLevelPositions.add(pkgNode.topLevelNodes.indexOf(globalVar)); + private void projectSortToTopLevelNodesList(Set sorted) { + List orderedTopLevelNodes = new ArrayList<>(); + + for (BSymbol symbol : sorted) { + TopLevelNode matchedNode = findMatchingTopLevelNode(symbol); + if (matchedNode != null) { + orderedTopLevelNodes.add(matchedNode); + } } - topLevelPositions.sort(Comparator.comparingInt(i -> i)); - for (int i = 0; i < topLevelPositions.size(); i++) { - Integer targetIndex = topLevelPositions.get(i); - pkgNode.topLevelNodes.set(targetIndex, pkgNode.globalVars.get(i)); + + reorderTopLevelNodes(orderedTopLevelNodes); + } + + private TopLevelNode findMatchingTopLevelNode(BSymbol symbol) { + for (TopLevelNode topLevelNode : pkgNode.topLevelNodes) { + if (isMatchingNode(topLevelNode, symbol)) { + return topLevelNode; + } } + return null; + } - topLevelPositions = new ArrayList<>(); - for (BLangConstant constant : pkgNode.constants) { - topLevelPositions.add(pkgNode.topLevelNodes.indexOf(constant)); + private boolean isMatchingNode(TopLevelNode topLevelNode, BSymbol symbol) { + switch (topLevelNode.getKind()) { + case VARIABLE: + return ((BLangVariable) topLevelNode).symbol == symbol; + case FUNCTION: + return ((BLangFunction) topLevelNode).symbol == symbol; + case TYPE_DEFINITION: + return ((BLangTypeDefinition) topLevelNode).symbol.getType().tsymbol == symbol; + case CONSTANT: + return ((BLangConstant) topLevelNode).symbol == symbol; + case SERVICE: + return ((BLangService) topLevelNode).symbol == symbol; + case CLASS_DEFN: + return ((BLangClassDefinition) topLevelNode).symbol == symbol; + case TUPLE_VARIABLE: + return ((BLangTupleVariable) topLevelNode).symbol == symbol; + case RECORD_VARIABLE: + return ((BLangRecordVariable) topLevelNode).symbol == symbol; + case ANNOTATION: + return ((BLangAnnotation) topLevelNode).symbol == symbol; + case ERROR_VARIABLE: + return ((BLangErrorVariable) topLevelNode).symbol == symbol; + case RESOURCE_FUNC: + return ((BLangResourceFunction) topLevelNode).symbol == symbol; + case XMLNS: + return ((BLangXMLNS) topLevelNode).symbol == symbol; + case IMPORT: + return ((BLangImportPackage) topLevelNode).symbol == symbol; + default: + return false; } - topLevelPositions.sort(Comparator.comparingInt(i -> i)); - for (int i = 0; i < topLevelPositions.size(); i++) { - Integer targetIndex = topLevelPositions.get(i); - pkgNode.topLevelNodes.set(targetIndex, pkgNode.constants.get(i)); + } + + private void reorderTopLevelNodes(List orderedTopLevelNodes) { + for (int i = orderedTopLevelNodes.size() - 1; i >= 0; i--) { + TopLevelNode topLevelNode = orderedTopLevelNodes.get(i); + pkgNode.topLevelNodes.remove(topLevelNode); + pkgNode.topLevelNodes.add(0, topLevelNode); } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BRecordType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BRecordType.java index a6933f7e6856..8362144a0222 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BRecordType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BRecordType.java @@ -21,10 +21,14 @@ import org.ballerinalang.model.types.TypeKind; import org.wso2.ballerinalang.compiler.semantics.model.TypeVisitor; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BTypeSymbol; +import org.wso2.ballerinalang.compiler.semantics.model.symbols.BVarSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.Symbols; import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.util.Flags; +import java.util.TreeMap; + + /** * {@code BRecordType} represents record type in Ballerina. * @@ -46,6 +50,8 @@ public class BRecordType extends BStructureType implements RecordType { public BRecordType mutableType; + public TreeMap enclMapSymbols; + public BRecordType(BTypeSymbol tSymbol) { super(TypeTags.RECORD, tSymbol); } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangRecordLiteral.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangRecordLiteral.java index 71c9b809f57d..b1f1e09bcf21 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangRecordLiteral.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangRecordLiteral.java @@ -33,7 +33,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.TreeMap; import java.util.stream.Collectors; import static org.ballerinalang.model.tree.NodeKind.RECORD_LITERAL_KEY_VALUE; @@ -293,7 +292,6 @@ public String toString() { public static class BLangStructLiteral extends BLangRecordLiteral { public BAttachedFunction initializer; - public TreeMap enclMapSymbols; public BLangStructLiteral(Location pos, BType structType, BTypeSymbol typeSymbol, List fields) { super(pos); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/ImmutableTypeCloner.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/ImmutableTypeCloner.java index 8b228c227c77..571808ade3a0 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/ImmutableTypeCloner.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/ImmutableTypeCloner.java @@ -32,6 +32,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.symbols.BAttachedFunction; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BObjectTypeSymbol; +import org.wso2.ballerinalang.compiler.semantics.model.symbols.BPackageSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BRecordTypeSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BTypeSymbol; @@ -578,16 +579,17 @@ private static BIntersectionType defineImmutableRecordType(Location pos, BRecord SymbolEnv env, SymbolTable symTable, BLangAnonymousModelHelper anonymousModelHelper, Names names, Types types, Set unresolvedTypes) { - PackageID pkgID = env.enclPkg.symbol.pkgID; + BPackageSymbol packageSymbol = env.enclPkg.symbol; + PackageID pkgID = packageSymbol.pkgID; BTypeSymbol recordTypeSymbol = origRecordType.tsymbol; BRecordTypeSymbol recordSymbol = Symbols.createRecordSymbol(recordTypeSymbol.flags | Flags.READONLY, getImmutableTypeName(names, getSymbolFQN(recordTypeSymbol)), - pkgID, null, env.scope.owner, pos, recordTypeSymbol.origin); + pkgID, null, packageSymbol, pos, recordTypeSymbol.origin); BInvokableType bInvokableType = new BInvokableType(new ArrayList<>(), symTable.nilType, null); BInvokableSymbol initFuncSymbol = Symbols.createFunctionSymbol( - Flags.PUBLIC, Names.EMPTY, Names.EMPTY, env.enclPkg.symbol.pkgID, bInvokableType, env.scope.owner, + Flags.PUBLIC, Names.EMPTY, Names.EMPTY, env.enclPkg.symbol.pkgID, bInvokableType, packageSymbol, false, symTable.builtinPos, VIRTUAL); initFuncSymbol.retType = symTable.nilType; recordSymbol.initializerFunc = new BAttachedFunction(Names.INIT_FUNCTION_SUFFIX, initFuncSymbol, @@ -619,6 +621,18 @@ private static BIntersectionType defineImmutableRecordType(Location pos, BRecord setRestType(types, symTable, anonymousModelHelper, names, immutableRecordType, origRecordType, pos, env, unresolvedTypes); + for (BLangTypeDefinition typeDefinition : env.enclPkg.typeDefinitions) { + BType type = typeDefinition.getBType(); + if (type != null && type.tag != TypeTags.RECORD) { + continue; + } + if (type == originalType) { + BLangRecordTypeNode originRecordType = (BLangRecordTypeNode) typeDefinition.typeNode; + recordTypeNode.isAnonymous = originRecordType.isAnonymous; + recordTypeNode.isLocal = originRecordType.isLocal; + } + } + TypeDefBuilderHelper.createInitFunctionForRecordType(recordTypeNode, env, names, symTable); TypeDefBuilderHelper.addTypeDefinition(immutableRecordType, recordSymbol, recordTypeNode, env); return immutableRecordIntersectionType; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/bir/bir-dump/failLockWithinLock b/tests/jballerina-unit-test/src/test/resources/test-src/bir/bir-dump/failLockWithinLock index 776a8a92d311..c2edbf24fd34 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/bir/bir-dump/failLockWithinLock +++ b/tests/jballerina-unit-test/src/test/resources/test-src/bir/bir-dump/failLockWithinLock @@ -14,7 +14,7 @@ failLockWithinLock function() -> (int, string) { %22(TEMP) string; %23(TEMP) map; %24(LOCAL) error; - %41(TEMP) int; + %40(TEMP) int; %42(TEMP) int; bb0 { @@ -101,10 +101,9 @@ failLockWithinLock function() -> (int, string) { panic %12; } bb19 { - %19 = newType (int, string); - %41 = ConstLoad 2; + %40 = ConstLoad 2; %42 = lockWithinLockInt; - %0 = newArray %19[%41]{%42,lockWithinLockString}; + %0 = newArray typedesc1[%40]{%42,lockWithinLockString}; GOTO bb20; } bb20 { diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/bir/bir-dump/mapInits b/tests/jballerina-unit-test/src/test/resources/test-src/bir/bir-dump/mapInits index c63308da760c..fee7b4cf900c 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/bir/bir-dump/mapInits +++ b/tests/jballerina-unit-test/src/test/resources/test-src/bir/bir-dump/mapInits @@ -3,254 +3,252 @@ mapInits function() -> (string|(), int|()) { %1(LOCAL) map; %2(TEMP) typeDesc; %4(LOCAL) Person; + %6(TEMP) string; %7(TEMP) string; %8(TEMP) string; - %9(TEMP) string; - %10(TEMP) int; + %9(TEMP) int; + %10(TEMP) string; %11(TEMP) string; - %12(TEMP) string; - %13(TEMP) Employee; - %20(SYNTHETIC) string|(); - %21(SYNTHETIC) Employee|(); - %25(SYNTHETIC) Employee|(); - %27(SYNTHETIC) boolean; - %28(SYNTHETIC) boolean; - %29(SYNTHETIC) any|error; - %30(TEMP) boolean; - %42(SYNTHETIC) boolean; - %43(SYNTHETIC) boolean; - %44(SYNTHETIC) any|error; - %60(SYNTHETIC) boolean; - %61(SYNTHETIC) boolean; - %71(TEMP) (); - %73(SYNTHETIC) int|(); - %74(SYNTHETIC) Employee|(); - %78(SYNTHETIC) Employee|(); - %80(SYNTHETIC) boolean; - %81(SYNTHETIC) boolean; - %82(SYNTHETIC) any|error; - %95(SYNTHETIC) boolean; - %96(SYNTHETIC) boolean; - %97(SYNTHETIC) any|error; - %109(TEMP) int; - %113(SYNTHETIC) boolean; - %114(SYNTHETIC) boolean; + %12(TEMP) Employee; + %18(SYNTHETIC) string|(); + %19(SYNTHETIC) Employee|(); + %23(SYNTHETIC) Employee|(); + %25(SYNTHETIC) boolean; + %26(SYNTHETIC) boolean; + %27(SYNTHETIC) any|error; + %28(TEMP) boolean; + %40(SYNTHETIC) boolean; + %41(SYNTHETIC) boolean; + %42(SYNTHETIC) any|error; + %58(SYNTHETIC) boolean; + %59(SYNTHETIC) boolean; + %69(TEMP) (); + %71(SYNTHETIC) int|(); + %72(SYNTHETIC) Employee|(); + %76(SYNTHETIC) Employee|(); + %78(SYNTHETIC) boolean; + %79(SYNTHETIC) boolean; + %80(SYNTHETIC) any|error; + %93(SYNTHETIC) boolean; + %94(SYNTHETIC) boolean; + %95(SYNTHETIC) any|error; + %107(TEMP) int; + %111(SYNTHETIC) boolean; + %112(SYNTHETIC) boolean; bb0 { %2 = newType map; - %1 = NewMap %2{}; - %2 = newType Person; - %7 = ConstLoad name; - %8 = ConstLoad Jack; - %9 = ConstLoad age; - %10 = ConstLoad 25; - %11 = ConstLoad address; - %12 = ConstLoad Usa; - %4 = NewMap %2{%7:%8,%9:%10,%11:%12}; - %13 = %4; + %1 = NewMap %2; + %6 = ConstLoad name; + %7 = ConstLoad Jack; + %8 = ConstLoad age; + %9 = ConstLoad 25; + %10 = ConstLoad address; + %11 = ConstLoad Usa; + %4 = NewMap %5; + %12 = %4; + %6 = ConstLoad jack; + %1[%6] = %12; + %9 = ConstLoad 2; %7 = ConstLoad jack; - %1[%7] = %13; - %2 = newType (string|(), int|()); - %10 = ConstLoad 2; - %8 = ConstLoad jack; - %21 = %1[%8]; - %25 = %21; - %30 = ConstLoad true; - %30? bb1 : bb2; + %19 = %1[%7]; + %23 = %19; + %28 = ConstLoad true; + %28? bb1 : bb2; } bb1 { - %28 = ConstLoad true; - %29 = %25; + %26 = ConstLoad true; + %27 = %23; GOTO bb3; } bb2 { - %28 = ConstLoad false; + %26 = ConstLoad false; GOTO bb3; } bb3 { - %28? bb4 : bb5; + %26? bb4 : bb5; } bb4 { - %27 = %29 is (); + %25 = %27 is (); GOTO bb6; } bb5 { - %27 = ConstLoad false; + %25 = ConstLoad false; GOTO bb6; } bb6 { - %27? bb7 : bb8; + %25? bb7 : bb8; } bb7 { - %20 = %29; + %18 = %27; GOTO bb24; } bb8 { - %30 = ConstLoad true; - %30? bb9 : bb10; + %28 = ConstLoad true; + %28? bb9 : bb10; } bb9 { - %43 = ConstLoad true; - %44 = %25; + %41 = ConstLoad true; + %42 = %23; GOTO bb11; } bb10 { - %43 = ConstLoad false; + %41 = ConstLoad false; GOTO bb11; } bb11 { - %43? bb12 : bb13; + %41? bb12 : bb13; } bb12 { - %42 = %44 is Employee; + %40 = %42 is Employee; GOTO bb14; } bb13 { - %42 = ConstLoad false; + %40 = ConstLoad false; GOTO bb14; } bb14 { - %42? bb15 : bb16; + %40? bb15 : bb16; } bb15 { - %13 = %44; - %9 = ConstLoad name; - %11 = %13[%9]; - %20 = %11; + %12 = %42; + %8 = ConstLoad name; + %10 = %12[%8]; + %18 = %10; GOTO bb24; } bb16 { - %30 = ConstLoad true; - %30? bb17 : bb18; + %28 = ConstLoad true; + %28? bb17 : bb18; } bb17 { - %61 = ConstLoad true; + %59 = ConstLoad true; GOTO bb19; } bb18 { - %61 = %25 is any; + %59 = %23 is any; GOTO bb19; } bb19 { - %61? bb20 : bb21; + %59? bb20 : bb21; } bb20 { - %60 = ConstLoad true; + %58 = ConstLoad true; GOTO bb22; } bb21 { - %60 = ConstLoad false; + %58 = ConstLoad false; GOTO bb22; } bb22 { - %60? bb23 : bb24; + %58? bb23 : bb24; } bb23 { - %71 = ConstLoad 0; - %20 = %71; + %69 = ConstLoad 0; + %18 = %69; GOTO bb24; } bb24 { - %12 = ConstLoad jack; - %74 = %1[%12]; - %78 = %74; - %30 = ConstLoad true; - %30? bb25 : bb26; + %11 = ConstLoad jack; + %72 = %1[%11]; + %76 = %72; + %28 = ConstLoad true; + %28? bb25 : bb26; } bb25 { - %81 = ConstLoad true; - %82 = %78; + %79 = ConstLoad true; + %80 = %76; GOTO bb27; } bb26 { - %81 = ConstLoad false; + %79 = ConstLoad false; GOTO bb27; } bb27 { - %81? bb28 : bb29; + %79? bb28 : bb29; } bb28 { - %80 = %82 is (); + %78 = %80 is (); GOTO bb30; } bb29 { - %80 = ConstLoad false; + %78 = ConstLoad false; GOTO bb30; } bb30 { - %80? bb31 : bb32; + %78? bb31 : bb32; } bb31 { - %73 = %82; + %71 = %80; GOTO bb48; } bb32 { - %30 = ConstLoad true; - %30? bb33 : bb34; + %28 = ConstLoad true; + %28? bb33 : bb34; } bb33 { - %96 = ConstLoad true; - %97 = %78; + %94 = ConstLoad true; + %95 = %76; GOTO bb35; } bb34 { - %96 = ConstLoad false; + %94 = ConstLoad false; GOTO bb35; } bb35 { - %96? bb36 : bb37; + %94? bb36 : bb37; } bb36 { - %95 = %97 is Employee; + %93 = %95 is Employee; GOTO bb38; } bb37 { - %95 = ConstLoad false; + %93 = ConstLoad false; GOTO bb38; } bb38 { - %95? bb39 : bb40; + %93? bb39 : bb40; } bb39 { - %13 = %97; - %7 = ConstLoad age; - %109 = %13[%7]; - %73 = %109; + %12 = %95; + %6 = ConstLoad age; + %107 = %12[%6]; + %71 = %107; GOTO bb48; } bb40 { - %30 = ConstLoad true; - %30? bb41 : bb42; + %28 = ConstLoad true; + %28? bb41 : bb42; } bb41 { - %114 = ConstLoad true; + %112 = ConstLoad true; GOTO bb43; } bb42 { - %114 = %78 is any; + %112 = %76 is any; GOTO bb43; } bb43 { - %114? bb44 : bb45; + %112? bb44 : bb45; } bb44 { - %113 = ConstLoad true; + %111 = ConstLoad true; GOTO bb46; } bb45 { - %113 = ConstLoad false; + %111 = ConstLoad false; GOTO bb46; } bb46 { - %113? bb47 : bb48; + %111? bb47 : bb48; } bb47 { - %71 = ConstLoad 0; - %73 = %71; + %69 = ConstLoad 0; + %71 = %69; GOTO bb48; } bb48 { - %0 = newArray %2[%10]{%20,%73}; + %0 = newArray typedesc0[%9]{%20,%73}; GOTO bb49; } bb49 {