diff --git a/.github/workflows/pull_request_full_build.yml b/.github/workflows/pull_request_full_build.yml index 5274b8db061b..e030a42767f7 100644 --- a/.github/workflows/pull_request_full_build.yml +++ b/.github/workflows/pull_request_full_build.yml @@ -4,10 +4,9 @@ on: pull_request: branches: - master - - java21 - - nutcracker - 2201.[0-9]+.x - 2201.[0-9]+.[0-9]+-stage + jobs: build-lang: name: Build Ballerina Lang diff --git a/.github/workflows/pull_request_ubuntu_build.yml b/.github/workflows/pull_request_ubuntu_build.yml index 8d5e95ff9859..9dc7752bc97b 100644 --- a/.github/workflows/pull_request_ubuntu_build.yml +++ b/.github/workflows/pull_request_ubuntu_build.yml @@ -15,8 +15,6 @@ on: - native-build - revert-client-decl-master - query-grouping-aggregation - - java21 - - nutcracker jobs: ubuntu_build: diff --git a/.github/workflows/pull_request_windows_build.yml b/.github/workflows/pull_request_windows_build.yml index 9aad32f64b00..6d0ee04e42a7 100644 --- a/.github/workflows/pull_request_windows_build.yml +++ b/.github/workflows/pull_request_windows_build.yml @@ -15,9 +15,6 @@ on: - native-build - revert-client-decl-master - query-grouping-aggregation - - java21 - - nutcracker - jobs: windows_build: name: Build with some tests on Windows diff --git a/ballerina-shell/modules/shell-cli/src/test/resources/testcases/operations.cast.json b/ballerina-shell/modules/shell-cli/src/test/resources/testcases/operations.cast.json index bcfb9d35a014..a687fab378e1 100644 --- a/ballerina-shell/modules/shell-cli/src/test/resources/testcases/operations.cast.json +++ b/ballerina-shell/modules/shell-cli/src/test/resources/testcases/operations.cast.json @@ -1,15 +1,15 @@ [ { "description": "Define types.", - "code": "type PersonOP record { string name; int age; }; type EmployeeOP record { string name; int age; int empNo; }; type DepartmentOP record { string code; };" + "code": "type Person record { string name; int age; }; type Employee record { string name; int age; int empNo; }; type Department record { string code; };" }, { "description": "Define employee.", - "code": "EmployeeOP employee = {name: \"Jane Doe\", age: 25, empNo: 1};" + "code": "Employee employee = {name: \"Jane Doe\", age: 25, empNo: 1};" }, { "description": "Cas employee to person.", - "code": "PersonOP person = employee;" + "code": "Person person = employee;" }, { "description": "Cas employee to person - get value.", @@ -18,7 +18,7 @@ }, { "description": "Recast back to employee.", - "code": "EmployeeOP employeeTwo = person;" + "code": "Employee employeeTwo = person;" }, { "description": "Recast back to employee - get value.", diff --git a/ballerina-shell/modules/shell-cli/src/test/resources/testcases/operations.equality.json b/ballerina-shell/modules/shell-cli/src/test/resources/testcases/operations.equality.json index fe87ea575eef..75c3e634644d 100644 --- a/ballerina-shell/modules/shell-cli/src/test/resources/testcases/operations.equality.json +++ b/ballerina-shell/modules/shell-cli/src/test/resources/testcases/operations.equality.json @@ -1,15 +1,15 @@ [ { "description": "Define types.", - "code": "type EmployeeEQ record { string name; int id; }; type PersonEQ record { string name; };" + "code": "type Employee record { string name; int id; }; type Person record { string name; };" }, { "description": "Define employee.", - "code": "final EmployeeEQ moduleEmployee = {name: \"John\", id: 2102};" + "code": "final Employee moduleEmployee = {name: \"John\", id: 2102};" }, { "description": "Define module ref getter.", - "code": "function getModuleEmployee() returns EmployeeEQ { return moduleEmployee; }" + "code": "function getModuleEmployee() returns Employee { return moduleEmployee; }" }, { "description": "Equality ==.", @@ -49,7 +49,7 @@ }, { "description": "Deep inequality in records.", - "code": "EmployeeEQ e1 = {name: \"Jane\", id: 1100}; EmployeeEQ e2 = {name: \"Jane\", id: 1100};" + "code": "Employee e1 = {name: \"Jane\", id: 1100}; Employee e2 = {name: \"Jane\", id: 1100};" }, { "description": "Deep inequality in records. - get value", @@ -58,7 +58,7 @@ }, { "description": "Deep equality in records.", - "code": "EmployeeEQ e3 = {name: \"Anne\", id: 1100};" + "code": "Employee e3 = {name: \"Anne\", id: 1100};" }, { "description": "Deep equality in records. - get value", @@ -67,7 +67,7 @@ }, { "description": "Reference equality ===.", - "code": "EmployeeEQ e4 = getModuleEmployee(); PersonEQ e5 = getModuleEmployee();" + "code": "Employee e4 = getModuleEmployee(); Person e5 = getModuleEmployee();" }, { "description": "Reference equality ===. - get value", diff --git a/ballerina-shell/modules/shell-core/src/test/resources/testcases/evaluator/operations.clone.json b/ballerina-shell/modules/shell-core/src/test/resources/testcases/evaluator/operations.clone.json index 2c6d6586bd66..9c13311bedf4 100644 --- a/ballerina-shell/modules/shell-core/src/test/resources/testcases/evaluator/operations.clone.json +++ b/ballerina-shell/modules/shell-core/src/test/resources/testcases/evaluator/operations.clone.json @@ -1,19 +1,19 @@ [ { "description": "Define types.", - "code": "type AddressCloneTest record { string country; string state; string city; string street; }; type PersonCloneTest record { string name; int age; boolean married; float salary; AddressCloneTest address; };" + "code": "type Address record { string country; string state; string city; string street; }; type Person record { string name; int age; boolean married; float salary; Address address; };" }, { "description": "Define address.", - "code": "AddressCloneTest address = { country: \"USA\", state: \"NC\", city: \"Raleigh\", street: \"Daniels St\" };" + "code": "Address address = { country: \"USA\", state: \"NC\", city: \"Raleigh\", street: \"Daniels St\" };" }, { "description": "Define person.", - "code": "PersonCloneTest person = { name: \"Alex\", age: 24, married: false, salary: 8000.0, address: address };" + "code": "Person person = { name: \"Alex\", age: 24, married: false, salary: 8000.0, address: address };" }, { "description": "Clone operation.", - "code": "PersonCloneTest result = person.clone();" + "code": "Person result = person.clone();" }, { "description": "Check reference equality.", diff --git a/ballerina-shell/modules/shell-core/src/test/resources/testcases/evaluator/operations.immutable.json b/ballerina-shell/modules/shell-core/src/test/resources/testcases/evaluator/operations.immutable.json index 870e6107df20..5e1fbfa5298b 100644 --- a/ballerina-shell/modules/shell-core/src/test/resources/testcases/evaluator/operations.immutable.json +++ b/ballerina-shell/modules/shell-core/src/test/resources/testcases/evaluator/operations.immutable.json @@ -1,11 +1,11 @@ [ { "description": "Define Details.", - "code": "type DetailsImmutableTest record {| string name; int id; |};" + "code": "type Details record {| string name; int id; |};" }, { "description": "Define Student.", - "code": "type StudentImmutableTest record {| int 'class; DetailsImmutableTest details; map marks; |};" + "code": "type Student record {| int 'class; Details details; map marks; |};" }, { "description": "Define addEntryToMap.", @@ -13,11 +13,11 @@ }, { "description": "Define immutable Details", - "code": "DetailsImmutableTest & readonly immutableDetails = { name: \"May\", id: 112233 };" + "code": "Details & readonly immutableDetails = { name: \"May\", id: 112233 };" }, { "description": "Define immutable Student &", - "code": "StudentImmutableTest & readonly student = { 'class: 12, details: immutableDetails, marks: { math: 80, physics: 85, chemistry: 75 } };" + "code": "Student & readonly student = { 'class: 12, details: immutableDetails, marks: { math: 80, physics: 85, chemistry: 75 } };" }, { "description": "Readonly status of student.", diff --git a/bvm/ballerina-rt/build.gradle b/bvm/ballerina-rt/build.gradle index 2cd3db732bbe..5d0623d9c4f6 100644 --- a/bvm/ballerina-rt/build.gradle +++ b/bvm/ballerina-rt/build.gradle @@ -80,7 +80,6 @@ dependencies { dist project(':ballerina-lang:regexp') dist project(':ballerina-lang:jballerina.java') dist project(':ballerina-shell:shell-rt') - dist project(':semtypes') // Third party jars // config diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/constants/RuntimeConstants.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/constants/RuntimeConstants.java index 7b8b06a95715..9dd918efebe1 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/constants/RuntimeConstants.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/constants/RuntimeConstants.java @@ -90,8 +90,6 @@ public final class RuntimeConstants { // Empty value for string public static final BString STRING_EMPTY_VALUE = StringUtils.fromString(""); - public static final Long INT_MAX_VALUE = 9223372036854775807L; - public static final Long INT_MIN_VALUE = -9223372036854775807L - 1L; public static final Integer BBYTE_MIN_VALUE = 0; public static final Integer BBYTE_MAX_VALUE = 255; public static final Integer SIGNED32_MAX_VALUE = 2147483647; diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/creators/TypeCreator.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/creators/TypeCreator.java index e1a627bbf879..b041914300b6 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/creators/TypeCreator.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/creators/TypeCreator.java @@ -50,7 +50,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; /** * Class @{@link TypeCreator} provides APIs to create ballerina type instances. @@ -59,7 +58,6 @@ */ public final class TypeCreator { - private static final RecordTypeCache registeredRecordTypes = new RecordTypeCache(); /** * Creates a new array type with given element type. * @@ -149,7 +147,7 @@ public static TupleType createTupleType(List typeList, Type restType, int * @return the new tuple type */ public static TupleType createTupleType(List typeList, Type restType, - int typeFlags, boolean isCyclic, boolean readonly) { + int typeFlags, boolean isCyclic, boolean readonly) { return new BTupleType(typeList, restType, typeFlags, isCyclic, readonly); } @@ -164,16 +162,16 @@ public static TupleType createTupleType(List typeList, Type restType, * @return the new tuple type */ public static TupleType createTupleType(String name, Module pkg, - int typeFlags, boolean isCyclic, boolean readonly) { + int typeFlags, boolean isCyclic, boolean readonly) { return new BTupleType(name, pkg, typeFlags, isCyclic, readonly); } /** - * Create a {@code MapType} which represents the map type. - * - * @param constraint constraint type which particular map is bound to. - * @return the new map type - */ + * Create a {@code MapType} which represents the map type. + * + * @param constraint constraint type which particular map is bound to. + * @return the new map type + */ public static MapType createMapType(Type constraint) { return new BMapType(constraint); } @@ -226,10 +224,6 @@ public static MapType createMapType(String typeName, Type constraint, Module mod */ public static RecordType createRecordType(String typeName, Module module, long flags, boolean sealed, int typeFlags) { - BRecordType memo = registeredRecordType(typeName, module); - if (memo != null) { - return memo; - } return new BRecordType(typeName, typeName, module, flags, sealed, typeFlags); } @@ -246,11 +240,8 @@ public static RecordType createRecordType(String typeName, Module module, long f * @return the new record type */ public static RecordType createRecordType(String typeName, Module module, long flags, Map fields, - Type restFieldType, boolean sealed, int typeFlags) { - BRecordType memo = registeredRecordType(typeName, module); - if (memo != null) { - return memo; - } + Type restFieldType, + boolean sealed, int typeFlags) { return new BRecordType(typeName, module, flags, fields, restFieldType, sealed, typeFlags); } @@ -529,45 +520,4 @@ public static FiniteType createFiniteType(String typeName, Set values, i private TypeCreator() { } - - private static BRecordType registeredRecordType(String typeName, Module pkg) { - if (typeName == null || pkg == null) { - return null; - } - return registeredRecordTypes.get(new TypeIdentifier(typeName, pkg)); - } - - public static void registerRecordType(BRecordType recordType) { - String name = recordType.getName(); - Module pkg = recordType.getPackage(); - if (name == null || pkg == null) { - return; - } - if (name.contains("$anon")) { - return; - } - TypeIdentifier typeIdentifier = new TypeIdentifier(name, pkg); - registeredRecordTypes.put(typeIdentifier, recordType); - } - - private static final class RecordTypeCache { - - private static final Map cache = new ConcurrentHashMap<>(); - - BRecordType get(TypeIdentifier key) { - return cache.get(key); - } - - void put(TypeIdentifier identifier, BRecordType value) { - cache.put(identifier, value); - } - } - - public record TypeIdentifier(String typeName, Module pkg) { - - public TypeIdentifier { - assert typeName != null; - assert pkg != null; - } - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/PredefinedTypes.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/PredefinedTypes.java index 00cee703124c..6541d6aa9811 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/PredefinedTypes.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/PredefinedTypes.java @@ -64,7 +64,7 @@ */ public final class PredefinedTypes { - public static final Module EMPTY_MODULE = new Module(null, null, null); + private static final Module EMPTY_MODULE = new Module(null, null, null); public static final IntegerType TYPE_INT = new BIntegerType(TypeConstants.INT_TNAME, EMPTY_MODULE); public static final IntegerType TYPE_INT_SIGNED_8 = diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/TypeTags.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/TypeTags.java index daf201901bd6..ebd78439ded5 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/TypeTags.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/TypeTags.java @@ -92,9 +92,10 @@ private TypeTags() { } public static boolean isIntegerTypeTag(int tag) { + + // TODO : Fix byte type. Ideally, byte belongs to here. But we have modeled it differently. return switch (tag) { - case BYTE_TAG, - INT_TAG, + case INT_TAG, SIGNED32_INT_TAG, SIGNED16_INT_TAG, SIGNED8_INT_TAG, diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Atom.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Atom.java deleted file mode 100644 index 0ddea623de6c..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Atom.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.api.types.semtype; - -/** - * Represent the BDD atom. - * - * @since 2201.11.0 - */ -public sealed interface Atom permits RecAtom, TypeAtom { - - /** - * Get the index of the atom. For {@code TypeAtoms} this is a unique index within the {@code Env}. Each - * {@code RecAtom} that points to the same {@code TypeAtom} will have the same index. - * - * @return index of the atom - */ - int index(); -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/AtomicType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/AtomicType.java deleted file mode 100644 index 7e5163fa8a78..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/AtomicType.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.api.types.semtype; - -import io.ballerina.runtime.internal.types.semtype.CellAtomicType; -import io.ballerina.runtime.internal.types.semtype.FunctionAtomicType; -import io.ballerina.runtime.internal.types.semtype.ListAtomicType; -import io.ballerina.runtime.internal.types.semtype.MappingAtomicType; - -/** - * Marker type representing AtomicType. - * - * @since 2201.11.0 - */ -public sealed interface AtomicType permits CellAtomicType, FunctionAtomicType, ListAtomicType, MappingAtomicType { - -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BasicTypeBitSet.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BasicTypeBitSet.java deleted file mode 100644 index f3fd6f57048b..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BasicTypeBitSet.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.ballerina.runtime.api.types.semtype; - -abstract sealed class BasicTypeBitSet permits SemType { - - private int all; - - protected BasicTypeBitSet(int all) { - this.all = all; - } - - protected void setAll(int all) { - this.all = all; - } - - public final int all() { - assert all != -1 : "SemType created by no arg constructor must be initialized with setAll"; - return all; - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BasicTypeCode.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BasicTypeCode.java deleted file mode 100644 index c9158bce4bf5..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BasicTypeCode.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.api.types.semtype; - -/** - * Represent bit field that indicate which basic type a semType belongs to. - * - * @since 2201.11.0 - */ -public final class BasicTypeCode { - - public static final int CODE_NIL = 0x00; - public static final int CODE_BOOLEAN = 0x01; - public static final int CODE_INT = 0x02; - public static final int CODE_FLOAT = 0x03; - public static final int CODE_DECIMAL = 0x04; - public static final int CODE_STRING = 0x05; - public static final int CODE_ERROR = 0x06; - public static final int CODE_TYPEDESC = 0x07; - public static final int CODE_HANDLE = 0x08; - public static final int CODE_FUNCTION = 0x09; - public static final int CODE_REGEXP = 0x0A; - public static final int CODE_FUTURE = 0x0B; - public static final int CODE_STREAM = 0x0C; - public static final int CODE_LIST = 0x0D; - public static final int CODE_MAPPING = 0x0E; - public static final int CODE_TABLE = 0x0F; - public static final int CODE_XML = 0x10; - public static final int CODE_OBJECT = 0x11; - public static final int CODE_CELL = 0x12; - public static final int CODE_UNDEF = 0x13; - - // Inherently immutable - public static final BasicTypeCode BT_NIL = get(CODE_NIL); - public static final BasicTypeCode BT_BOOLEAN = get(CODE_BOOLEAN); - public static final BasicTypeCode BT_INT = get(CODE_INT); - public static final BasicTypeCode BT_FLOAT = get(CODE_FLOAT); - public static final BasicTypeCode BT_DECIMAL = get(CODE_DECIMAL); - public static final BasicTypeCode BT_STRING = get(CODE_STRING); - public static final BasicTypeCode BT_ERROR = get(CODE_ERROR); - public static final BasicTypeCode BT_TYPEDESC = get(CODE_TYPEDESC); - public static final BasicTypeCode BT_HANDLE = get(CODE_HANDLE); - public static final BasicTypeCode BT_FUNCTION = get(CODE_FUNCTION); - public static final BasicTypeCode BT_REGEXP = get(CODE_REGEXP); - - // Inherently mutable - public static final BasicTypeCode BT_FUTURE = get(CODE_FUTURE); - public static final BasicTypeCode BT_STREAM = get(CODE_STREAM); - - // Selectively immutable - public static final BasicTypeCode BT_LIST = get(CODE_LIST); - public static final BasicTypeCode BT_MAPPING = get(CODE_MAPPING); - public static final BasicTypeCode BT_TABLE = get(CODE_TABLE); - public static final BasicTypeCode BT_XML = get(CODE_XML); - public static final BasicTypeCode BT_OBJECT = get(CODE_OBJECT); - - // Non-val - public static final BasicTypeCode BT_CELL = get(CODE_CELL); - public static final BasicTypeCode BT_UNDEF = get(CODE_UNDEF); - - // Helper bit fields (does not represent basic type tag) - static final int VT_COUNT = CODE_OBJECT + 1; - public static final int BASIC_TYPE_MASK = (1 << (CODE_STRING + 1)) - 1; - public static final int VT_MASK = (1 << VT_COUNT) - 1; - - static final int VT_COUNT_INHERENTLY_IMMUTABLE = CODE_FUTURE; - public static final int VT_INHERENTLY_IMMUTABLE = (1 << VT_COUNT_INHERENTLY_IMMUTABLE) - 1; - - private final int code; - - private BasicTypeCode(int code) { - this.code = code; - } - - public static BasicTypeCode get(int code) { - if (BasicTypeCodeCache.isCached(code)) { - return BasicTypeCodeCache.cache[code]; - } - return new BasicTypeCode(code); - } - - public int code() { - return code; - } - - @Override - public int hashCode() { - return code; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof BasicTypeCode other) { - return code == other.code; - } - return false; - } - - private static final class BasicTypeCodeCache { - - private static final BasicTypeCode[] cache; - static { - cache = new BasicTypeCode[CODE_UNDEF + 2]; - for (int i = CODE_NIL; i < CODE_UNDEF + 1; i++) { - cache[i] = new BasicTypeCode(i); - } - } - - private static boolean isCached(int code) { - return 0 < code && code < VT_COUNT; - } - - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Bdd.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Bdd.java deleted file mode 100644 index 2573230f05a8..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Bdd.java +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.api.types.semtype; - -import io.ballerina.runtime.internal.types.semtype.SubTypeData; - -import static io.ballerina.runtime.api.types.semtype.Conjunction.and; - -/** - * Represent BDD node. Subtypes that uses BDDs to represent subtypes such as - * list, mapping and cell should implement - * their own {@code SubType} implementation that wraps an implementation of this - * class. - * - * @since 2201.11.0 - */ -public abstract sealed class Bdd extends SubType implements SubTypeData permits BddAllOrNothing, BddNode { - - Bdd(boolean all, boolean nothing) { - super(all, nothing); - } - - @Override - public SubType union(SubType other) { - return bddUnion((Bdd) other); - } - - private Bdd bddUnion(Bdd other) { - if (other == this) { - return this; - } else if (this == BddAllOrNothing.ALL || other == BddAllOrNothing.ALL) { - return BddAllOrNothing.ALL; - } else if (other == BddAllOrNothing.NOTHING) { - return this; - } else if (this == BddAllOrNothing.NOTHING) { - return other; - } - BddNode b1Bdd = (BddNode) this; - BddNode b2Bdd = (BddNode) other; - int cmp = atomCmp(b1Bdd.atom(), b2Bdd.atom()); - if (cmp < 0) { - return bddCreate(b1Bdd.atom(), - b1Bdd.left(), - b1Bdd.middle().bddUnion(other), - b1Bdd.right()); - } else if (cmp > 0) { - return bddCreate(b2Bdd.atom(), - b2Bdd.left(), - this.bddUnion(b2Bdd.middle()), - b2Bdd.right()); - } else { - return bddCreate(b1Bdd.atom(), - b1Bdd.left().bddUnion(b2Bdd.left()), - b1Bdd.middle().bddUnion(b2Bdd.middle()), - b1Bdd.right().bddUnion(b2Bdd.right())); - } - } - - private int atomCmp(Atom a1, Atom a2) { - if (a1 instanceof RecAtom r1) { - if (a2 instanceof RecAtom r2) { - return r1.index() - r2.index(); - } else { - return -1; - } - } else if (a2 instanceof RecAtom) { - return 1; - } else { - return a1.index() - a2.index(); - } - } - - @Override - public SubType intersect(SubType other) { - return bddIntersect((Bdd) other); - } - - private Bdd bddIntersect(Bdd other) { - if (other == this) { - return this; - } else if (this == BddAllOrNothing.NOTHING || other == BddAllOrNothing.NOTHING) { - return BddAllOrNothing.NOTHING; - } else if (other == BddAllOrNothing.ALL) { - return this; - } else if (this == BddAllOrNothing.ALL) { - return other; - } - BddNode b1Bdd = (BddNode) this; - BddNode b2Bdd = (BddNode) other; - int cmp = atomCmp(b1Bdd.atom(), b2Bdd.atom()); - if (cmp < 0) { - return bddCreate(b1Bdd.atom(), - b1Bdd.left().bddIntersect(other), - b1Bdd.middle().bddIntersect(other), - b1Bdd.right().bddIntersect(other)); - } else if (cmp > 0) { - return bddCreate(b2Bdd.atom(), - this.bddIntersect(b2Bdd.left()), - this.bddIntersect(b2Bdd.middle()), - this.bddIntersect(b2Bdd.right())); - } else { - return bddCreate(b1Bdd.atom(), - b1Bdd.left().bddUnion(b1Bdd.middle()).bddIntersect(b2Bdd.left().bddUnion(b2Bdd.middle())), - BddAllOrNothing.NOTHING, - b1Bdd.right().bddUnion(b1Bdd.middle()).bddIntersect(b2Bdd.right().bddUnion(b2Bdd.middle()))); - } - } - - @Override - public SubType diff(SubType other) { - return bddDiff((Bdd) other); - } - - private Bdd bddDiff(Bdd other) { - if (this == other || other == BddAllOrNothing.ALL || this == BddAllOrNothing.NOTHING) { - return BddAllOrNothing.NOTHING; - } else if (other == BddAllOrNothing.NOTHING) { - return this; - } else if (this == BddAllOrNothing.ALL) { - return other.bddComplement(); - } - BddNode b1Bdd = (BddNode) this; - BddNode b2Bdd = (BddNode) other; - int cmp = atomCmp(b1Bdd.atom(), b2Bdd.atom()); - if (cmp < 0L) { - return bddCreate(b1Bdd.atom(), - b1Bdd.left().bddUnion(b1Bdd.middle()).bddDiff(other), - BddAllOrNothing.NOTHING, - b1Bdd.right().bddUnion(b1Bdd.middle()).bddDiff(other)); - } else if (cmp > 0L) { - return bddCreate(b2Bdd.atom(), - this.bddDiff(b2Bdd.left().bddUnion(b2Bdd.middle())), - BddAllOrNothing.NOTHING, - this.bddDiff(b2Bdd.right().bddUnion(b2Bdd.middle()))); - } else { - // There is an error in the Castagna paper for this formula. - // The union needs to be materialized here. - // The original formula does not work in a case like (a0|a1) - a0. - // Castagna confirms that the following formula is the correct one. - return bddCreate(b1Bdd.atom(), - b1Bdd.left().bddUnion(b1Bdd.middle()).bddDiff(b2Bdd.left().bddUnion(b2Bdd.middle())), - BddAllOrNothing.NOTHING, - b1Bdd.right().bddUnion(b1Bdd.middle()).bddDiff(b2Bdd.right().bddUnion(b2Bdd.middle()))); - } - } - - @Override - public SubType complement() { - return bddComplement(); - } - - private Bdd bddComplement() { - if (this == BddAllOrNothing.ALL) { - return BddAllOrNothing.NOTHING; - } else if (this == BddAllOrNothing.NOTHING) { - return BddAllOrNothing.ALL; - } - Bdd nothing = BddAllOrNothing.NOTHING; - BddNode b = (BddNode) this; - if (b.right() == nothing) { - return bddCreate(b.atom(), - nothing, - b.left().bddUnion(b.middle()).bddComplement(), - b.middle().bddComplement()); - } else if (b.left() == nothing) { - return bddCreate(b.atom(), - b.middle().bddComplement(), - b.right().bddUnion(b.middle()).bddComplement(), - nothing); - } else if (b.middle() == nothing) { - return bddCreate(b.atom(), - b.left().bddComplement(), - b.left().bddUnion(b.right()).bddComplement(), - b.right().bddComplement()); - } else { - // There is a typo in the Frisch PhD thesis for this formula. - // (It has left and right swapped.) - // Castagna (the PhD supervisor) confirms that this is the correct formula. - return bddCreate(b.atom(), - b.left().bddUnion(b.middle()).bddComplement(), - nothing, - b.right().bddUnion(b.middle()).bddComplement()); - } - } - - private Bdd bddCreate(Atom atom, Bdd left, Bdd middle, Bdd right) { - if (middle == BddAllOrNothing.ALL) { - return middle; - } - if (left.equals(right)) { - return left.bddUnion(right); - } - - return new BddNodeImpl(atom, left, middle, right); - } - - @Override - public boolean isEmpty(Context cx) { - // Basic types that uses Bdd as a delegate should implement isEmpty instead. - throw new IllegalStateException("Bdd don't support isEmpty"); - } - - @Override - public SubTypeData data() { - // Basic types that uses Bdd (and has a meaningful data part) as a delegate should implement data instead. - throw new IllegalStateException("Bdd don't support data"); - } - - public static boolean bddEvery(Context cx, Bdd b, BddPredicate predicate) { - return bddEvery(cx, b, null, null, predicate); - } - - private static boolean bddEvery(Context cx, Bdd b, Conjunction pos, Conjunction neg, BddPredicate predicate) { - if (b instanceof BddAllOrNothing allOrNothing) { - return allOrNothing == BddAllOrNothing.NOTHING || predicate.apply(cx, pos, neg); - } - BddNode bn = (BddNode) b; - return bddEvery(cx, bn.left(), and(bn.atom(), pos), neg, predicate) - && bddEvery(cx, bn.middle(), pos, neg, predicate) - && bddEvery(cx, bn.right(), pos, and(bn.atom(), neg), predicate); - } - - public static boolean bddEveryPositive(Context cx, Bdd b, Conjunction pos, Conjunction neg, - BddPredicate predicate) { - if (b instanceof BddAllOrNothing allOrNothing) { - return allOrNothing == BddAllOrNothing.NOTHING || predicate.apply(cx, pos, neg); - } else { - BddNode bn = (BddNode) b; - return bddEveryPositive(cx, bn.left(), andIfPositive(bn.atom(), pos), neg, predicate) - && bddEveryPositive(cx, bn.middle(), pos, neg, predicate) - && bddEveryPositive(cx, bn.right(), pos, andIfPositive(bn.atom(), neg), predicate); - } - } - - private static Conjunction andIfPositive(Atom atom, Conjunction next) { - if (atom instanceof RecAtom recAtom && recAtom.index() < 0) { - return next; - } - return and(atom, next); - } - - public abstract boolean posMaybeEmpty(); - - // This is for debugging purposes. - // It uses the Frisch/Castagna notation. - public static String bddToString(Bdd b, boolean inner) { - if (b instanceof BddAllOrNothing) { - return b.isAll() ? "1" : "0"; - } else { - String str; - BddNode bdd = (BddNode) b; - Atom a = bdd.atom(); - - if (a instanceof RecAtom) { - str = "r"; - } else { - str = "a"; - } - str += a.index(); - str += "?" + bddToString(bdd.left(), true) + ":" + bddToString(bdd.middle(), true) + - ":" + bddToString(bdd.right(), true); - if (inner) { - str = "(" + str + ")"; - } - return str; - } - } - -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BddAllOrNothing.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BddAllOrNothing.java deleted file mode 100644 index e5b6c67ebad5..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BddAllOrNothing.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.api.types.semtype; - -/** - * Represent the leaf node of a Bdd. - * - * @since 2201.11.0 - */ -public final class BddAllOrNothing extends Bdd { - - public static final BddAllOrNothing ALL = new BddAllOrNothing(true); - public static final BddAllOrNothing NOTHING = new BddAllOrNothing(false); - - private BddAllOrNothing(boolean all) { - super(all, !all); - } - - @Override - public int hashCode() { - return this == ALL ? 1 : 0; - } - - @Override - public boolean equals(Object o) { - return this == o; - } - - @Override - public boolean posMaybeEmpty() { - return this == ALL; - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BddNode.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BddNode.java deleted file mode 100644 index 001f154701ee..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BddNode.java +++ /dev/null @@ -1,66 +0,0 @@ -package io.ballerina.runtime.api.types.semtype; - -/** - * Internal node of a BDD, which represents a disjunction of conjunctions of atoms. - * - * @since 2201.11.0 - */ -public abstract sealed class BddNode extends Bdd permits BddNodeImpl, BddNodeSimple { - - private volatile Integer hashCode = null; - - protected BddNode(boolean all, boolean nothing) { - super(all, nothing); - } - - public static BddNode bddAtom(Atom atom) { - return new BddNodeSimple(atom); - } - - public boolean isSimple() { - return this instanceof BddNodeSimple; - } - - public abstract Atom atom(); - - public abstract Bdd left(); - - public abstract Bdd middle(); - - public abstract Bdd right(); - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof BddNode other)) { - return false; - } - return atom().equals(other.atom()) && left().equals(other.left()) && middle().equals(other.middle()) && - right().equals(other.right()); - } - - @Override - public int hashCode() { - Integer result = hashCode; - if (result == null) { - // No need to synchronize this since {@code computeHashCode} is idempotent - hashCode = result = computeHashCode(); - } - return result; - } - - private int computeHashCode() { - int result = atom().hashCode(); - result = 31 * result + left().hashCode(); - result = 31 * result + middle().hashCode(); - result = 31 * result + right().hashCode(); - return result; - } - - @Override - public boolean posMaybeEmpty() { - return middle().posMaybeEmpty() || right().posMaybeEmpty(); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BddNodeImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BddNodeImpl.java deleted file mode 100644 index 71b1a9528220..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BddNodeImpl.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.api.types.semtype; - -/** - * Generalized implementation of {@code BddNode}. - * - * @since 2201.11.0 - */ -final class BddNodeImpl extends BddNode { - - private final Atom atom; - private final Bdd left; - private final Bdd middle; - private final Bdd right; - - BddNodeImpl(Atom atom, Bdd left, Bdd middle, Bdd right) { - super(false, false); - this.atom = atom; - this.left = left; - this.middle = middle; - this.right = right; - } - - @Override - public Atom atom() { - return atom; - } - - @Override - public Bdd left() { - return left; - } - - @Override - public Bdd middle() { - return middle; - } - - @Override - public Bdd right() { - return right; - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BddNodeSimple.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BddNodeSimple.java deleted file mode 100644 index bd64cdcf9af5..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BddNodeSimple.java +++ /dev/null @@ -1,37 +0,0 @@ -package io.ballerina.runtime.api.types.semtype; - -/** - * Represent a Bdd node that contains a single atom as positive. This is used to reduce the memory overhead of - * BddNodeImpl in representing such nodes - * - * @since 2201.11.0 - */ -final class BddNodeSimple extends BddNode { - - private final Atom atom; - - BddNodeSimple(Atom atom) { - super(false, false); - this.atom = atom; - } - - @Override - public Atom atom() { - return atom; - } - - @Override - public Bdd left() { - return BddAllOrNothing.ALL; - } - - @Override - public Bdd middle() { - return BddAllOrNothing.NOTHING; - } - - @Override - public Bdd right() { - return BddAllOrNothing.NOTHING; - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Builder.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Builder.java deleted file mode 100644 index 4c4f1149387b..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Builder.java +++ /dev/null @@ -1,456 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.api.types.semtype; - -import io.ballerina.runtime.internal.types.semtype.BBooleanSubType; -import io.ballerina.runtime.internal.types.semtype.BCellSubType; -import io.ballerina.runtime.internal.types.semtype.BDecimalSubType; -import io.ballerina.runtime.internal.types.semtype.BFloatSubType; -import io.ballerina.runtime.internal.types.semtype.BIntSubType; -import io.ballerina.runtime.internal.types.semtype.BListSubType; -import io.ballerina.runtime.internal.types.semtype.BMappingSubType; -import io.ballerina.runtime.internal.types.semtype.BStringSubType; -import io.ballerina.runtime.internal.types.semtype.CellAtomicType; -import io.ballerina.runtime.internal.types.semtype.FixedLengthArray; -import io.ballerina.runtime.internal.types.semtype.ListAtomicType; -import io.ballerina.runtime.internal.types.semtype.ListDefinition; -import io.ballerina.runtime.internal.types.semtype.MappingAtomicType; -import io.ballerina.runtime.internal.types.semtype.MappingDefinition; -import io.ballerina.runtime.internal.types.semtype.TableUtils; -import io.ballerina.runtime.internal.types.semtype.XmlUtils; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Stream; - -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_CELL; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_ERROR; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_FUNCTION; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_FUTURE; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_HANDLE; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_LIST; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_MAPPING; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_OBJECT; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_REGEXP; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_TYPEDESC; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_XML; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_UNDEF; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.VT_MASK; -import static io.ballerina.runtime.api.types.semtype.BddNode.bddAtom; -import static io.ballerina.runtime.api.types.semtype.Core.union; -import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_LIMITED; -import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_NONE; - -/** - * Utility class for creating semtypes. - * - * @since 2201.11.0 - */ -public final class Builder { - - private static final String[] EMPTY_STRING_ARR = new String[0]; - private static final SemType VAL = SemType.from(VT_MASK); - private static final SemType OBJECT = from(BT_OBJECT); - - private static final SemType INNER = getBasicTypeUnion(VAL.all() | from(BasicTypeCode.BT_UNDEF).all()); - private static final SemType ANY = getBasicTypeUnion(BasicTypeCode.VT_MASK & ~(1 << BasicTypeCode.BT_ERROR.code())); - private static final SemType SIMPLE_OR_STRING = - getBasicTypeUnion((1 << BasicTypeCode.BT_NIL.code()) - | (1 << BasicTypeCode.BT_BOOLEAN.code()) - | (1 << BasicTypeCode.BT_INT.code()) - | (1 << BasicTypeCode.BT_FLOAT.code()) - | (1 << BasicTypeCode.BT_DECIMAL.code()) - | (1 << BT_REGEXP.code()) - | (1 << BasicTypeCode.BT_STRING.code())); - - private static final SemType[] EMPTY_TYPES_ARR = new SemType[0]; - - private static final ConcurrentLazySupplier MAPPING_RO = new ConcurrentLazySupplier<>(() -> - basicSubType(BT_MAPPING, BMappingSubType.createDelegate(getBddSubtypeRo())) - ); - private static final ConcurrentLazySupplier ANYDATA = new ConcurrentLazySupplier<>( - () -> { - Env env = Env.getInstance(); - ListDefinition listDef = new ListDefinition(); - MappingDefinition mapDef = new MappingDefinition(); - SemType tableTy = TableUtils.tableContaining(env, mapDef.getSemType(env)); - SemType accum = Stream.of(getSimpleOrStringType(), getXmlType(), listDef.getSemType(env), - mapDef.getSemType(env), - tableTy).reduce(Builder.getNeverType(), Core::union); - listDef.defineListTypeWrapped(env, EMPTY_TYPES_ARR, 0, accum, CELL_MUT_LIMITED); - mapDef.defineMappingTypeWrapped(env, new MappingDefinition.Field[0], accum, CELL_MUT_LIMITED); - return accum; - } - ); - private static final ConcurrentLazySupplier INNER_RO = - new ConcurrentLazySupplier<>(() -> union(getReadonlyType(), getInnerType())); - - private static final ConcurrentLazySupplier LIST_ATOMIC_INNER = - new ConcurrentLazySupplier<>(() -> new ListAtomicType( - FixedLengthArray.empty(), PredefinedTypeEnv.getInstance().cellSemTypeInner())); - private static final ConcurrentLazySupplier MAPPING_ATOMIC_INNER = - new ConcurrentLazySupplier<>(() -> new MappingAtomicType( - EMPTY_STRING_ARR, EMPTY_TYPES_ARR, PredefinedTypeEnv.getInstance().cellSemTypeInner())); - - private static final ConcurrentLazySupplier XML_ELEMENT = new ConcurrentLazySupplier<>(() -> - XmlUtils.xmlSingleton(XmlUtils.XML_PRIMITIVE_ELEMENT_RO | XmlUtils.XML_PRIMITIVE_ELEMENT_RW)); - private static final ConcurrentLazySupplier XML_COMMENT = new ConcurrentLazySupplier<>(() -> - XmlUtils.xmlSingleton(XmlUtils.XML_PRIMITIVE_COMMENT_RO | XmlUtils.XML_PRIMITIVE_COMMENT_RW)); - private static final ConcurrentLazySupplier XML_TEXT = new ConcurrentLazySupplier<>(() -> - XmlUtils.xmlSingleton(XmlUtils.XML_PRIMITIVE_TEXT)); - private static final ConcurrentLazySupplier XML_PI = new ConcurrentLazySupplier<>(() -> - XmlUtils.xmlSingleton(XmlUtils.XML_PRIMITIVE_PI_RO | XmlUtils.XML_PRIMITIVE_PI_RW)); - private static final ConcurrentLazySupplier XML_NEVER = new ConcurrentLazySupplier<>(() -> - XmlUtils.xmlSingleton(XmlUtils.XML_PRIMITIVE_NEVER)); - private static final PredefinedTypeEnv PREDEFINED_TYPE_ENV = PredefinedTypeEnv.getInstance(); - private static final BddNode LIST_SUBTYPE_THREE_ELEMENT = bddAtom(PREDEFINED_TYPE_ENV.atomListThreeElement()); - private static final BddNode LIST_SUBTYPE_THREE_ELEMENT_RO = bddAtom(PREDEFINED_TYPE_ENV.atomListThreeElementRO()); - private static final BddNode LIST_SUBTYPE_TWO_ELEMENT = bddAtom(PREDEFINED_TYPE_ENV.atomListTwoElement()); - - private Builder() { - } - - public static SemType from(BasicTypeCode typeCode) { - if (BasicTypeCache.isCached(typeCode)) { - return BasicTypeCache.cache[typeCode.code()]; - } - return SemType.from(1 << typeCode.code()); - } - - public static SemType getNeverType() { - return SemType.from(0); - } - - public static SemType getNilType() { - return from(BasicTypeCode.BT_NIL); - } - - public static SemType getUndefType() { - return from(BasicTypeCode.BT_UNDEF); - } - - public static SemType getCellType() { - return from(BT_CELL); - } - - public static SemType getInnerType() { - return INNER; - } - - public static SemType getIntType() { - return from(BasicTypeCode.BT_INT); - } - - public static SemType getDecimalType() { - return from(BasicTypeCode.BT_DECIMAL); - } - - public static SemType getFloatType() { - return from(BasicTypeCode.BT_FLOAT); - } - - public static SemType getBooleanType() { - return from(BasicTypeCode.BT_BOOLEAN); - } - - public static SemType getStringType() { - return from(BasicTypeCode.BT_STRING); - } - - public static SemType getCharType() { - return StringTypeCache.charType; - } - - public static SemType getListType() { - return from(BT_LIST); - } - - public static SemType getReadonlyType() { - return PREDEFINED_TYPE_ENV.readonlyType(); - } - - static SemType getBasicTypeUnion(int bitset) { - return switch (bitset) { - case 0 -> getNeverType(); - case VT_MASK -> VAL; - default -> { - if (Integer.bitCount(bitset) == 1) { - int code = Integer.numberOfTrailingZeros(bitset); - // TODO: what are the others? - if (BasicTypeCache.isCached(code)) { - yield BasicTypeCache.cache[code]; - } - } - yield SemType.from(bitset); - } - }; - } - - public static SemType basicSubType(BasicTypeCode basicTypeCode, SubType subType) { - assert !(subType instanceof Bdd) : "BDD should always be wrapped with a delegate"; - assert checkDelegate(basicTypeCode, subType) : "BDd is wrapped in wrong delegate"; - int some = 1 << basicTypeCode.code(); - SubType[] subTypes = initializeSubtypeArray(some); - subTypes[0] = subType; - return SemType.from(0, some, subTypes); - } - - private static boolean checkDelegate(BasicTypeCode basicTypeCode, SubType subType) { - return (basicTypeCode != BT_MAPPING || subType instanceof BMappingSubType) - && (basicTypeCode != BT_LIST || subType instanceof BListSubType) - && (basicTypeCode != BT_CELL || subType instanceof BCellSubType); - } - - public static SemType getIntConst(long value) { - if (value >= IntTypeCache.CACHE_MIN_VALUE && value <= IntTypeCache.CACHE_MAX_VALUE) { - return IntTypeCache.cache[(int) value - IntTypeCache.CACHE_MIN_VALUE]; - } - return createIntSingletonType(value); - } - - private static SemType createIntSingletonType(long value) { - List values = new ArrayList<>(1); - values.add(value); - return basicSubType(BasicTypeCode.BT_INT, BIntSubType.createIntSubType(values)); - } - - public static SemType getBooleanConst(boolean value) { - return value ? BooleanTypeCache.TRUE : BooleanTypeCache.FALSE; - } - - public static SemType createIntRange(long min, long max) { - return basicSubType(BasicTypeCode.BT_INT, BIntSubType.createIntSubType(min, max)); - } - - public static SemType getDecimalConst(BigDecimal value) { - BigDecimal[] values = {value}; - return basicSubType(BasicTypeCode.BT_DECIMAL, BDecimalSubType.createDecimalSubType(true, values)); - } - - public static SemType getFloatConst(double value) { - Double[] values = {value}; - return basicSubType(BasicTypeCode.BT_FLOAT, BFloatSubType.createFloatSubType(true, values)); - } - - // TODO: consider caching small strings - public static SemType getStringConst(String value) { - BStringSubType subType; - String[] values = {value}; - String[] empty = EMPTY_STRING_ARR; - if (value.length() == 1 || value.codePointCount(0, value.length()) == 1) { - subType = BStringSubType.createStringSubType(true, values, true, empty); - } else { - subType = BStringSubType.createStringSubType(true, empty, true, values); - } - return basicSubType(BasicTypeCode.BT_STRING, subType); - } - - static SubType[] initializeSubtypeArray(int some) { - return new SubType[Integer.bitCount(some)]; - } - - public static SemType getRoCellContaining(Env env, SemType ty) { - return getCellContaining(env, ty, CELL_MUT_NONE); - } - - public static SemType getRwCellContaining(Env env, SemType ty) { - return getCellContaining(env, ty, CellAtomicType.CellMutability.CELL_MUT_LIMITED); - } - - public static SemType getCellContaining(Env env, SemType ty, CellAtomicType.CellMutability mut) { - return env.getCachedCellType(ty, mut, () -> createCellSemType(env, ty, mut)); - } - - private static SemType createCellSemType(Env env, SemType ty, CellAtomicType.CellMutability mut) { - CellAtomicType atomicCell = CellAtomicType.from(ty, mut); - TypeAtom atom = env.cellAtom(atomicCell); - BddNode bdd = bddAtom(atom); - return basicSubType(BT_CELL, BCellSubType.createDelegate(bdd)); - } - - public static SemType getValType() { - return getBasicTypeUnion(VT_MASK); - } - - public static SemType getAnyType() { - return ANY; - } - - public static SemType getMappingType() { - return from(BT_MAPPING); - } - - public static SemType getFunctionType() { - return from(BT_FUNCTION); - } - - public static SemType getErrorType() { - return from(BT_ERROR); - } - - public static SemType getXmlType() { - return from(BT_XML); - } - - public static SemType getXmlElementType() { - return XML_ELEMENT.get(); - } - - public static SemType getXmlCommentType() { - return XML_COMMENT.get(); - } - - public static SemType getXmlTextType() { - return XML_TEXT.get(); - } - - public static SemType getXmlNeverType() { - return XML_NEVER.get(); - } - - public static SemType getXmlPIType() { - return XML_PI.get(); - } - - public static SemType getHandleType() { - return from(BT_HANDLE); - } - - public static SemType getFutureType() { - return from(BT_FUTURE); - } - - public static SemType getRegexType() { - return from(BT_REGEXP); - } - - public static SemType getTypeDescType() { - return from(BT_TYPEDESC); - } - - public static SemType getStreamType() { - return from(BasicTypeCode.BT_STREAM); - } - - public static SemType getAnyDataType() { - return ANYDATA.get(); - } - - public static SemType getObjectType() { - return OBJECT; - } - - static SemType mappingRO() { - return MAPPING_RO.get(); - } - - static SemType innerReadOnly() { - return INNER_RO.get(); - } - - static CellAtomicType cellAtomicVal() { - return PREDEFINED_TYPE_ENV.cellAtomicVal(); - } - - public static BddNode getBddSubtypeRo() { - return bddAtom(RecAtom.createRecAtom(0)); - } - - public static ListAtomicType getListAtomicInner() { - return LIST_ATOMIC_INNER.get(); - } - - public static MappingAtomicType getMappingAtomicInner() { - return MAPPING_ATOMIC_INNER.get(); - } - - public static BddNode getListSubtypeThreeElement() { - return LIST_SUBTYPE_THREE_ELEMENT; - } - - public static BddNode getListSubtypeThreeElementRO() { - return LIST_SUBTYPE_THREE_ELEMENT_RO; - } - - public static BddNode getListSubtypeTwoElement() { - return LIST_SUBTYPE_TWO_ELEMENT; - } - - public static SemType getSimpleOrStringType() { - return SIMPLE_OR_STRING; - } - - public static SemType getTableType() { - return from(BasicTypeCode.BT_TABLE); - } - - private static final class IntTypeCache { - - private static final int CACHE_MAX_VALUE = 127; - private static final int CACHE_MIN_VALUE = -128; - private static final SemType[] cache; - static { - cache = new SemType[CACHE_MAX_VALUE - CACHE_MIN_VALUE + 1]; - for (int i = CACHE_MIN_VALUE; i <= CACHE_MAX_VALUE; i++) { - cache[i - CACHE_MIN_VALUE] = createIntSingletonType(i); - } - } - } - - private static final class BooleanTypeCache { - - private static final SemType TRUE = createBooleanSingletonType(true); - private static final SemType FALSE = createBooleanSingletonType(false); - - private static SemType createBooleanSingletonType(boolean value) { - return basicSubType(BasicTypeCode.BT_BOOLEAN, BBooleanSubType.from(value)); - } - } - - private static final class StringTypeCache { - - private static final SemType charType; - static { - BStringSubType subTypeData = BStringSubType.createStringSubType(false, Builder.EMPTY_STRING_ARR, true, - Builder.EMPTY_STRING_ARR); - charType = basicSubType(BasicTypeCode.BT_STRING, subTypeData); - } - } - - private static final class BasicTypeCache { - - private static final SemType[] cache; - static { - cache = new SemType[CODE_UNDEF + 2]; - for (int i = 0; i < CODE_UNDEF + 1; i++) { - cache[i] = SemType.from(1 << i); - } - } - - private static boolean isCached(BasicTypeCode code) { - int i = code.code(); - return 0 < i && i <= CODE_UNDEF; - } - - private static boolean isCached(int code) { - return 0 < code && code <= CODE_UNDEF; - } - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/CacheableTypeDescriptor.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/CacheableTypeDescriptor.java deleted file mode 100644 index bad069886c65..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/CacheableTypeDescriptor.java +++ /dev/null @@ -1,41 +0,0 @@ -package io.ballerina.runtime.api.types.semtype; - -import io.ballerina.runtime.api.types.Type; - -import java.util.Optional; - -/** - * Represent TypeDescriptors whose type check results can be cached. - * - * @since 2201.11.0 - */ -public interface CacheableTypeDescriptor extends Type { - - /** - * Check whether the type check result of this type descriptor should be cached. Can be used to avoid caching in - * cases where either directly doing the type check is cheaper or we can't determine if two instances of a type - * descriptor are equal without doing a type check. - * - * @return true if the type check result should be cached, false otherwise - */ - boolean shouldCache(); - - /** - * Check whether the type check result of this type descriptor is cached for the given type descriptor. - * - * @param cx Context in which the type check is performed - * @param other Type descriptor to check the cached result for - * @return Optional containing the cached result if it is cached, empty otherwise - */ - Optional cachedTypeCheckResult(Context cx, CacheableTypeDescriptor other); - - /** - * Cache the type check result of this type descriptor for the given type descriptor. Note that implementations of - * this method could choose to not cache the result if {@link #shouldCache()} returns false. In such cases, even - * after calling this method, {@link #cachedTypeCheckResult(Context, CacheableTypeDescriptor)} could return empty. - * - * @param other Type descriptor to cache the result for - * @param result Result of the type check - */ - void cacheTypeCheckResult(CacheableTypeDescriptor other, boolean result); -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/ConcurrentLazySupplier.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/ConcurrentLazySupplier.java deleted file mode 100644 index 2ea49c4906f1..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/ConcurrentLazySupplier.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.ballerina.runtime.api.types.semtype; - -import java.util.function.Supplier; - -/** - * A thread-safe single lazy supplier that initialize the value only once. - * - * @param type of the value - * @since 2201.11.0 - */ -public class ConcurrentLazySupplier implements Supplier { - - private Supplier initializer; - private volatile E value = null; - - public ConcurrentLazySupplier(Supplier initializer) { - this.initializer = initializer; - } - - @Override - public E get() { - E result = value; - if (result == null) { - synchronized (this) { - result = value; - if (result == null) { - result = initializer.get(); - assert result != null; - value = result; - initializer = null; - } - } - } - return result; - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/ConcurrentLazySupplierWithCallback.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/ConcurrentLazySupplierWithCallback.java deleted file mode 100644 index 94646141bb5b..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/ConcurrentLazySupplierWithCallback.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.api.types.semtype; - -import java.util.function.Consumer; -import java.util.function.Supplier; - -/** - * A thread-safe lazy supplier that initializes the value on the first call to {@link #get()} and calls the callback. - * - * @param the type of the value - * @since 2201.11.0 - */ -public class ConcurrentLazySupplierWithCallback implements Supplier { - - private volatile E value = null; - private Supplier initializer; - private Consumer callback; - - ConcurrentLazySupplierWithCallback(Supplier initializer, Consumer callback) { - this.initializer = initializer; - this.callback = callback; - } - - @Override - public E get() { - E result = value; - if (result == null) { - synchronized (this) { - result = value; - if (result == null) { - result = initializer.get(); - assert result != null; - value = result; - initializer = null; - callback.accept(result); - callback = null; - } - } - } - return result; - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Context.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Context.java deleted file mode 100644 index 4d6634f89f76..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Context.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.api.types.semtype; - -import io.ballerina.runtime.internal.types.semtype.BddMemo; -import io.ballerina.runtime.internal.types.semtype.FunctionAtomicType; -import io.ballerina.runtime.internal.types.semtype.ListAtomicType; -import io.ballerina.runtime.internal.types.semtype.MappingAtomicType; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.WeakHashMap; - -/** - * Context in which type checking operations are performed. Note context is not - * thread safe, and multiple type check operations should not use the same - * context concurrently. Multiple contexts may share same environment without - * issue. - * - * @since 2201.11.0 - */ -public final class Context { - - // Contains all BddMemo entries with isEmpty == PROVISIONAL - private final List memoStack = new ArrayList<>(); - public final Env env; - public final Map listMemo = new WeakHashMap<>(); - public final Map mappingMemo = new WeakHashMap<>(); - public final Map functionMemo = new WeakHashMap<>(); - private static final int MAX_CACHE_SIZE = 100; - private final Map> typeCheckCacheMemo; - - private Context(Env env) { - this.env = env; - this.typeCheckCacheMemo = createTypeCheckCacheMemo(); - } - - private static Map> createTypeCheckCacheMemo() { - // This is fine since this map is not going to get leaked out of the context and - // context is unique to a thread. So there will be no concurrent modifications - return new LinkedHashMap<>(MAX_CACHE_SIZE, 1f, true) { - @Override - protected boolean removeEldestEntry( - Map.Entry> eldest) { - return size() > MAX_CACHE_SIZE; - } - }; - } - - public static Context from(Env env) { - return new Context(env); - } - - /** - * Memoization logic - * Castagna's paper does not deal with this fully. Although he calls it memoization, it is not, strictly speaking, - * just memoization, since it is not just an optimization, but required for correct handling of recursive types. - * The handling of recursive types depends on our types being defined inductively, rather than coinductively. - * This means that each shape that is a member of the set denoted by the type is finite. There is a tricky problem - * here with memoizing results that rely on assumptions that subsequently turn out to be false. Memoization/caching - * is discussed in section 7.1.2 of the Frisch thesis. This follows Frisch's approach of undoing memoizations that - * turn out to be wrong. (I did not succeed in fully understanding his approach, so I am not completely sure if we - * are doing the same.) - * @param memoTable corresponding memo table for the Bdd - * @param isEmptyPredicate predicate to be applied on the Bdd - * @param bdd Bdd to be checked - * @return result of applying predicate on the bdd - */ - public boolean memoSubtypeIsEmpty(Map memoTable, BddIsEmptyPredicate isEmptyPredicate, Bdd bdd) { - BddMemo m = memoTable.computeIfAbsent(bdd, ignored -> new BddMemo()); - return m.isEmpty().orElseGet(() -> memoSubTypeIsEmptyInner(isEmptyPredicate, bdd, m)); - } - - private boolean memoSubTypeIsEmptyInner(BddIsEmptyPredicate isEmptyPredicate, Bdd bdd, BddMemo m) { - // We are staring the type check with the assumption our type is empty (see: inductive type) - m.isEmpty = BddMemo.Status.PROVISIONAL; - int initStackDepth = memoStack.size(); - memoStack.add(m); - boolean isEmpty = isEmptyPredicate.apply(this, bdd); - boolean isLoop = m.isEmpty == BddMemo.Status.LOOP; - // if not empty our assumption is wrong so we need to reset the memoized values, otherwise we cleanup the stack - // at the end - if (!isEmpty || initStackDepth == 0) { - resetMemoizedValues(initStackDepth, isEmpty, isLoop, m); - } - return isEmpty; - } - - private void resetMemoizedValues(int initStackDepth, boolean isEmpty, boolean isLoop, BddMemo m) { - for (int i = initStackDepth + 1; i < memoStack.size(); i++) { - BddMemo.Status memoStatus = memoStack.get(i).isEmpty; - if (Objects.requireNonNull(memoStatus) == BddMemo.Status.PROVISIONAL || - memoStatus == BddMemo.Status.LOOP || memoStatus == BddMemo.Status.CYCLIC) { - // We started with the assumption our type is empty. Now we know for sure if we are empty or not - // if we are empty all of these who don't have anything except us should be empty as well. - // Otherwise, we don't know if they are empty or not - memoStack.get(i).isEmpty = isEmpty ? BddMemo.Status.TRUE : BddMemo.Status.NULL; - } - } - if (memoStack.size() > initStackDepth) { - memoStack.subList(initStackDepth, memoStack.size()).clear(); - } - if (isLoop && isEmpty) { - // The only way that we have found that this can be empty is by going through a loop. - // This means that the shapes in the type would all be infinite. - // But we define types inductively, which means we only consider finite shapes. - m.isEmpty = BddMemo.Status.CYCLIC; - } else { - m.isEmpty = isEmpty ? BddMemo.Status.TRUE : BddMemo.Status.FALSE; - } - } - - public ListAtomicType listAtomType(Atom atom) { - if (atom instanceof RecAtom recAtom) { - return this.env.getRecListAtomType(recAtom); - } else { - return (ListAtomicType) ((TypeAtom) atom).atomicType(); - } - } - - public MappingAtomicType mappingAtomType(Atom atom) { - if (atom instanceof RecAtom recAtom) { - return this.env.getRecMappingAtomType(recAtom); - } else { - return (MappingAtomicType) ((TypeAtom) atom).atomicType(); - } - } - - public FunctionAtomicType functionAtomicType(Atom atom) { - if (atom instanceof RecAtom recAtom) { - return this.env.getRecFunctionAtomType(recAtom); - } else { - return (FunctionAtomicType) ((TypeAtom) atom).atomicType(); - } - } - - public TypeCheckCache getTypeCheckCache(CacheableTypeDescriptor typeDescriptor) { - return typeCheckCacheMemo.computeIfAbsent(typeDescriptor, TypeCheckCache::new); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Core.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Core.java deleted file mode 100644 index 3eefea1b58e4..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Core.java +++ /dev/null @@ -1,520 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.api.types.semtype; - -import io.ballerina.runtime.internal.types.semtype.AllOrNothing; -import io.ballerina.runtime.internal.types.semtype.BFutureSubType; -import io.ballerina.runtime.internal.types.semtype.BIntSubType; -import io.ballerina.runtime.internal.types.semtype.BObjectSubType; -import io.ballerina.runtime.internal.types.semtype.BStreamSubType; -import io.ballerina.runtime.internal.types.semtype.BTableSubType; -import io.ballerina.runtime.internal.types.semtype.BTypedescSubType; -import io.ballerina.runtime.internal.types.semtype.CellAtomicType; -import io.ballerina.runtime.internal.types.semtype.DelegatedSubType; -import io.ballerina.runtime.internal.types.semtype.EnumerableSubtypeData; -import io.ballerina.runtime.internal.types.semtype.ListAtomicType; -import io.ballerina.runtime.internal.types.semtype.SubTypeData; -import io.ballerina.runtime.internal.types.semtype.SubtypePair; -import io.ballerina.runtime.internal.types.semtype.SubtypePairs; - -import java.math.BigDecimal; -import java.util.Arrays; -import java.util.Optional; -import java.util.function.Function; - -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_CELL; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_DECIMAL; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_FLOAT; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_INT; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_LIST; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_STRING; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_FUTURE; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_OBJECT; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_STREAM; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_TABLE; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_TYPEDESC; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.VT_MASK; -import static io.ballerina.runtime.api.types.semtype.Builder.getListType; -import static io.ballerina.runtime.api.types.semtype.Builder.getUndefType; -import static io.ballerina.runtime.internal.types.semtype.BListSubType.bddListMemberTypeInnerVal; -import static io.ballerina.runtime.internal.types.semtype.BMappingProj.mappingMemberTypeInner; -import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_NONE; -import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.cellAtomType; -import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.intersectCellAtomicType; - -/** - * Contain functions defined in `core.bal` file. - * - * @since 2201.11.0 - */ -public final class Core { - - private Core() { - } - - public static SemType diff(SemType t1, SemType t2) { - int all1 = t1.all(); - int all2 = t2.all(); - int some1 = t1.some(); - int some2 = t2.some(); - if (some1 == 0) { - if (some2 == 0) { - return Builder.getBasicTypeUnion(all1 & ~all2); - } else { - if (all1 == 0) { - return t1; - } - } - } else { - if (some2 == 0) { - if (all2 == VT_MASK) { - return Builder.getBasicTypeUnion(0); - } - } - } - int all = all1 & ~(all2 | some2); - int some = (all1 | some1) & ~all2; - some = some & ~all; - if (some == 0) { - return SemType.from(all); - } - SubType[] subtypes = Builder.initializeSubtypeArray(some); - int i = 0; - boolean filterNulls = false; - for (SubtypePair pair : new SubtypePairs(t1, t2, some)) { - SubType data1 = pair.subType1(); - SubType data2 = pair.subType2(); - int code = pair.typeCode(); - SubType data; - if (data1 == null) { - data = data2.complement(); - } else if (data2 == null) { - data = data1; - } else { - data = data1.diff(data2); - } - if (data.isAll()) { - all |= 1 << code; - some &= ~(1 << code); - filterNulls = true; - } else if (data.isNothing()) { - some &= ~(1 << code); - filterNulls = true; - } else { - subtypes[i] = data; - i++; - } - } - return SemType.from(all, some, filterNulls ? filterNulls(some, subtypes) : subtypes); - } - - // TODO: this should return SubTypeData not subtype - public static SubType getComplexSubtypeData(SemType t, BasicTypeCode code) { - assert (t.some() & (1 << code.code())) != 0; - SubType subType = t.subTypeByCode(code.code()); - if (subType instanceof DelegatedSubType wrapper) { - return wrapper.inner(); - } - return subType; - } - - // This computes the spec operation called "member type of K in T", - // for the case when T is a subtype of list, and K is either `int` or a singleton int. - // This is what Castagna calls projection. - // We will extend this to allow `key` to be a SemType, which will turn into an IntSubtype. - // If `t` is not a list, NEVER is returned - public static SemType listMemberTypeInnerVal(Context cx, SemType t, SemType k) { - if (t.some() == 0) { - return (t.all() & getListType().all()) != 0 ? Builder.getValType() : Builder.getNeverType(); - } else { - SubTypeData keyData = intSubtype(k); - if (isNothingSubtype(keyData)) { - return Builder.getNeverType(); - } - return bddListMemberTypeInnerVal(cx, (Bdd) getComplexSubtypeData(t, BT_LIST), keyData, - Builder.getValType()); - } - } - - public static SemType union(SemType t1, SemType t2) { - assert t1 != null && t2 != null; - int all1 = t1.all(); - int some1 = t1.some(); - int all2 = t2.all(); - int some2 = t2.some(); - if (some1 == 0) { - if (some2 == 0) { - return Builder.getBasicTypeUnion(all1 | all2); - } - } - - int all = all1 | all2; - int some = (some1 | some2) & ~all; - if (some == 0) { - return Builder.getBasicTypeUnion(all); - } - SubType[] subtypes = Builder.initializeSubtypeArray(some); - int i = 0; - boolean filterNulls = false; - for (SubtypePair pair : new SubtypePairs(t1, t2, some)) { - int code = pair.typeCode(); - SubType data1 = pair.subType1(); - SubType data2 = pair.subType2(); - SubType data; - if (data1 == null) { - data = data2; - } else if (data2 == null) { - data = data1; - } else { - data = data1.union(data2); - } - if (data.isAll()) { - filterNulls = true; - all |= 1 << code; - some &= ~(1 << code); - } else { - subtypes[i] = data; - i++; - } - } - if (some == 0) { - return SemType.from(all); - } - return SemType.from(all, some, filterNulls ? filterNulls(some, subtypes) : subtypes); - } - - private static SubType[] filterNulls(int some, SubType[] subtypes) { - int newSize = cardinality(some); - SubType[] filtered = new SubType[newSize]; - System.arraycopy(subtypes, 0, filtered, 0, newSize); - return filtered; - } - - public static SemType intersect(SemType t1, SemType t2) { - assert t1 != null && t2 != null; - int all1 = t1.all(); - int some1 = t1.some(); - int all2 = t2.all(); - int some2 = t2.some(); - if (some1 == 0) { - if (some2 == 0) { - return SemType.from(all1 & all2); - } else { - if (all1 == 0) { - return t1; - } - if (all1 == VT_MASK) { - return t2; - } - } - } else if (some2 == 0) { - if (all2 == 0) { - return t2; - } - if (all2 == VT_MASK) { - return t1; - } - } - - int all = all1 & all2; - int some = (some1 | all1) & (some2 | all2); - some = some & ~all; - if (some == 0) { - return SemType.from(all); - } - - SubType[] subtypes = Builder.initializeSubtypeArray(some); - int i = 0; - boolean filterNulls = false; - for (SubtypePair pair : new SubtypePairs(t1, t2, some)) { - int code = pair.typeCode(); - SubType data1 = pair.subType1(); - SubType data2 = pair.subType2(); - - SubType data; - if (data1 == null) { - data = data2; - } else if (data2 == null) { - data = data1; - } else { - data = data1.intersect(data2); - } - - if (!data.isNothing()) { - subtypes[i] = data; - i++; - } else { - some &= ~(1 << code); - filterNulls = true; - } - } - if (some == 0) { - return SemType.from(all); - } - return SemType.from(all, some, filterNulls ? filterNulls(some, subtypes) : subtypes); - } - - public static boolean isEmpty(Context cx, SemType t) { - if (t.some() == 0) { - return t.all() == 0; - } - if (t.all() != 0) { - return false; - } - for (SubType subType : t.subTypeData()) { - assert subType != null : "subtype array must not be sparse"; - if (!subType.isEmpty(cx)) { - return false; - } - } - return true; - } - - public static SemType complement(SemType t) { - return diff(Builder.getValType(), t); - } - - public static boolean isNever(SemType t) { - return t.all() == 0 && t.some() == 0; - } - - public static boolean isSubType(Context cx, SemType t1, SemType t2) { - return isEmpty(cx, diff(t1, t2)); - } - - public static boolean isSubtypeSimple(SemType t1, SemType t2) { - assert t1 != null && t2 != null; - int bits = t1.all() | t1.some(); - return (bits & ~t2.all()) == 0; - } - - public static boolean isNothingSubtype(SubTypeData data) { - return data == AllOrNothing.NOTHING; - } - - public static SubTypeData intSubtype(SemType t) { - return subTypeData(t, BT_INT); - } - - public static SubTypeData stringSubtype(SemType t) { - return subTypeData(t, BT_STRING); - } - - public static SubTypeData subTypeData(SemType s, BasicTypeCode code) { - if ((s.all() & (1 << code.code())) != 0) { - return AllOrNothing.ALL; - } - if (s.some() == 0) { - return AllOrNothing.NOTHING; - } - SubType subType = s.subTypeByCode(code.code()); - assert subType != null; - return subType.data(); - } - - public static boolean containsBasicType(SemType t1, SemType t2) { - int bits = t1.all() | t1.some(); - return (bits & t2.all()) != 0; - } - - public static boolean isSameType(Context cx, SemType t1, SemType t2) { - return isSubType(cx, t1, t2) && isSubType(cx, t2, t1); - } - - private static int cardinality(int bitset) { - return Integer.bitCount(bitset); - } - - public static SemType getCellContainingInnerVal(Env env, SemType t) { - CellAtomicType cat = - cellAtomicType(t).orElseThrow(() -> new IllegalArgumentException("t is not a cell semtype")); - return Builder.getCellContaining(env, diff(cat.ty(), getUndefType()), cat.mut()); - } - - public static SemType intersectCellMemberSemTypes(Env env, SemType t1, SemType t2) { - CellAtomicType c1 = - cellAtomicType(t1).orElseThrow(() -> new IllegalArgumentException("t1 is not a cell semtype")); - CellAtomicType c2 = - cellAtomicType(t2).orElseThrow(() -> new IllegalArgumentException("t2 is not a cell semtype")); - - CellAtomicType atomicType = intersectCellAtomicType(c1, c2); - return Builder.getCellContaining(env, atomicType.ty(), - getUndefType().equals(atomicType.ty()) ? CELL_MUT_NONE : atomicType.mut()); - } - - public static Optional cellAtomicType(SemType t) { - SemType cell = Builder.getCellType(); - if (t.some() == 0) { - return cell.equals(t) ? Optional.of(Builder.cellAtomicVal()) : Optional.empty(); - } else { - if (!isSubtypeSimple(t, cell)) { - return Optional.empty(); - } - return bddCellAtomicType((Bdd) getComplexSubtypeData(t, BT_CELL), Builder.cellAtomicVal()); - } - } - - private static Optional bddCellAtomicType(Bdd bdd, CellAtomicType top) { - if (bdd instanceof BddAllOrNothing allOrNothing) { - if (allOrNothing.isAll()) { - return Optional.of(top); - } - return Optional.empty(); - } - BddNode bddNode = (BddNode) bdd; - return bddNode.isSimple() ? Optional.of(cellAtomType(bddNode.atom())) : Optional.empty(); - } - - public static SemType cellInnerVal(SemType t) { - return diff(cellInner(t), getUndefType()); - } - - public static SemType cellInner(SemType t) { - CellAtomicType cat = - cellAtomicType(t).orElseThrow(() -> new IllegalArgumentException("t is not a cell semtype")); - return cat.ty(); - } - - public static SemType createBasicSemType(BasicTypeCode typeCode, Bdd bdd) { - if (bdd instanceof BddAllOrNothing) { - return bdd.isAll() ? Builder.from(typeCode) : Builder.getNeverType(); - } - SubType subType = switch (typeCode.code()) { - case CODE_OBJECT -> BObjectSubType.createDelegate(bdd); - case CODE_FUTURE -> BFutureSubType.createDelegate(bdd); - case CODE_TYPEDESC -> BTypedescSubType.createDelegate(bdd); - case CODE_TABLE -> BTableSubType.createDelegate(bdd); - case CODE_STREAM -> BStreamSubType.createDelegate(bdd); - default -> throw new IllegalArgumentException("Unexpected type code: " + typeCode); - }; - return SemType.from(0, 1 << typeCode.code(), new SubType[]{subType}); - } - - public static SemType mappingMemberTypeInnerVal(Context cx, SemType t, SemType k) { - return diff(mappingMemberTypeInner(cx, t, k), Builder.getUndefType()); - } - - public static Optional listAtomicType(Context cx, SemType t) { - ListAtomicType listAtomicInner = Builder.getListAtomicInner(); - if (t.some() == 0) { - return Core.isSubtypeSimple(t, Builder.getListType()) ? Optional.ofNullable(listAtomicInner) : - Optional.empty(); - } - Env env = cx.env; - if (!isSubtypeSimple(t, Builder.getListType())) { - return Optional.empty(); - } - return bddListAtomicType(env, (Bdd) getComplexSubtypeData(t, BT_LIST), listAtomicInner); - } - - public static SemType floatToInt(SemType t) { - if (!containsBasicType(t, Builder.getFloatType())) { - return Builder.getNeverType(); - } - return convertEnumerableNumericType(t, BT_FLOAT, Builder.getIntType(), - (floatValue) -> ((Double) floatValue).longValue(), Builder::getIntConst); - } - - public static SemType floatToDecimal(SemType t) { - if (!containsBasicType(t, Builder.getFloatType())) { - return Builder.getNeverType(); - } - return convertEnumerableNumericType(t, BT_FLOAT, Builder.getDecimalType(), - (floatValue) -> BigDecimal.valueOf((Double) floatValue), Builder::getDecimalConst); - } - - public static SemType decimalToInt(SemType t) { - if (!containsBasicType(t, Builder.getDecimalType())) { - return Builder.getNeverType(); - } - return convertEnumerableNumericType(t, BT_DECIMAL, Builder.getIntType(), - (decimalVal) -> ((BigDecimal) decimalVal).longValue(), Builder::getIntConst); - } - - public static SemType decimalToFloat(SemType t) { - if (!containsBasicType(t, Builder.getDecimalType())) { - return Builder.getNeverType(); - } - return convertEnumerableNumericType(t, BT_DECIMAL, Builder.getFloatType(), - (decimalVal) -> ((BigDecimal) decimalVal).doubleValue(), Builder::getFloatConst); - } - - public static SemType intToFloat(SemType t) { - if (!containsBasicType(t, Builder.getIntType())) { - return Builder.getNeverType(); - } - SubTypeData subTypeData = subTypeData(t, BT_INT); - if (subTypeData == AllOrNothing.NOTHING) { - return Builder.getNeverType(); - } - if (subTypeData == AllOrNothing.ALL) { - return Builder.getFloatType(); - } - BIntSubType.IntSubTypeData intSubTypeData = (BIntSubType.IntSubTypeData) subTypeData; - return intSubTypeData.values().stream().map(Builder::getFloatConst).reduce(Builder.getNeverType(), Core::union); - } - - public static SemType intToDecimal(SemType t) { - if (!containsBasicType(t, Builder.getIntType())) { - return Builder.getNeverType(); - } - SubTypeData subTypeData = subTypeData(t, BT_INT); - if (subTypeData == AllOrNothing.NOTHING) { - return Builder.getNeverType(); - } - if (subTypeData == AllOrNothing.ALL) { - return Builder.getDecimalType(); - } - BIntSubType.IntSubTypeData intSubTypeData = (BIntSubType.IntSubTypeData) subTypeData; - return intSubTypeData.values().stream().map(BigDecimal::new).map(Builder::getDecimalConst) - .reduce(Builder.getNeverType(), Core::union); - } - - private static , T extends Comparable> SemType convertEnumerableNumericType( - SemType source, BasicTypeCode targetTypeCode, SemType topType, Function valueConverter, - Function semTypeCreator) { - SubTypeData subTypeData = subTypeData(source, targetTypeCode); - if (subTypeData == AllOrNothing.NOTHING) { - return Builder.getNeverType(); - } - if (subTypeData == AllOrNothing.ALL) { - return topType; - } - //noinspection unchecked - it's a enumerable type - EnumerableSubtypeData enumerableSubtypeData = (EnumerableSubtypeData) subTypeData; - SemType posType = - Arrays.stream(enumerableSubtypeData.values()).map(valueConverter).distinct().map(semTypeCreator) - .reduce(Builder.getNeverType(), Core::union); - if (enumerableSubtypeData.allowed()) { - return posType; - } - return diff(topType, posType); - } - - private static Optional bddListAtomicType(Env env, Bdd bdd, ListAtomicType top) { - if (!(bdd instanceof BddNode bddNode)) { - if (bdd.isAll()) { - return Optional.ofNullable(top); - } else { - return Optional.empty(); - } - } - return bddNode.isSimple() ? Optional.of(env.listAtomType(bddNode.atom())) : Optional.empty(); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Definition.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Definition.java deleted file mode 100644 index 0b0017f05841..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Definition.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.api.types.semtype; - -import io.ballerina.runtime.internal.types.semtype.DefinitionContainer; - -/** - * Represent a type definition which will act as a layer of indirection between {@code Env} and the type descriptor. - * - * @since 2201.11.0 - */ -public abstract class Definition { - - private DefinitionContainer container; - - /** - * Get the {@code SemType} of this definition in the given environment. - * - * @param env type environment - */ - public abstract SemType getSemType(Env env); - - /** - * Register the container as the holder of this definition. Used to maintain concurrency invariants. - * - * @param container holder of the definition - * @see io.ballerina.runtime.internal.types.semtype.DefinitionContainer - */ - public void registerContainer(DefinitionContainer container) { - this.container = container; - } - - protected void notifyContainer() { - if (container != null) { - container.definitionUpdated(); - } - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Env.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Env.java deleted file mode 100644 index 10b00639a035..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Env.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.api.types.semtype; - -import io.ballerina.runtime.internal.types.semtype.CellAtomicType; -import io.ballerina.runtime.internal.types.semtype.FunctionAtomicType; -import io.ballerina.runtime.internal.types.semtype.ListAtomicType; -import io.ballerina.runtime.internal.types.semtype.MappingAtomicType; - -import java.lang.ref.Reference; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.WeakHashMap; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.function.Supplier; - -/** - * Represent the environment in which {@code SemTypes} are defined in. Type - * checking types defined in different - * environments with each other in undefined. This is safe to be shared between - * multiple threads. - * - * @since 2201.11.0 - */ -public final class Env { - // Currently there is no reason to worry about above restrictions since Env is a singleton, but strictly speaking - // there is not technical restriction preventing multiple instances of Env. - - private static final Env INSTANCE = new Env(); - - // Each atom is created once but will be accessed multiple times during type checking. Also in perfect world we - // will create atoms at the beginning of the execution and will eventually reach - // a steady state. - private final ReadWriteLock atomLock = new ReentrantReadWriteLock(); - private final Map> atomTable; - - private final ReadWriteLock recListLock = new ReentrantReadWriteLock(); - final List recListAtoms; - - private final ReadWriteLock recMapLock = new ReentrantReadWriteLock(); - final List recMappingAtoms; - - private final ReadWriteLock recFunctionLock = new ReentrantReadWriteLock(); - private final List recFunctionAtoms; - - private final Map cellTypeCache = new ConcurrentHashMap<>(); - - private final AtomicInteger distinctAtomCount = new AtomicInteger(0); - - private Env() { - this.atomTable = new WeakHashMap<>(); - this.recListAtoms = new ArrayList<>(); - this.recMappingAtoms = new ArrayList<>(); - this.recFunctionAtoms = new ArrayList<>(); - - PredefinedTypeEnv.getInstance().initializeEnv(this); - } - - public static Env getInstance() { - return INSTANCE; - } - - public TypeAtom cellAtom(CellAtomicType atomicType) { - return this.typeAtom(atomicType); - } - - private TypeAtom typeAtom(AtomicType atomicType) { - atomLock.readLock().lock(); - try { - Reference ref = this.atomTable.get(atomicType); - if (ref != null) { - TypeAtom atom = ref.get(); - if (atom != null) { - return atom; - } - } - } finally { - atomLock.readLock().unlock(); - } - atomLock.writeLock().lock(); - try { - TypeAtom result = TypeAtom.createTypeAtom(this.atomTable.size(), atomicType); - this.atomTable.put(result.atomicType(), new WeakReference<>(result)); - return result; - } finally { - atomLock.writeLock().unlock(); - } - } - - // Ideally this cache should be in the builder as well. But technically we can't cache cells across environments. - // In practice this shouldn't be an issue since there should be only one environment, but I am doing this here - // just in case. - SemType getCachedCellType(SemType ty, CellAtomicType.CellMutability mut, Supplier semTypeCreator) { - if (ty.some() != 0) { - return semTypeCreator.get(); - } - return this.cellTypeCache.computeIfAbsent(new CellSemTypeCacheKey(ty, mut), k -> semTypeCreator.get()); - } - - public RecAtom recListAtom() { - recListLock.writeLock().lock(); - try { - int result = this.recListAtoms.size(); - // represents adding () in nballerina - this.recListAtoms.add(null); - return RecAtom.createRecAtom(result); - } finally { - recListLock.writeLock().unlock(); - } - } - - public void setRecListAtomType(RecAtom rec, ListAtomicType atomicType) { - // NOTE: this is fine since we are not actually changing the recList - recListLock.readLock().lock(); - try { - this.recListAtoms.set(rec.index(), atomicType); - } finally { - recListLock.readLock().unlock(); - } - - } - - public Atom listAtom(ListAtomicType atomicType) { - return this.typeAtom(atomicType); - } - - public ListAtomicType getRecListAtomType(RecAtom ra) { - recListLock.readLock().lock(); - try { - return this.recListAtoms.get(ra.index()); - } finally { - recListLock.readLock().unlock(); - } - } - - public ListAtomicType listAtomType(Atom atom) { - if (atom instanceof RecAtom recAtom) { - return getRecListAtomType(recAtom); - } else { - return (ListAtomicType) ((TypeAtom) atom).atomicType(); - } - } - - public RecAtom recMappingAtom() { - recMapLock.writeLock().lock(); - try { - int result = this.recMappingAtoms.size(); - // represents adding () in nballerina - this.recMappingAtoms.add(null); - return RecAtom.createRecAtom(result); - } finally { - recMapLock.writeLock().unlock(); - } - } - - public void setRecMappingAtomType(RecAtom rec, MappingAtomicType atomicType) { - recMapLock.readLock().lock(); - try { - this.recMappingAtoms.set(rec.index(), atomicType); - } finally { - recMapLock.readLock().unlock(); - } - } - - public TypeAtom mappingAtom(MappingAtomicType atomicType) { - return this.typeAtom(atomicType); - } - - public MappingAtomicType getRecMappingAtomType(RecAtom recAtom) { - recMapLock.readLock().lock(); - try { - return this.recMappingAtoms.get(recAtom.index()); - } finally { - recMapLock.readLock().unlock(); - } - } - - public RecAtom recFunctionAtom() { - recFunctionLock.writeLock().lock(); - try { - int result = this.recFunctionAtoms.size(); - // represents adding () in nballerina - this.recFunctionAtoms.add(null); - return RecAtom.createRecAtom(result); - } finally { - recFunctionLock.writeLock().unlock(); - } - } - - public void setRecFunctionAtomType(RecAtom rec, FunctionAtomicType atomicType) { - recFunctionLock.readLock().lock(); - try { - this.recFunctionAtoms.set(rec.index(), atomicType); - } finally { - recFunctionLock.readLock().unlock(); - } - } - - public FunctionAtomicType getRecFunctionAtomType(RecAtom recAtom) { - recFunctionLock.readLock().lock(); - try { - return this.recFunctionAtoms.get(recAtom.index()); - } finally { - recFunctionLock.readLock().unlock(); - } - } - - public Atom functionAtom(FunctionAtomicType atomicType) { - return this.typeAtom(atomicType); - } - - private record CellSemTypeCacheKey(SemType ty, CellAtomicType.CellMutability mut) { - - } - - public int distinctAtomCountGetAndIncrement() { - return this.distinctAtomCount.getAndIncrement(); - } - - // This is for debug purposes - public Optional atomicTypeByIndex(int index) { - atomLock.readLock().lock(); - try { - for (Map.Entry> entry : this.atomTable.entrySet()) { - TypeAtom typeAtom = entry.getValue().get(); - if (typeAtom == null) { - continue; - } - if (typeAtom.index() == index) { - return Optional.of(entry.getKey()); - } - } - return Optional.empty(); - } finally { - atomLock.readLock().unlock(); - } - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/FieldPair.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/FieldPair.java deleted file mode 100644 index 29ce90a72be5..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/FieldPair.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.api.types.semtype; - -/** - * Represent the matching fields types of two mapping atomic types. - * - * @param name name of the field - * @param type1 type of the field in the first mapping - * @param type2 type of the field in teh second mapping - * @param index1 corresponding index of the field in the first mapping. If matching field is rest value is {@code null} - * @param index2 corresponding index of the field in the second mapping. If matching field is rest value is - * {@code null} - * @since 2201.11.0 - */ -public record FieldPair(String name, SemType type1, SemType type2, Integer index1, Integer index2) { - -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/FieldPairs.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/FieldPairs.java deleted file mode 100644 index 82618c4c93f6..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/FieldPairs.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.api.types.semtype; - -import io.ballerina.runtime.internal.types.semtype.Common; -import io.ballerina.runtime.internal.types.semtype.MappingAtomicType; - -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.util.Objects; -import java.util.Optional; - -/** - * {@code Iterable} over the matching fields of two mapping atomic types. - * - * @since 2201.11.0 - */ -public class FieldPairs implements Iterable { - - MappingAtomicType m1; - MappingAtomicType m2; - private final MappingPairIterator itr; - - public FieldPairs(MappingAtomicType m1, MappingAtomicType m2) { - this.m1 = m1; - this.m2 = m2; - itr = new MappingPairIterator(m1, m2); - } - - @Override - public Iterator iterator() { - return itr; - } - - private static final class MappingPairIterator implements Iterator { - - private final String[] names1; - private final String[] names2; - private final SemType[] types1; - private final SemType[] types2; - private final int len1; - private final int len2; - private int i1 = 0; - private int i2 = 0; - private final SemType rest1; - private final SemType rest2; - - private boolean doneIteration = false; - private boolean shouldCalculate = true; - private FieldPair cache = null; - - private MappingPairIterator(MappingAtomicType m1, MappingAtomicType m2) { - this.names1 = m1.names(); - this.len1 = this.names1.length; - this.types1 = m1.types(); - this.rest1 = m1.rest(); - this.names2 = m2.names(); - this.len2 = this.names2.length; - this.types2 = m2.types(); - this.rest2 = m2.rest(); - } - - @Override - public boolean hasNext() { - if (this.doneIteration) { - return false; - } - if (this.shouldCalculate) { - FieldPair cache = internalNext(); - if (cache == null) { - this.doneIteration = true; - } - this.cache = cache; - this.shouldCalculate = false; - } - return !this.doneIteration; - } - - @Override - public FieldPair next() { - if (this.doneIteration) { - throw new NoSuchElementException("Exhausted iterator"); - } - - if (this.shouldCalculate) { - FieldPair cache = internalNext(); - if (cache == null) { - // this.doneIteration = true; - throw new IllegalStateException(); - } - this.cache = cache; - } - this.shouldCalculate = true; - return this.cache; - } - - /* - * This method corresponds to `next` method of MappingPairing. - */ - private FieldPair internalNext() { - FieldPair p; - if (this.i1 >= this.len1) { - if (this.i2 >= this.len2) { - return null; - } - p = new FieldPair(curName2(), this.rest1, curType2(), null, this.i2); - this.i2 += 1; - } else if (this.i2 >= this.len2) { - p = new FieldPair(curName1(), curType1(), this.rest2, this.i1, null); - this.i1 += 1; - } else { - String name1 = curName1(); - String name2 = curName2(); - if (Common.codePointCompare(name1, name2)) { - p = new FieldPair(name1, curType1(), this.rest2, this.i1, null); - this.i1 += 1; - } else if (Common.codePointCompare(name2, name1)) { - p = new FieldPair(name2, this.rest1, curType2(), null, this.i2); - this.i2 += 1; - } else { - p = new FieldPair(name1, curType1(), curType2(), this.i1, this.i2); - this.i1 += 1; - this.i2 += 1; - } - } - return p; - } - - private SemType curType1() { - return this.types1[this.i1]; - } - - private String curName1() { - return this.names1[this.i1]; - } - - private SemType curType2() { - return this.types2[this.i2]; - } - - private String curName2() { - return this.names2[this.i2]; - } - - public void reset() { - this.i1 = 0; - this.i2 = 0; - } - - public Optional index1(String name) { - int i1Prev = this.i1 - 1; - return i1Prev >= 0 && Objects.equals(this.names1[i1Prev], name) ? Optional.of(i1Prev) : Optional.empty(); - } - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Pair.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Pair.java deleted file mode 100644 index f8d4922c7f56..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Pair.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.api.types.semtype; - -/** - * Data structure used to pass around pairs of values. - * - * @param type of first value - * @param type of second value - * @param first first values - * @param second second value - * @since 2201.11.0 - */ -public record Pair(E1 first, E2 second) { - - public static Pair from(E1 first, E2 second) { - return new Pair<>(first, second); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/PredefinedTypeEnv.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/PredefinedTypeEnv.java deleted file mode 100644 index 1545a36e572e..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/PredefinedTypeEnv.java +++ /dev/null @@ -1,609 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.api.types.semtype; - -import io.ballerina.runtime.internal.types.semtype.BCellSubType; -import io.ballerina.runtime.internal.types.semtype.BListSubType; -import io.ballerina.runtime.internal.types.semtype.BMappingSubType; -import io.ballerina.runtime.internal.types.semtype.BObjectSubType; -import io.ballerina.runtime.internal.types.semtype.BTableSubType; -import io.ballerina.runtime.internal.types.semtype.CellAtomicType; -import io.ballerina.runtime.internal.types.semtype.FixedLengthArray; -import io.ballerina.runtime.internal.types.semtype.ListAtomicType; -import io.ballerina.runtime.internal.types.semtype.MappingAtomicType; -import io.ballerina.runtime.internal.types.semtype.XmlUtils; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Supplier; - -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_CELL; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_LIST; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_MAPPING; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_OBJECT; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_TABLE; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_XML; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.VT_INHERENTLY_IMMUTABLE; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.VT_MASK; -import static io.ballerina.runtime.api.types.semtype.BddNode.bddAtom; -import static io.ballerina.runtime.api.types.semtype.Builder.basicSubType; -import static io.ballerina.runtime.api.types.semtype.Builder.from; -import static io.ballerina.runtime.api.types.semtype.Builder.getBasicTypeUnion; -import static io.ballerina.runtime.api.types.semtype.Builder.getStringConst; -import static io.ballerina.runtime.api.types.semtype.Core.union; -import static io.ballerina.runtime.api.types.semtype.TypeAtom.createTypeAtom; - -final class PredefinedTypeEnv { - - private static PredefinedTypeEnv instance; - private final AtomicBoolean initialized = new AtomicBoolean(false); - private static final int BDD_REC_ATOM_OBJECT_READONLY = 1; - private static final RecAtom OBJECT_RO_REC_ATOM = RecAtom.createRecAtom(BDD_REC_ATOM_OBJECT_READONLY); - private static final BddNode MAPPING_SUBTYPE_OBJECT_RO = bddAtom(OBJECT_RO_REC_ATOM); - - private final List> initializedCellAtoms = new ArrayList<>(); - private final List> initializedListAtoms = new ArrayList<>(); - private final List> initializedMappingAtoms = new ArrayList<>(); - private final List initializedRecListAtoms = new ArrayList<>(); - private final List initializedRecMappingAtoms = new ArrayList<>(); - private final AtomicInteger nextAtomIndex = new AtomicInteger(0); - // This is to avoid passing down env argument when doing cell type operations. - // Please refer to the cellSubtypeDataEnsureProper() in cell.bal - private final Supplier cellAtomicVal = new ConcurrentLazySupplierWithCallback<>( - () -> CellAtomicType.from(getBasicTypeUnion(VT_MASK), CellAtomicType.CellMutability.CELL_MUT_LIMITED), - this::addInitializedCellAtom - ); - private final Supplier atomCellVal = - createTypeAtomSupplierFromCellAtomicSupplier(cellAtomicVal, this::cellAtomIndex); - private final Supplier cellSemTypeVal = new ConcurrentLazySupplier<>( - () -> basicSubType(BT_CELL, BCellSubType.createDelegate(bddAtom(atomCellVal())))); - private final Supplier cellAtomicNever = new ConcurrentLazySupplierWithCallback<>( - () -> CellAtomicType.from(SemType.from(0), CellAtomicType.CellMutability.CELL_MUT_LIMITED), - this::addInitializedCellAtom - ); - private final Supplier atomCellNever = - createTypeAtomSupplierFromCellAtomicSupplier(cellAtomicNever, this::cellAtomIndex); - // Represent the typeAtom required to construct equivalent subtypes of map and (any|error)[]. - - private final ConcurrentLazySupplier inner = - new ConcurrentLazySupplier<>(() -> SemType.from(VT_MASK | from(BasicTypeCode.BT_UNDEF).all())); - private final Supplier cellAtomicInner = new ConcurrentLazySupplierWithCallback<>( - () -> CellAtomicType.from(inner.get(), CellAtomicType.CellMutability.CELL_MUT_LIMITED), - this::addInitializedCellAtom - ); - private final Supplier atomCellInner = - createTypeAtomSupplierFromCellAtomicSupplier(cellAtomicInner, this::cellAtomIndex); - private final Supplier cellSemTypeInner = new ConcurrentLazySupplier<>( - () -> basicSubType(BT_CELL, BCellSubType.createDelegate(bddAtom(atomCellInner())))); - // TypeAtoms related to (map)[]. This is to avoid passing down env argument when doing - // tableSubtypeComplement operation. - private final Supplier cellAtomicInnerMapping = new ConcurrentLazySupplierWithCallback<>( - () -> CellAtomicType.from(union(Builder.getMappingType(), Builder.getUndefType()), - CellAtomicType.CellMutability.CELL_MUT_LIMITED), - this::addInitializedCellAtom - ); - private final Supplier atomCellInnerMapping = - createTypeAtomSupplierFromCellAtomicSupplier(cellAtomicInnerMapping, this::cellAtomIndex); - private final Supplier listAtomicMapping = new ConcurrentLazySupplierWithCallback<>( - () -> new ListAtomicType(FixedLengthArray.empty(), basicSubType( - BT_CELL, BCellSubType.createDelegate(bddAtom(atomCellInnerMapping())))), - this::addInitializedListAtom - ); - private final Supplier atomListMapping = - createTypeAtomSupplierFromCellAtomicSupplier(listAtomicMapping, this::listAtomIndex); - // TypeAtoms related to readonly type. This is to avoid requiring context when referring to readonly type. - // CELL_ATOMIC_INNER_MAPPING_RO & LIST_ATOMIC_MAPPING_RO are typeAtoms required to construct - // readonly & (map)[] which is then used for readonly table type when constructing VAL_READONLY - private final Supplier cellAtomicInnerMappingRO = new ConcurrentLazySupplierWithCallback<>( - () -> CellAtomicType.from(union(Builder.mappingRO(), Builder.getUndefType()), - CellAtomicType.CellMutability.CELL_MUT_LIMITED), - this::addInitializedCellAtom - ); - private final Supplier atomCellInnerMappingRO = - createTypeAtomSupplierFromCellAtomicSupplier(cellAtomicInnerMappingRO, this::cellAtomIndex); - private final Supplier listAtomicMappingRO = new ConcurrentLazySupplierWithCallback<>( - () -> new ListAtomicType(FixedLengthArray.empty(), basicSubType( - BT_CELL, BCellSubType.createDelegate(bddAtom(atomCellInnerMappingRO())))), - this::addInitializedListAtom - ); - - private final Supplier listSubtypeMapping = new ConcurrentLazySupplier<>( - () -> bddAtom(atomListMapping.get())); - private final Supplier mappingArray = new ConcurrentLazySupplier<>( - () -> basicSubType(BT_LIST, BListSubType.createDelegate(listSubtypeMapping.get()))); - private final Supplier cellAtomicMappingArray = new ConcurrentLazySupplierWithCallback<>(() -> - CellAtomicType.from(mappingArray.get(), CellAtomicType.CellMutability.CELL_MUT_LIMITED), - this::addInitializedCellAtom); - private final Supplier atomCellMappingArray = new ConcurrentLazySupplier<>(() -> { - CellAtomicType cellAtom = cellAtomicMappingArray.get(); - return createTypeAtom(cellAtomIndex(cellAtom), cellAtom); - }); - private final Supplier cellSemTypeListSubtypeMapping = new ConcurrentLazySupplier<>(() -> - basicSubType(BT_CELL, BCellSubType.createDelegate(bddAtom(atomCellMappingArray.get())))); - private final Supplier listAtomicThreeElement = new ConcurrentLazySupplierWithCallback<>( - () -> new ListAtomicType( - FixedLengthArray.from(new SemType[]{cellSemTypeListSubtypeMapping.get(), cellSemTypeVal.get()}, 3), - cellSemTypeVal.get()), - this::addInitializedListAtom - ); - private final Supplier atomListThreeElement = new ConcurrentLazySupplier<>(() -> { - ListAtomicType listAtomic = listAtomicThreeElement.get(); - return createTypeAtom(listAtomIndex(listAtomic), listAtomic); - }); - private final Supplier atomListMappingRO = - createTypeAtomSupplierFromCellAtomicSupplier(listAtomicMappingRO, this::listAtomIndex); - - private final Supplier cellAtomicUndef = new ConcurrentLazySupplierWithCallback<>( - () -> CellAtomicType.from(Builder.getUndefType(), CellAtomicType.CellMutability.CELL_MUT_NONE), - this::addInitializedCellAtom - ); - private final Supplier atomCellUndef = - createTypeAtomSupplierFromCellAtomicSupplier(cellAtomicUndef, this::cellAtomIndex); - private final Supplier cellSemTypeUndef = new ConcurrentLazySupplier<>( - () -> basicSubType(BT_CELL, BCellSubType.createDelegate(bddAtom(atomCellUndef.get())))); - - private final Supplier listSubtypeMappingRO = new ConcurrentLazySupplier<>(() -> bddAtom( - atomListMappingRO.get())); - private final Supplier mappingArrayRO = new ConcurrentLazySupplier<>(() -> basicSubType( - BT_LIST, BListSubType.createDelegate(listSubtypeMappingRO.get()))); - private final Supplier cellAtomicMappingArrayRO = new ConcurrentLazySupplierWithCallback<>( - () -> CellAtomicType.from(mappingArrayRO.get(), CellAtomicType.CellMutability.CELL_MUT_LIMITED), - this::addInitializedCellAtom - ); - private final Supplier atomCellMappingArrayRO = new ConcurrentLazySupplier<>(() -> { - CellAtomicType cellAtom = cellAtomicMappingArrayRO.get(); - return createTypeAtom(cellAtomIndex(cellAtom), cellAtom); - }); - private final Supplier cellSemTypeListSubtypeMappingRO = new ConcurrentLazySupplier<>( - () -> basicSubType(BT_CELL, BCellSubType.createDelegate(bddAtom(atomCellMappingArrayRO.get())))); - private final Supplier listAtomicThreeElementRO = new ConcurrentLazySupplierWithCallback<>( - () -> new ListAtomicType( - FixedLengthArray.from(new SemType[]{cellSemTypeListSubtypeMappingRO.get(), cellSemTypeVal.get()}, - 3), - cellSemTypeUndef.get()), - this::addInitializedListAtom - ); - private final Supplier atomListThreeElementRO = new ConcurrentLazySupplier<>(() -> { - ListAtomicType listAtomic = listAtomicThreeElementRO.get(); - return createTypeAtom(listAtomIndex(listAtomic), listAtomic); - }); - - private final Supplier readonlyType = new ConcurrentLazySupplier<>(() -> unionOf( - SemType.from(VT_INHERENTLY_IMMUTABLE), - basicSubType(BT_LIST, BListSubType.createDelegate(bddSubtypeRo())), - basicSubType(BT_MAPPING, BMappingSubType.createDelegate(bddSubtypeRo())), - basicSubType(BT_OBJECT, BObjectSubType.createDelegate(MAPPING_SUBTYPE_OBJECT_RO)), - basicSubType(BT_TABLE, BTableSubType.createDelegate(bddAtom(atomListThreeElementRO.get()))), - basicSubType(BT_XML, XmlUtils.XML_SUBTYPE_RO) - )); - - private final ConcurrentLazySupplier innerReadOnly = - new ConcurrentLazySupplier<>(() -> union(readonlyType.get(), inner.get())); - private final Supplier cellAtomicInnerRO = new ConcurrentLazySupplierWithCallback<>( - () -> CellAtomicType.from(innerReadOnly.get(), CellAtomicType.CellMutability.CELL_MUT_NONE), - this::addInitializedCellAtom - ); - private final Supplier atomCellInnerRO = - createTypeAtomSupplierFromCellAtomicSupplier(cellAtomicInnerRO, this::cellAtomIndex); - private final Supplier cellSemTypeInnerRO = new ConcurrentLazySupplier<>( - () -> basicSubType(BT_CELL, BCellSubType.createDelegate(bddAtom(atomCellInnerRO.get())))); - private final Supplier listAtomicRO = new ConcurrentLazySupplierWithCallback<>( - () -> new ListAtomicType(FixedLengthArray.empty(), cellSemTypeInnerRO.get()), - this.initializedRecListAtoms::add - ); - private final Supplier mappingAtomicRO = new ConcurrentLazySupplierWithCallback<>( - () -> new MappingAtomicType(new String[]{}, new SemType[]{}, cellSemTypeInnerRO.get()), - initializedRecMappingAtoms::add - ); - // TypeAtoms related to [any|error, any|error]. This is to avoid passing down env argument when doing - // streamSubtypeComplement operation. - private final Supplier cellAtomicObjectMemberKind = - new ConcurrentLazySupplierWithCallback<>( - () -> CellAtomicType.from( - union(getStringConst("field"), getStringConst("method")), - CellAtomicType.CellMutability.CELL_MUT_NONE), - this::addInitializedCellAtom); - private final Supplier atomCellObjectMemberKind = - createTypeAtomSupplierFromCellAtomicSupplier(cellAtomicObjectMemberKind, this::cellAtomIndex); - private final Supplier cellSemTypeObjectMemberKind = new ConcurrentLazySupplier<>( - () -> Builder.basicSubType(BT_CELL, BCellSubType.createDelegate(bddAtom(atomCellObjectMemberKind())))); - private final Supplier cellAtomicObjectMemberVisibility = - new ConcurrentLazySupplierWithCallback<>( - () -> CellAtomicType.from( - union(getStringConst("public"), getStringConst("private")), - CellAtomicType.CellMutability.CELL_MUT_NONE), - this::addInitializedCellAtom); - private final Supplier atomCellObjectMemberVisibility = - createTypeAtomSupplierFromCellAtomicSupplier(cellAtomicObjectMemberVisibility, this::cellAtomIndex); - private final Supplier cellSemTypeObjectMemberVisibility = new ConcurrentLazySupplier<>( - () -> basicSubType(BT_CELL, BCellSubType.createDelegate(bddAtom(atomCellObjectMemberVisibility())))); - private final Supplier mappingAtomicObjectMember = new ConcurrentLazySupplierWithCallback<>( - () -> new MappingAtomicType( - new String[]{"kind", "value", "visibility"}, - new SemType[]{cellSemTypeObjectMemberKind.get(), cellSemTypeVal.get(), - cellSemTypeObjectMemberVisibility.get()}, - cellSemTypeUndef.get()), - this::addInitializedMapAtom - ); - private final Supplier atomMappingObjectMember = - createTypeAtomSupplierFromCellAtomicSupplier(mappingAtomicObjectMember, this::mappingAtomIndex); - private final Supplier mappingSemTypeObjectMember = new ConcurrentLazySupplier<>( - () -> basicSubType(BT_MAPPING, BMappingSubType.createDelegate(bddAtom(atomMappingObjectMember())))); - private final Supplier cellAtomicObjectMember = - new ConcurrentLazySupplierWithCallback<>( - () -> CellAtomicType.from( - mappingSemTypeObjectMember.get(), CellAtomicType.CellMutability.CELL_MUT_UNLIMITED), - this::addInitializedCellAtom); - private final Supplier atomCellObjectMember = - createTypeAtomSupplierFromCellAtomicSupplier(cellAtomicObjectMember, this::cellAtomIndex); - private final Supplier cellSemTypeObjectMember = new ConcurrentLazySupplier<>( - () -> basicSubType(BT_CELL, BCellSubType.createDelegate(bddAtom(atomCellObjectMember())))); - private final Supplier mappingAtomicObject = new ConcurrentLazySupplierWithCallback<>( - () -> new MappingAtomicType( - new String[]{"$qualifiers"}, new SemType[]{cellSemTypeVal.get()}, - cellSemTypeObjectMember.get() - ), - this::addInitializedMapAtom - ); - private final Supplier atomMappingObject = - createTypeAtomSupplierFromCellAtomicSupplier(mappingAtomicObject, this::mappingAtomIndex); - private final Supplier cellAtomicValRO = - new ConcurrentLazySupplierWithCallback<>( - () -> CellAtomicType.from( - readonlyType.get(), CellAtomicType.CellMutability.CELL_MUT_NONE), - this::addInitializedCellAtom); - private final Supplier atomCellValRO = - createTypeAtomSupplierFromCellAtomicSupplier(cellAtomicValRO, this::cellAtomIndex); - private final Supplier cellSemTypeValRo = new ConcurrentLazySupplier<>( - () -> basicSubType(BT_CELL, BCellSubType.createDelegate(bddAtom(atomCellValRO())))); - private final Supplier mappingAtomicObjectMemberRO = new ConcurrentLazySupplierWithCallback<>( - () -> new MappingAtomicType( - new String[]{"kind", "value", "visibility"}, - new SemType[]{cellSemTypeObjectMemberKind.get(), cellSemTypeValRo.get(), - cellSemTypeObjectMemberVisibility.get()}, - cellSemTypeUndef.get()), - this::addInitializedMapAtom - ); - private final Supplier atomMappingObjectMemberRO = - createTypeAtomSupplierFromCellAtomicSupplier(mappingAtomicObjectMemberRO, this::mappingAtomIndex); - private final Supplier mappingSemTypeObjectMemberRO = new ConcurrentLazySupplier<>( - () -> basicSubType(BT_MAPPING, BMappingSubType.createDelegate(bddAtom(atomMappingObjectMemberRO())))); - private final Supplier cellAtomicObjectMemberRO = - new ConcurrentLazySupplierWithCallback<>( - () -> CellAtomicType.from( - mappingSemTypeObjectMemberRO.get(), CellAtomicType.CellMutability.CELL_MUT_NONE), - this::addInitializedCellAtom); - private final Supplier atomCellObjectMemberRO = - createTypeAtomSupplierFromCellAtomicSupplier(cellAtomicObjectMemberRO, this::cellAtomIndex); - private final Supplier cellSemTypeObjectMemberRO = new ConcurrentLazySupplier<>( - () -> basicSubType(BT_CELL, BCellSubType.createDelegate(bddAtom(atomCellObjectMemberRO())))); - private final Supplier mappingAtomicObjectRO = new ConcurrentLazySupplierWithCallback<>( - () -> new MappingAtomicType( - new String[]{"$qualifiers"}, new SemType[]{cellSemTypeVal.get()}, - cellSemTypeObjectMemberRO.get() - ), - initializedRecMappingAtoms::add - ); - - private final Supplier listAtomicTwoElement = new ConcurrentLazySupplierWithCallback<>( - () -> new ListAtomicType( - FixedLengthArray.from(new SemType[]{cellSemTypeVal.get()}, 2), - cellSemTypeUndef.get()), - this::addInitializedListAtom - ); - private final Supplier atomListTwoElement = new ConcurrentLazySupplier<>(() -> { - ListAtomicType listAtomic = listAtomicTwoElement.get(); - return createTypeAtom(listAtomIndex(listAtomic), listAtomic); - }); - - private PredefinedTypeEnv() { - } - - private static SemType unionOf(SemType... types) { - SemType accum = types[0]; - for (int i = 1; i < types.length; i++) { - accum = union(accum, types[i]); - } - return accum; - } - - private static BddNode bddSubtypeRo() { - return bddAtom(RecAtom.createRecAtom(0)); - } - - - public static synchronized PredefinedTypeEnv getInstance() { - if (instance == null) { - instance = new PredefinedTypeEnv(); - instance.initialize(); - } - return instance; - } - - private static Supplier createTypeAtomSupplierFromCellAtomicSupplier( - Supplier atomicTypeSupplier, IndexSupplier indexSupplier) { - return new ConcurrentLazySupplier<>(() -> { - E atomicType = atomicTypeSupplier.get(); - int index = indexSupplier.get(atomicType); - return createTypeAtom(index, atomicType); - }); - } - - private void initialize() { - // Initialize RecAtoms - mappingAtomicRO(); - listAtomicRO(); - mappingAtomicObjectRO(); - - // initialize atomic types - cellAtomicVal(); - cellAtomicNever(); - cellAtomicInner(); - cellAtomicInnerMapping(); - listAtomicMapping(); - cellAtomicInner(); - listAtomicMappingRO(); - cellAtomicInnerRO(); - initialized.set(true); - } - - private void addInitializedCellAtom(CellAtomicType atom) { - addInitializedAtom(initializedCellAtoms, atom); - } - - private void addInitializedListAtom(ListAtomicType atom) { - addInitializedAtom(initializedListAtoms, atom); - } - - private void addInitializedMapAtom(MappingAtomicType atom) { - addInitializedAtom(initializedMappingAtoms, atom); - } - - private void addInitializedAtom(Collection> atoms, E atom) { - atoms.add(new InitializedTypeAtom<>(atom, nextAtomIndex.getAndIncrement())); - } - - private int cellAtomIndex(CellAtomicType atom) { - return atomIndex(initializedCellAtoms, atom); - } - - private int listAtomIndex(ListAtomicType atom) { - return atomIndex(initializedListAtoms, atom); - } - - private int mappingAtomIndex(MappingAtomicType atom) { - return atomIndex(initializedMappingAtoms, atom); - } - - private int atomIndex(List> initializedAtoms, E atom) { - for (InitializedTypeAtom initializedListAtom : initializedAtoms) { - if (initializedListAtom.atomicType() == atom) { - return initializedListAtom.index(); - } - } - throw new IndexOutOfBoundsException(); - } - - CellAtomicType cellAtomicVal() { - return cellAtomicVal.get(); - } - - TypeAtom atomCellVal() { - return atomCellVal.get(); - } - - CellAtomicType cellAtomicNever() { - return cellAtomicNever.get(); - } - - TypeAtom atomCellNever() { - return atomCellNever.get(); - } - - CellAtomicType cellAtomicInner() { - return cellAtomicInner.get(); - } - - TypeAtom atomCellInner() { - return atomCellInner.get(); - } - - CellAtomicType cellAtomicInnerMapping() { - return cellAtomicInnerMapping.get(); - } - - TypeAtom atomCellInnerMapping() { - return atomCellInnerMapping.get(); - } - - CellAtomicType cellAtomicInnerMappingRO() { - return cellAtomicInnerMappingRO.get(); - } - - TypeAtom atomCellInnerMappingRO() { - return atomCellInnerMappingRO.get(); - } - - ListAtomicType listAtomicMapping() { - return listAtomicMapping.get(); - } - - TypeAtom atomListMapping() { - return atomListMapping.get(); - } - - ListAtomicType listAtomicMappingRO() { - return listAtomicMappingRO.get(); - } - - TypeAtom atomListMappingRO() { - return atomListMappingRO.get(); - } - - CellAtomicType cellAtomicInnerRO() { - return cellAtomicInnerRO.get(); - } - - TypeAtom atomCellInnerRO() { - return atomCellInnerRO.get(); - } - - CellAtomicType cellAtomicUndef() { - return cellAtomicUndef.get(); - } - - TypeAtom atomCellUndef() { - return atomCellUndef.get(); - } - - CellAtomicType cellAtomicValRO() { - return cellAtomicValRO.get(); - } - - TypeAtom atomCellValRO() { - return atomCellValRO.get(); - } - - MappingAtomicType mappingAtomicObjectMemberRO() { - return mappingAtomicObjectMemberRO.get(); - } - - TypeAtom atomMappingObjectMemberRO() { - return atomMappingObjectMemberRO.get(); - } - - CellAtomicType cellAtomicObjectMemberRO() { - return cellAtomicObjectMemberRO.get(); - } - - TypeAtom atomCellObjectMemberRO() { - return atomCellObjectMemberRO.get(); - } - - CellAtomicType cellAtomicObjectMemberKind() { - return cellAtomicObjectMemberKind.get(); - } - - TypeAtom atomCellObjectMemberKind() { - return atomCellObjectMemberKind.get(); - } - - CellAtomicType cellAtomicObjectMemberVisibility() { - return cellAtomicObjectMemberVisibility.get(); - } - - TypeAtom atomCellObjectMemberVisibility() { - return atomCellObjectMemberVisibility.get(); - } - - MappingAtomicType mappingAtomicObjectMember() { - return mappingAtomicObjectMember.get(); - } - - TypeAtom atomMappingObjectMember() { - return atomMappingObjectMember.get(); - } - - CellAtomicType cellAtomicObjectMember() { - return cellAtomicObjectMember.get(); - } - - TypeAtom atomCellObjectMember() { - return atomCellObjectMember.get(); - } - - MappingAtomicType mappingAtomicObject() { - return mappingAtomicObject.get(); - } - - TypeAtom atomMappingObject() { - return atomMappingObject.get(); - } - - ListAtomicType listAtomicRO() { - return listAtomicRO.get(); - } - - MappingAtomicType mappingAtomicRO() { - return mappingAtomicRO.get(); - } - - MappingAtomicType mappingAtomicObjectRO() { - return mappingAtomicObjectRO.get(); - } - - TypeAtom atomListThreeElement() { - return atomListThreeElement.get(); - } - - TypeAtom atomListThreeElementRO() { - return atomListThreeElementRO.get(); - } - - SemType readonlyType() { - return readonlyType.get(); - } - - // Due to some reason SpotBug thinks this method is overrideable if we don't put final here as well. - final void initializeEnv(Env env) { - assert initialized.get() : "PredefinedTypeEnv has not fully initialized, check concurrency issues"; - fillRecAtoms(env.recListAtoms, initializedRecListAtoms); - fillRecAtoms(env.recMappingAtoms, initializedRecMappingAtoms); - initializedCellAtoms.forEach(each -> env.cellAtom(each.atomicType())); - initializedListAtoms.forEach(each -> env.listAtom(each.atomicType())); - } - - private void fillRecAtoms(List envRecAtomList, List initializedRecAtoms) { - int count = reservedRecAtomCount(); - for (int i = 0; i < count; i++) { - if (i < initializedRecAtoms.size()) { - envRecAtomList.add(initializedRecAtoms.get(i)); - } else { - // This is mainly to help with bir serialization/deserialization logic. Given the number of such atoms - // will be small this shouldn't be a problem. - envRecAtomList.add(null); - } - } - } - - private int reservedRecAtomCount() { - return Integer.max(initializedRecListAtoms.size(), initializedRecMappingAtoms.size()); - } - - SemType cellSemTypeInner() { - return cellSemTypeInner.get(); - } - - public Atom atomListTwoElement() { - return atomListTwoElement.get(); - } - - @FunctionalInterface - private interface IndexSupplier { - - int get(E atomicType); - } - - private record InitializedTypeAtom(E atomicType, int index) { - - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/RecAtom.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/RecAtom.java deleted file mode 100644 index f302a7dc3c45..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/RecAtom.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package io.ballerina.runtime.api.types.semtype; - -/** - * Represent a recursive type atom. - * - * @since 2201.11.0 - */ -public final class RecAtom implements Atom { - - private final int index; - private static final int BDD_REC_ATOM_READONLY = 0; - private static final RecAtom ZERO = new RecAtom(BDD_REC_ATOM_READONLY); - - private RecAtom(int index) { - this.index = index; - } - - public static RecAtom createRecAtom(int index) { - if (index == BDD_REC_ATOM_READONLY) { - return ZERO; - } - return new RecAtom(index); - } - - public static RecAtom createDistinctRecAtom(int index) { - return new RecAtom(index); - } - - @Override - public int index() { - return index; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o instanceof RecAtom recAtom) { - return recAtom.index == this.index; - } - return false; - } - - @Override - public int hashCode() { - return index; - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/SemType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/SemType.java deleted file mode 100644 index d185c96b6c7f..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/SemType.java +++ /dev/null @@ -1,71 +0,0 @@ -package io.ballerina.runtime.api.types.semtype; - -import io.ballerina.runtime.api.types.Type; -import io.ballerina.runtime.internal.types.semtype.ImmutableSemType; -import io.ballerina.runtime.internal.types.semtype.MutableSemType; -import io.ballerina.runtime.internal.types.semtype.SemTypeHelper; - -/** - * Represent a type in runtime. - * - * @since 2201.11.0 - */ -public sealed class SemType extends BasicTypeBitSet - permits io.ballerina.runtime.internal.types.BType, ImmutableSemType { - - private int some; - private SubType[] subTypeData; - - protected SemType(int all, int some, SubType[] subTypeData) { - super(all); - this.some = some; - this.subTypeData = subTypeData; - } - - protected SemType() { - this(-1, -1, null); - } - - public static SemType from(int all) { - return new SemType(all, 0, null); - } - - public static SemType from(int all, int some, SubType[] subTypes) { - return new SemType(all, some, subTypes); - } - - public final int some() { - assert some != -1 : "SemType created by no arg constructor must be initialized with setSome"; - return some; - } - - public final SubType[] subTypeData() { - return subTypeData; - } - - public final SubType subTypeByCode(int code) { - if ((some() & (1 << code)) == 0) { - return null; - } - int someMask = (1 << code) - 1; - int some = some() & someMask; - return subTypeData()[Integer.bitCount(some)]; - } - - protected void setSome(int some, SubType[] subTypeData) { - this.some = some; - this.subTypeData = subTypeData; - } - - public static SemType tryInto(Type type) { - if (type instanceof MutableSemType mutableSemType) { - mutableSemType.updateInnerSemTypeIfNeeded(); - } - return (SemType) type; - } - - @Override - public String toString() { - return SemTypeHelper.stringRepr(this); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/ShapeAnalyzer.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/ShapeAnalyzer.java deleted file mode 100644 index 99bc4c9a51f5..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/ShapeAnalyzer.java +++ /dev/null @@ -1,72 +0,0 @@ -package io.ballerina.runtime.api.types.semtype; - -import io.ballerina.runtime.api.types.Type; -import io.ballerina.runtime.api.values.BString; -import io.ballerina.runtime.api.values.BValue; -import io.ballerina.runtime.internal.types.TypeWithAcceptedType; -import io.ballerina.runtime.internal.types.TypeWithShape; -import io.ballerina.runtime.internal.values.DecimalValue; - -import java.util.Optional; - -/** - * Utility class for performing shape related operations. - * - * @since 2201.11.0 - */ -public class ShapeAnalyzer { - - private ShapeAnalyzer() { - } - - public static Optional acceptedTypeOf(Context cx, Type typeDesc) { - if (typeDesc instanceof TypeWithAcceptedType typeWithAcceptedType) { - return typeWithAcceptedType.acceptedTypeOf(cx); - } - return Optional.of(SemType.tryInto(typeDesc)); - } - - public static Optional shapeOf(Context cx, Object object) { - if (object == null) { - return Optional.of(Builder.getNilType()); - } else if (object instanceof DecimalValue decimalValue) { - return Optional.of(Builder.getDecimalConst(decimalValue.value())); - } else if (object instanceof Double doubleValue) { - return Optional.of(Builder.getFloatConst(doubleValue)); - } else if (object instanceof Number intValue) { - long value = - intValue instanceof Byte byteValue ? Byte.toUnsignedLong(byteValue) : intValue.longValue(); - return Optional.of(Builder.getIntConst(value)); - } else if (object instanceof Boolean booleanValue) { - return Optional.of(Builder.getBooleanConst(booleanValue)); - } else if (object instanceof BString stringValue) { - return Optional.of(Builder.getStringConst(stringValue.getValue())); - } else if (object instanceof BValue bValue) { - Type type = bValue.getType(); - if (type instanceof TypeWithShape typeWithShape) { - return typeWithShape.shapeOf(cx, ShapeAnalyzer::shapeOf, object); - } else { - return Optional.empty(); - } - } - return Optional.empty(); - } - - public static Optional inherentTypeOf(Context cx, Object object) { - if (object instanceof BValue bValue) { - return bValue.inherentTypeOf(cx); - } - if (object == null) { - return Optional.of(Builder.getNilType()); - } else if (object instanceof Double doubleValue) { - return Optional.of(Builder.getFloatConst(doubleValue)); - } else if (object instanceof Number intValue) { - long value = - intValue instanceof Byte byteValue ? Byte.toUnsignedLong(byteValue) : intValue.longValue(); - return Optional.of(Builder.getIntConst(value)); - } else if (object instanceof Boolean booleanValue) { - return Optional.of(Builder.getBooleanConst(booleanValue)); - } - return Optional.empty(); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/SubType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/SubType.java deleted file mode 100644 index 85fabfa2303b..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/SubType.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.api.types.semtype; - -import io.ballerina.runtime.internal.types.semtype.SubTypeData; - -import java.util.Objects; - -/** - * Describe set of operation supported by each basic Type. - * - * @since 2201.11.0 - */ -public abstract class SubType { - - private final boolean all; - private final boolean nothing; - - protected SubType(boolean all, boolean nothing) { - this.all = all; - this.nothing = nothing; - } - - public abstract SubType union(SubType other); - - public abstract SubType intersect(SubType other); - - public SubType diff(SubType other) { - return this.intersect(other.complement()); - } - - public abstract SubType complement(); - - public abstract boolean isEmpty(Context cx); - - public final boolean isAll() { - return all; - } - - public final boolean isNothing() { - return nothing; - } - - public abstract SubTypeData data(); - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - SubType other = (SubType) o; - return Objects.equals(data(), other.data()); - } - - @Override - public int hashCode() { - return Objects.hashCode(data()); - } - -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/TypeAtom.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/TypeAtom.java deleted file mode 100644 index 02080171937e..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/TypeAtom.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.api.types.semtype; - -/** - * Represent a TypeAtom. Each operand of a type operation could be thought of as - * an atom - * - * @param index unique index within the {@code Env} - * @param atomicType atomic type representing the actual type represented by - * this atom. - * @since 2201.11.0 - */ -public record TypeAtom(int index, AtomicType atomicType) implements Atom { - - public TypeAtom { - assert atomicType != null; - } - - public static TypeAtom createTypeAtom(int index, AtomicType atomicType) { - return new TypeAtom(index, atomicType); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/TypeCheckCache.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/TypeCheckCache.java deleted file mode 100644 index a3ef0861072f..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/TypeCheckCache.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.ballerina.runtime.api.types.semtype; - -import io.ballerina.runtime.api.types.Type; - -import java.util.Map; -import java.util.Optional; -import java.util.WeakHashMap; - -/** - * Generalized implementation of type check result cache. It is okay to access - * this from multiple threads but makes no - * guarantee about the consistency of the cache under parallel access. Given - * result don't change due to race conditions - * this should eventually become consistent. - * - * @param Type of the type descriptor which owns this cache - * @since 2201.11.0 - */ -public class TypeCheckCache { - - // Not synchronizing this should be fine since race conditions don't lead to inconsistent results. (i.e. results - // of doing multiple type checks are agnostic to the order of execution). Data races shouldn't lead to tearing in - // 64-bit JVMs. - private final Map cachedResults = new WeakHashMap<>(); - private final T owner; - - public TypeCheckCache(T owner) { - this.owner = owner; - } - - public Optional cachedTypeCheckResult(T other) { - return Optional.ofNullable(cachedResults.get(other)); - } - - public void cacheTypeCheckResult(T other, boolean result) { - cachedResults.put(other, result); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BCollection.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BCollection.java index 1c9d28de48da..a95834a70d6e 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BCollection.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BCollection.java @@ -17,8 +17,6 @@ */ package io.ballerina.runtime.api.values; -import io.ballerina.runtime.api.types.semtype.SemType; - /** *

* {@link BCollection} represents a collection in Ballerina. @@ -34,12 +32,4 @@ public interface BCollection { * @return iterator created. */ BIterator getIterator(); - - default SemType shapeOf() { - return null; - } - - default void cacheShape(SemType semType) { - - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BError.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BError.java index 5dd81119cabd..88b368d827f4 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BError.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BError.java @@ -17,14 +17,8 @@ */ package io.ballerina.runtime.api.values; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.ShapeAnalyzer; -import io.ballerina.runtime.internal.types.TypeWithShape; - import java.io.PrintWriter; import java.util.List; -import java.util.Optional; /** *

@@ -89,9 +83,4 @@ public void printStackTrace(PrintWriter printWriter) { */ public abstract List getCallStack(); - @Override - public Optional inherentTypeOf(Context cx) { - TypeWithShape type = (TypeWithShape) getType(); - return type.inherentTypeOf(cx, ShapeAnalyzer::inherentTypeOf, this); - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BRegexpValue.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BRegexpValue.java index ed62af17014f..7de5799b3f45 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BRegexpValue.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BRegexpValue.java @@ -17,11 +17,8 @@ */ package io.ballerina.runtime.api.values; -import io.ballerina.runtime.api.types.semtype.SemType; import io.ballerina.runtime.internal.values.RegExpDisjunction; -import java.util.Optional; - /** *

* Represents RegexpValue. @@ -36,6 +33,4 @@ public interface BRegexpValue extends BValue { public RegExpDisjunction getRegExpDisjunction(); BTypedesc getTypedesc(); - - Optional shapeOf(); } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BString.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BString.java index 08d9a54c4e23..b7308732d7bc 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BString.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BString.java @@ -17,8 +17,6 @@ */ package io.ballerina.runtime.api.values; -import io.ballerina.runtime.api.types.Type; - /** * Interface representing ballerina strings. * @@ -42,5 +40,4 @@ public interface BString { BIterator getIterator(); - Type getType(); } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BValue.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BValue.java index c23f563ff6d1..82a8bdac0a59 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BValue.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BValue.java @@ -18,11 +18,8 @@ package io.ballerina.runtime.api.values; import io.ballerina.runtime.api.types.Type; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SemType; import java.util.Map; -import java.util.Optional; /** *

@@ -61,20 +58,4 @@ default String informalStringValue(BLink parent) { String expressionStringValue(BLink parent); Type getType(); - - /** - * Basic type of the value. - * - * @return {@code SemType} representing the value's basic type - */ - default SemType widenedType() { - // This is wrong since we are actually returning the actual (narrowed) type of the value. But since this is - // used only as an optimization (to avoid recalculating singleton type) in the type checker this is better - // than caching the widened types as well. - return SemType.tryInto(getType()); - } - - default Optional inherentTypeOf(Context cx) { - return Optional.empty(); - } } 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 d1d5aeb91d80..4705c4ead712 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 @@ -22,19 +22,14 @@ import io.ballerina.runtime.api.types.ArrayType.ArrayState; import io.ballerina.runtime.api.types.Field; import io.ballerina.runtime.api.types.FunctionType; -import io.ballerina.runtime.api.types.MapType; +import io.ballerina.runtime.api.types.IntersectionType; import io.ballerina.runtime.api.types.MethodType; -import io.ballerina.runtime.api.types.ReadonlyType; +import io.ballerina.runtime.api.types.PredefinedTypes; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; +import io.ballerina.runtime.api.types.UnionType; import io.ballerina.runtime.api.types.XmlNodeType; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.CacheableTypeDescriptor; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.ShapeAnalyzer; +import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.values.BDecimal; import io.ballerina.runtime.api.values.BError; import io.ballerina.runtime.api.values.BObject; @@ -42,39 +37,64 @@ import io.ballerina.runtime.api.values.BString; import io.ballerina.runtime.api.values.BValue; import io.ballerina.runtime.api.values.BXml; +import io.ballerina.runtime.internal.commons.TypeValuePair; import io.ballerina.runtime.internal.types.BAnnotatableType; import io.ballerina.runtime.internal.types.BArrayType; -import io.ballerina.runtime.internal.types.BBooleanType; +import io.ballerina.runtime.internal.types.BErrorType; +import io.ballerina.runtime.internal.types.BField; import io.ballerina.runtime.internal.types.BFiniteType; +import io.ballerina.runtime.internal.types.BFunctionType; +import io.ballerina.runtime.internal.types.BFutureType; import io.ballerina.runtime.internal.types.BIntersectionType; +import io.ballerina.runtime.internal.types.BJsonType; +import io.ballerina.runtime.internal.types.BMapType; +import io.ballerina.runtime.internal.types.BNetworkObjectType; import io.ballerina.runtime.internal.types.BObjectType; +import io.ballerina.runtime.internal.types.BParameterizedType; import io.ballerina.runtime.internal.types.BRecordType; +import io.ballerina.runtime.internal.types.BResourceMethodType; +import io.ballerina.runtime.internal.types.BStreamType; import io.ballerina.runtime.internal.types.BTableType; import io.ballerina.runtime.internal.types.BTupleType; import io.ballerina.runtime.internal.types.BType; +import io.ballerina.runtime.internal.types.BTypeIdSet; import io.ballerina.runtime.internal.types.BTypeReferenceType; +import io.ballerina.runtime.internal.types.BTypedescType; import io.ballerina.runtime.internal.types.BUnionType; -import io.ballerina.runtime.internal.types.TypeWithShape; +import io.ballerina.runtime.internal.types.BXmlType; import io.ballerina.runtime.internal.utils.ErrorUtils; +import io.ballerina.runtime.internal.values.ArrayValue; import io.ballerina.runtime.internal.values.DecimalValue; import io.ballerina.runtime.internal.values.DecimalValueKind; +import io.ballerina.runtime.internal.values.ErrorValue; import io.ballerina.runtime.internal.values.HandleValue; -import io.ballerina.runtime.internal.values.RefValue; +import io.ballerina.runtime.internal.values.MapValue; +import io.ballerina.runtime.internal.values.MapValueImpl; import io.ballerina.runtime.internal.values.RegExpValue; +import io.ballerina.runtime.internal.values.StreamValue; +import io.ballerina.runtime.internal.values.TableValueImpl; +import io.ballerina.runtime.internal.values.TupleValueImpl; import io.ballerina.runtime.internal.values.TypedescValue; import io.ballerina.runtime.internal.values.TypedescValueImpl; import io.ballerina.runtime.internal.values.ValuePair; +import io.ballerina.runtime.internal.values.XmlComment; +import io.ballerina.runtime.internal.values.XmlItem; +import io.ballerina.runtime.internal.values.XmlPi; import io.ballerina.runtime.internal.values.XmlSequence; +import io.ballerina.runtime.internal.values.XmlText; import io.ballerina.runtime.internal.values.XmlValue; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.function.Predicate; -import java.util.stream.Stream; import static io.ballerina.runtime.api.constants.RuntimeConstants.BALLERINA_BUILTIN_PKG_PREFIX; import static io.ballerina.runtime.api.constants.RuntimeConstants.BBYTE_MAX_VALUE; @@ -89,6 +109,8 @@ import static io.ballerina.runtime.api.constants.RuntimeConstants.UNSIGNED16_MAX_VALUE; import static io.ballerina.runtime.api.constants.RuntimeConstants.UNSIGNED32_MAX_VALUE; import static io.ballerina.runtime.api.constants.RuntimeConstants.UNSIGNED8_MAX_VALUE; +import static io.ballerina.runtime.api.types.PredefinedTypes.TYPE_ANY; +import static io.ballerina.runtime.api.types.PredefinedTypes.TYPE_ANYDATA; import static io.ballerina.runtime.api.types.PredefinedTypes.TYPE_BOOLEAN; import static io.ballerina.runtime.api.types.PredefinedTypes.TYPE_BYTE; import static io.ballerina.runtime.api.types.PredefinedTypes.TYPE_DECIMAL; @@ -100,8 +122,15 @@ import static io.ballerina.runtime.api.types.PredefinedTypes.TYPE_INT_UNSIGNED_16; import static io.ballerina.runtime.api.types.PredefinedTypes.TYPE_INT_UNSIGNED_32; import static io.ballerina.runtime.api.types.PredefinedTypes.TYPE_INT_UNSIGNED_8; +import static io.ballerina.runtime.api.types.PredefinedTypes.TYPE_JSON; import static io.ballerina.runtime.api.types.PredefinedTypes.TYPE_NULL; +import static io.ballerina.runtime.api.types.PredefinedTypes.TYPE_READONLY_JSON; +import static io.ballerina.runtime.api.types.PredefinedTypes.TYPE_STRING; import static io.ballerina.runtime.api.utils.TypeUtils.getImpliedType; +import static io.ballerina.runtime.api.utils.TypeUtils.isValueType; +import static io.ballerina.runtime.internal.TypeConverter.ERROR_MESSAGE_UNION_END; +import static io.ballerina.runtime.internal.TypeConverter.ERROR_MESSAGE_UNION_SEPARATOR; +import static io.ballerina.runtime.internal.TypeConverter.ERROR_MESSAGE_UNION_START; import static io.ballerina.runtime.internal.utils.CloneUtils.getErrorMessage; /** @@ -114,37 +143,32 @@ public final class TypeChecker { private static final byte MAX_TYPECAST_ERROR_COUNT = 20; private static final String REG_EXP_TYPENAME = "RegExp"; - private static final ThreadLocal threadContext = - ThreadLocal.withInitial(() -> Context.from(Env.getInstance())); public static Object checkCast(Object sourceVal, Type targetType) { List errors = new ArrayList<>(); - if (checkIsType(sourceVal, targetType)) { + Type sourceType = getImpliedType(getType(sourceVal)); + if (checkIsType(errors, sourceVal, sourceType, targetType)) { return sourceVal; } - Type sourceType = getType(sourceVal); - if (Core.containsBasicType(SemType.tryInto(sourceType), ConvertibleCastMaskHolder.CONVERTIBLE_CAST_MASK) && - Core.containsBasicType(SemType.tryInto(targetType), ConvertibleCastMaskHolder.CONVERTIBLE_CAST_MASK)) { - // We need to maintain order for these? - if (targetType instanceof BUnionType unionType) { - for (Type memberType : unionType.getMemberTypes()) { - try { - return TypeConverter.castValues(memberType, sourceVal); - } catch (Exception e) { - //ignore and continue - } + + if (sourceType.getTag() <= TypeTags.BOOLEAN_TAG && targetType.getTag() <= TypeTags.BOOLEAN_TAG) { + return TypeConverter.castValues(targetType, sourceVal); + } + + // if the source is a numeric value and the target type is a union, try to find a matching + // member. + if (sourceType.getTag() <= TypeTags.BOOLEAN_TAG && targetType.getTag() == TypeTags.UNION_TAG) { + for (Type memberType : ((BUnionType) targetType).getMemberTypes()) { + try { + return TypeConverter.castValues(memberType, sourceVal); + } catch (Exception e) { + //ignore and continue } - } else { - return TypeConverter.castValues(targetType, sourceVal); } } - throw createTypeCastError(sourceVal, targetType, errors); - } - public static Context context() { - // We are pinning each context to thread. We can't use the same context with multiple type checks concurrently - return threadContext.get(); + throw createTypeCastError(sourceVal, targetType, errors); } public static long anyToInt(Object sourceVal) { @@ -257,13 +281,7 @@ public static boolean anyToJBoolean(Object sourceVal) { * @return true if the value belongs to the given type, false otherwise */ public static boolean checkIsType(Object sourceVal, Type targetType) { - Type sourceType = getType(sourceVal); - if (isSubType(sourceType, targetType)) { - return true; - } - SemType sourceSemType = SemType.tryInto(sourceType); - return couldInherentTypeBeDifferent(sourceSemType) && - isSubTypeWithInherentType(cx, sourceVal, SemType.tryInto(targetType)); + return checkIsType(null, sourceVal, getType(sourceVal), targetType); } /** @@ -276,15 +294,22 @@ public static boolean checkIsType(Object sourceVal, Type targetType) { * @return true if the value belongs to the given type, false otherwise */ public static boolean checkIsType(List errors, Object sourceVal, Type sourceType, Type targetType) { - return checkIsType(sourceVal, targetType); - } + if (checkIsType(sourceVal, sourceType, targetType, null)) { + return true; + } - // This is just an optimization since shapes are not cached, when in doubt return false - private static boolean couldInherentTypeBeDifferent(SemType type) { - if (type instanceof TypeWithShape typeWithShape) { - return typeWithShape.couldInherentTypeBeDifferent(); + if (getImpliedType(sourceType).getTag() == TypeTags.XML_TAG && !targetType.isReadOnly()) { + XmlValue val = (XmlValue) sourceVal; + if (val.getNodeType() == XmlNodeType.SEQUENCE) { + return checkIsLikeOnValue(errors, sourceVal, sourceType, targetType, new ArrayList<>(), false, null); + } } - return true; + + if (isMutable(sourceVal, sourceType)) { + return false; + } + + return checkIsLikeOnValue(errors, sourceVal, sourceType, targetType, new ArrayList<>(), false, null); } /** @@ -307,27 +332,8 @@ public static boolean checkIsLikeType(Object sourceValue, Type targetType) { * @return true if the value has the same shape as the given type; false otherwise */ public static boolean checkIsLikeType(Object sourceValue, Type targetType, boolean allowNumericConversion) { - Context cx = context(); - SemType shape = ShapeAnalyzer.shapeOf(cx, sourceValue).orElseThrow(); - SemType targetSemType = ShapeAnalyzer.acceptedTypeOf(cx, targetType).orElseThrow(); - if (Core.isSubType(cx, shape, NumericTypeHolder.NUMERIC_TYPE) && allowNumericConversion) { - targetSemType = appendNumericConversionTypes(targetSemType); - } - return Core.isSubType(cx, shape, targetSemType); - } - - private static SemType appendNumericConversionTypes(SemType semType) { - SemType result = semType; - // We can represent any int value as a float or a decimal. This is to avoid the overhead of creating - // enumerable semtypes for them - if (Core.containsBasicType(semType, Builder.getIntType())) { - result = Core.union(Core.union(Builder.getDecimalType(), Builder.getFloatType()), result); - } - result = Core.union(result, Core.floatToInt(semType)); - result = Core.union(result, Core.floatToDecimal(semType)); - result = Core.union(result, Core.decimalToInt(semType)); - result = Core.union(result, Core.decimalToFloat(semType)); - return result; + return checkIsLikeType(null, sourceValue, targetType, new ArrayList<>(), allowNumericConversion, + null); } /** @@ -338,34 +344,29 @@ private static SemType appendNumericConversionTypes(SemType semType) { * @return true if the two types are same; false otherwise */ public static boolean isSameType(Type sourceType, Type targetType) { - return Core.isSameType(context(), SemType.tryInto(sourceType), SemType.tryInto(targetType)); + return sourceType == targetType || sourceType.equals(targetType); } public static Type getType(Object value) { - if (value instanceof BValue bValue) { - if (!(value instanceof BObject bObject)) { - return bValue.getType(); - } - return bObject.getOriginalType(); - } if (value == null) { return TYPE_NULL; - } else if (value instanceof Number number) { - return getNumberType(number); - } else if (value instanceof Boolean booleanValue) { - return BBooleanType.singletonType(booleanValue); + } else if (value instanceof Number) { + if (value instanceof Long) { + return TYPE_INT; + } else if (value instanceof Double) { + return TYPE_FLOAT; + } else if (value instanceof Integer || value instanceof Byte) { + return TYPE_BYTE; + } + } else if (value instanceof BString) { + return TYPE_STRING; + } else if (value instanceof Boolean) { + return TYPE_BOOLEAN; + } else if (value instanceof BObject bObject) { + return bObject.getOriginalType(); } - throw new IllegalArgumentException("unexpected value type"); - } - private static Type getNumberType(Number number) { - if (number instanceof Double) { - return TYPE_FLOAT; - } - if (number instanceof Integer || number instanceof Byte) { - return TYPE_BYTE; - } - return TYPE_INT; + return ((BValue) value).getType(); } /** @@ -379,6 +380,18 @@ public static boolean isEqual(Object lhsValue, Object rhsValue) { return isEqual(lhsValue, rhsValue, new HashSet<>()); } + /** + * Check if two decimal values are equal in value. + * + * @param lhsValue The value on the left hand side + * @param rhsValue The value of the right hand side + * @return True if values are equal, else false. + */ + public static boolean checkDecimalEqual(DecimalValue lhsValue, DecimalValue rhsValue) { + return isDecimalRealNumber(lhsValue) && isDecimalRealNumber(rhsValue) && + lhsValue.decimalValue().compareTo(rhsValue.decimalValue()) == 0; + } + /** * Check if two decimal values are exactly equal. * @@ -398,7 +411,7 @@ public static boolean checkDecimalExactEqual(DecimalValue lhsValue, DecimalValue * @param decimalValue The decimal value being checked * @return True if the decimal value is a real number. */ - static boolean isDecimalRealNumber(DecimalValue decimalValue) { + private static boolean isDecimalRealNumber(DecimalValue decimalValue) { return decimalValue.valueKind == DecimalValueKind.ZERO || decimalValue.valueKind == DecimalValueKind.OTHER; } @@ -421,36 +434,54 @@ public static boolean isReferenceEqual(Object lhsValue, Object rhsValue) { return false; } - Context cx = context(); - SemType lhsType = widenedType(cx, lhsValue); - SemType rhsType = widenedType(cx, rhsValue); - if (isSimpleBasicSemType(lhsType)) { - return isSimpleBasicValuesEqual(lhsValue, rhsValue); - } - Predicate basicTypePredicate = - (basicType) -> Core.isSubType(cx, lhsType, basicType) && Core.isSubType(cx, rhsType, basicType); - if (basicTypePredicate.test(Builder.getStringType())) { - return isEqual(lhsValue, rhsValue); - } - if (basicTypePredicate.test(Builder.getXmlType())) { - return isXMLValueRefEqual((XmlValue) lhsValue, (XmlValue) rhsValue); - } - if (basicTypePredicate.test(Builder.getHandleType())) { - return isHandleValueRefEqual(lhsValue, rhsValue); - } - if (basicTypePredicate.test(Builder.getFunctionType())) { - return isFunctionPointerEqual(getImpliedType(getType(lhsValue)), getImpliedType(getType(rhsValue))); - } - if (basicTypePredicate.test(Builder.getRegexType())) { - RegExpValue lhsReg = (RegExpValue) lhsValue; - RegExpValue rhsReg = (RegExpValue) rhsValue; - return lhsReg.equals(rhsReg, new HashSet<>()); - } - // Other types have storage identity so == test should have passed - return false; + Type lhsType = getImpliedType(getType(lhsValue)); + Type rhsType = getImpliedType(getType(rhsValue)); + + return switch (lhsType.getTag()) { + case TypeTags.FLOAT_TAG -> { + if (rhsType.getTag() != TypeTags.FLOAT_TAG) { + yield false; + } + yield lhsValue.equals(((Number) rhsValue).doubleValue()); + } + case TypeTags.DECIMAL_TAG -> { + if (rhsType.getTag() != TypeTags.DECIMAL_TAG) { + yield false; + } + yield checkDecimalExactEqual((DecimalValue) lhsValue, (DecimalValue) rhsValue); + } + case TypeTags.INT_TAG, + TypeTags.BYTE_TAG, + TypeTags.BOOLEAN_TAG, + TypeTags.STRING_TAG -> isEqual(lhsValue, rhsValue); + case TypeTags.XML_TAG, + TypeTags.XML_COMMENT_TAG, + TypeTags.XML_ELEMENT_TAG, + TypeTags.XML_PI_TAG, + TypeTags.XML_TEXT_TAG -> { + if (!TypeTags.isXMLTypeTag(rhsType.getTag())) { + yield false; + } + yield isXMLValueRefEqual((XmlValue) lhsValue, (XmlValue) rhsValue); + } + case TypeTags.HANDLE_TAG -> { + if (rhsType.getTag() != TypeTags.HANDLE_TAG) { + yield false; + } + yield isHandleValueRefEqual(lhsValue, rhsValue); + } + case TypeTags.FUNCTION_POINTER_TAG -> lhsType.getPackage().equals(rhsType.getPackage()) && + lhsType.getName().equals(rhsType.getName()) && rhsType.equals(lhsType); + default -> { + if (lhsValue instanceof RegExpValue lhsRegExpValue && rhsValue instanceof RegExpValue) { + yield lhsRegExpValue.equals(rhsValue, new HashSet<>()); + } + yield false; + } + }; } - static boolean isXMLValueRefEqual(XmlValue lhsValue, XmlValue rhsValue) { + private static boolean isXMLValueRefEqual(XmlValue lhsValue, XmlValue rhsValue) { boolean isLhsXmlSequence = lhsValue.getNodeType() == XmlNodeType.SEQUENCE; boolean isRhsXmlSequence = rhsValue.getNodeType() == XmlNodeType.SEQUENCE; @@ -488,38 +519,6 @@ private static boolean isXMLSequenceRefEqual(XmlSequence lhsValue, XmlSequence r return lhsIter.hasNext() == rhsIter.hasNext(); } - private static boolean isFunctionPointerEqual(Type lhsType, Type rhsType) { - return lhsType.getPackage().equals(rhsType.getPackage()) && - lhsType.getName().equals(rhsType.getName()) && rhsType.equals(lhsType); - } - - private static boolean isSimpleBasicValuesEqual(Object v1, Object v2) { - Context cx = context(); - SemType v1Ty = widenedType(cx, v1); - if (!isSimpleBasicSemType(v1Ty)) { - return false; - } - - SemType v2Ty = widenedType(cx, v2); - if (!isSimpleBasicSemType(v2Ty)) { - return false; - } - - if (!Core.isSameType(cx, v1Ty, v2Ty)) { - return false; - } - - if (Core.isSubType(cx, v1Ty, Builder.getDecimalType())) { - return checkDecimalExactEqual((DecimalValue) v1, (DecimalValue) v2); - } - if (Core.isSubType(cx, v1Ty, Builder.getIntType())) { - Number n1 = (Number) v1; - Number n2 = (Number) v2; - return n1.longValue() == n2.longValue(); - } - return v1.equals(v2); - } - /** * Get the typedesc of a value. * @@ -531,7 +530,7 @@ public static TypedescValue getTypedesc(Object value) { if (type == null) { return null; } - if (belongToSingleBasicTypeOrString(type)) { + if (isSimpleBasicType(type)) { return new TypedescValueImpl(new BFiniteType(value.toString(), Set.of(value), 0)); } if (value instanceof BRefValue bRefValue) { @@ -563,149 +562,1418 @@ public static Object getAnnotValue(TypedescValue typedescValue, BString annotTag * @return flag indicating the equivalence of the two types */ public static boolean checkIsType(Type sourceType, Type targetType) { - return isSubType(sourceType, targetType); + return checkIsType(sourceType, targetType, null); } @Deprecated public static boolean checkIsType(Type sourceType, Type targetType, List unresolvedTypes) { - return isSubType(sourceType, targetType); + // First check whether both types are the same. + if (sourceType == targetType || (sourceType.getTag() == targetType.getTag() && sourceType.equals(targetType))) { + return true; + } + + if (checkIsNeverTypeOrStructureTypeWithARequiredNeverMember(sourceType)) { + return true; + } + + if (targetType.isReadOnly() && !sourceType.isReadOnly()) { + return false; + } + + int sourceTypeTag = sourceType.getTag(); + int targetTypeTag = targetType.getTag(); + + switch (sourceTypeTag) { + case TypeTags.INTERSECTION_TAG: + return checkIsType(((BIntersectionType) sourceType).getEffectiveType(), + targetTypeTag != TypeTags.INTERSECTION_TAG ? targetType : + ((BIntersectionType) targetType).getEffectiveType(), unresolvedTypes); + case TypeTags.TYPE_REFERENCED_TYPE_TAG: + return checkIsType(((BTypeReferenceType) sourceType).getReferredType(), + targetTypeTag != TypeTags.TYPE_REFERENCED_TYPE_TAG ? targetType : + ((BTypeReferenceType) targetType).getReferredType(), unresolvedTypes); + case TypeTags.PARAMETERIZED_TYPE_TAG: + if (targetTypeTag != TypeTags.PARAMETERIZED_TYPE_TAG) { + return checkIsType(((BParameterizedType) sourceType).getParamValueType(), targetType, + unresolvedTypes); + } + return checkIsType(((BParameterizedType) sourceType).getParamValueType(), + ((BParameterizedType) targetType).getParamValueType(), unresolvedTypes); + case TypeTags.READONLY_TAG: + return checkIsType(PredefinedTypes.ANY_AND_READONLY_OR_ERROR_TYPE, + targetType, unresolvedTypes); + case TypeTags.UNION_TAG: + return isUnionTypeMatch((BUnionType) sourceType, targetType, unresolvedTypes); + case TypeTags.FINITE_TYPE_TAG: + if ((targetTypeTag == TypeTags.FINITE_TYPE_TAG || targetTypeTag <= TypeTags.NULL_TAG || + targetTypeTag == TypeTags.XML_TEXT_TAG)) { + return isFiniteTypeMatch((BFiniteType) sourceType, targetType); + } + break; + default: + break; + } + + return switch (targetTypeTag) { + case TypeTags.BYTE_TAG, + TypeTags.SIGNED8_INT_TAG, + TypeTags.FLOAT_TAG, + TypeTags.DECIMAL_TAG, + TypeTags.CHAR_STRING_TAG, + TypeTags.BOOLEAN_TAG, + TypeTags.NULL_TAG -> sourceTypeTag == targetTypeTag; + case TypeTags.STRING_TAG -> TypeTags.isStringTypeTag(sourceTypeTag); + case TypeTags.XML_TEXT_TAG -> { + if (sourceTypeTag == TypeTags.XML_TAG) { + yield ((BXmlType) sourceType).constraint.getTag() == TypeTags.NEVER_TAG; + } + yield sourceTypeTag == targetTypeTag; + } + case TypeTags.INT_TAG -> sourceTypeTag == TypeTags.INT_TAG || sourceTypeTag == TypeTags.BYTE_TAG || + (sourceTypeTag >= TypeTags.SIGNED8_INT_TAG && sourceTypeTag <= TypeTags.UNSIGNED32_INT_TAG); + case TypeTags.SIGNED16_INT_TAG -> sourceTypeTag == TypeTags.BYTE_TAG || + (sourceTypeTag >= TypeTags.SIGNED8_INT_TAG && sourceTypeTag <= TypeTags.SIGNED16_INT_TAG); + case TypeTags.SIGNED32_INT_TAG -> sourceTypeTag == TypeTags.BYTE_TAG || + (sourceTypeTag >= TypeTags.SIGNED8_INT_TAG && sourceTypeTag <= TypeTags.SIGNED32_INT_TAG); + case TypeTags.UNSIGNED8_INT_TAG -> + sourceTypeTag == TypeTags.BYTE_TAG || sourceTypeTag == TypeTags.UNSIGNED8_INT_TAG; + case TypeTags.UNSIGNED16_INT_TAG -> + sourceTypeTag == TypeTags.BYTE_TAG || sourceTypeTag == TypeTags.UNSIGNED8_INT_TAG || + sourceTypeTag == TypeTags.UNSIGNED16_INT_TAG; + case TypeTags.UNSIGNED32_INT_TAG -> + sourceTypeTag == TypeTags.BYTE_TAG || sourceTypeTag == TypeTags.UNSIGNED8_INT_TAG || + sourceTypeTag == TypeTags.UNSIGNED16_INT_TAG || + sourceTypeTag == TypeTags.UNSIGNED32_INT_TAG; + case TypeTags.ANY_TAG -> checkIsAnyType(sourceType); + case TypeTags.ANYDATA_TAG -> sourceType.isAnydata(); + case TypeTags.SERVICE_TAG -> checkIsServiceType(sourceType, targetType, + unresolvedTypes == null ? new ArrayList<>() : unresolvedTypes); + case TypeTags.HANDLE_TAG -> sourceTypeTag == TypeTags.HANDLE_TAG; + case TypeTags.READONLY_TAG -> + checkIsType(sourceType, PredefinedTypes.ANY_AND_READONLY_OR_ERROR_TYPE, unresolvedTypes); + case TypeTags.XML_ELEMENT_TAG, + TypeTags.XML_COMMENT_TAG, + TypeTags.XML_PI_TAG -> targetTypeTag == sourceTypeTag; + case TypeTags.INTERSECTION_TAG -> + checkIsType(sourceType, ((BIntersectionType) targetType).getEffectiveType(), unresolvedTypes); + case TypeTags.TYPE_REFERENCED_TYPE_TAG -> + checkIsType(sourceType, ((BTypeReferenceType) targetType).getReferredType(), unresolvedTypes); + default -> checkIsRecursiveType(sourceType, targetType, + unresolvedTypes == null ? new ArrayList<>() : unresolvedTypes); + }; } - /** - * Check if two decimal values are equal in value. - * - * @param lhsValue The value on the left hand side - * @param rhsValue The value of the right hand side - * @return True if values are equal, else false. - */ - public static boolean checkDecimalEqual(DecimalValue lhsValue, DecimalValue rhsValue) { - return isDecimalRealNumber(lhsValue) && isDecimalRealNumber(rhsValue) && - lhsValue.decimalValue().compareTo(rhsValue.decimalValue()) == 0; + private static boolean checkIsType(Object sourceVal, Type sourceType, Type targetType, + List unresolvedTypes) { + sourceType = getImpliedType(sourceType); + targetType = getImpliedType(targetType); + + int sourceTypeTag = sourceType.getTag(); + int targetTypeTag = targetType.getTag(); + + // If the source type is neither a record type nor an object type, check `is` type by looking only at the types. + // Else, since records and objects may have `readonly` or `final` fields, need to use the value also. + // e.g., + // const HUNDRED = 100; + // + // type Foo record { + // HUNDRED i; + // }; + // + // type Bar record { + // readonly string|int i; + // }; + // + // where `Bar b = {i: 100};`, `b is Foo` should evaluate to true. + if (sourceTypeTag != TypeTags.RECORD_TYPE_TAG && sourceTypeTag != TypeTags.OBJECT_TYPE_TAG) { + return checkIsType(sourceType, targetType); + } + + if (sourceType == targetType || (sourceType.getTag() == targetType.getTag() && sourceType.equals(targetType))) { + return true; + } + + if (targetType.isReadOnly() && !sourceType.isReadOnly()) { + return false; + } + + return switch (targetTypeTag) { + case TypeTags.ANY_TAG -> checkIsAnyType(sourceType); + case TypeTags.READONLY_TAG -> isInherentlyImmutableType(sourceType) || sourceType.isReadOnly(); + default -> checkIsRecursiveTypeOnValue(sourceVal, sourceType, targetType, sourceTypeTag, targetTypeTag, + unresolvedTypes == null ? new ArrayList<>() : unresolvedTypes); + }; } - public static boolean isNumericType(Type type) { - return Core.isSubType(context(), SemType.tryInto(type), NumericTypeHolder.NUMERIC_TYPE); + // Private methods + + private static boolean checkTypeDescType(Type sourceType, BTypedescType targetType, + List unresolvedTypes) { + if (sourceType.getTag() != TypeTags.TYPEDESC_TAG) { + return false; + } + + BTypedescType sourceTypedesc = (BTypedescType) sourceType; + return checkIsType(sourceTypedesc.getConstraint(), targetType.getConstraint(), unresolvedTypes); + } + + private static boolean checkIsRecursiveType(Type sourceType, Type targetType, List unresolvedTypes) { + return switch (targetType.getTag()) { + case TypeTags.MAP_TAG -> checkIsMapType(sourceType, (BMapType) targetType, unresolvedTypes); + case TypeTags.STREAM_TAG -> checkIsStreamType(sourceType, (BStreamType) targetType, unresolvedTypes); + case TypeTags.TABLE_TAG -> checkIsTableType(sourceType, (BTableType) targetType, unresolvedTypes); + case TypeTags.JSON_TAG -> checkIsJSONType(sourceType, unresolvedTypes); + case TypeTags.RECORD_TYPE_TAG -> checkIsRecordType(sourceType, (BRecordType) targetType, unresolvedTypes); + case TypeTags.FUNCTION_POINTER_TAG -> checkIsFunctionType(sourceType, (BFunctionType) targetType); + case TypeTags.ARRAY_TAG -> checkIsArrayType(sourceType, (BArrayType) targetType, unresolvedTypes); + case TypeTags.TUPLE_TAG -> checkIsTupleType(sourceType, (BTupleType) targetType, unresolvedTypes); + case TypeTags.UNION_TAG -> checkIsUnionType(sourceType, (BUnionType) targetType, unresolvedTypes); + case TypeTags.OBJECT_TYPE_TAG -> + checkObjectEquivalency(sourceType, (BObjectType) targetType, unresolvedTypes); + case TypeTags.FINITE_TYPE_TAG -> checkIsFiniteType(sourceType, (BFiniteType) targetType); + case TypeTags.FUTURE_TAG -> checkIsFutureType(sourceType, (BFutureType) targetType, unresolvedTypes); + case TypeTags.ERROR_TAG -> checkIsErrorType(sourceType, (BErrorType) targetType, unresolvedTypes); + case TypeTags.TYPEDESC_TAG -> checkTypeDescType(sourceType, (BTypedescType) targetType, unresolvedTypes); + case TypeTags.XML_TAG -> checkIsXMLType(sourceType, targetType, unresolvedTypes); + // other non-recursive types shouldn't reach here + default -> false; + }; } - public static boolean isByteLiteral(long longValue) { - return (longValue >= BBYTE_MIN_VALUE && longValue <= BBYTE_MAX_VALUE); + private static boolean checkIsRecursiveTypeOnValue(Object sourceVal, Type sourceType, Type targetType, + int sourceTypeTag, int targetTypeTag, + List unresolvedTypes) { + return switch (targetTypeTag) { + case TypeTags.ANYDATA_TAG -> { + if (sourceTypeTag == TypeTags.OBJECT_TYPE_TAG) { + yield false; + } + yield checkRecordBelongsToAnydataType((MapValue) sourceVal, (BRecordType) sourceType, unresolvedTypes); + } + case TypeTags.MAP_TAG -> checkIsMapType(sourceVal, sourceType, (BMapType) targetType, unresolvedTypes); + case TypeTags.JSON_TAG -> checkIsMapType(sourceVal, sourceType, + new BMapType(targetType.isReadOnly() ? TYPE_READONLY_JSON : + TYPE_JSON), unresolvedTypes); + case TypeTags.RECORD_TYPE_TAG -> + checkIsRecordType(sourceVal, sourceType, (BRecordType) targetType, unresolvedTypes); + case TypeTags.UNION_TAG -> { + for (Type type : ((BUnionType) targetType).getMemberTypes()) { + if (checkIsType(sourceVal, sourceType, type, unresolvedTypes)) { + yield true; + } + } + yield false; + } + case TypeTags.OBJECT_TYPE_TAG -> + checkObjectEquivalency(sourceVal, sourceType, (BObjectType) targetType, unresolvedTypes); + default -> false; + }; } - // Private methods + private static boolean isFiniteTypeMatch(BFiniteType sourceType, Type targetType) { + for (Object bValue : sourceType.valueSpace) { + if (!checkIsType(bValue, targetType)) { + return false; + } + } + return true; + } + + private static boolean isUnionTypeMatch(BUnionType sourceType, Type targetType, List unresolvedTypes) { + for (Type type : sourceType.getMemberTypes()) { + if (!checkIsType(type, targetType, unresolvedTypes)) { + return false; + } + } + return true; + } - private static boolean isSubTypeWithInherentType(Context cx, Object sourceValue, SemType target) { - return ShapeAnalyzer.inherentTypeOf(cx, sourceValue) - .map(source -> !Core.isEmpty(cx, source) && Core.isSubType(cx, source, target)) - // OR else do the normal type check by taking the shape of - .orElse(false); + private static boolean checkIsUnionType(Type sourceType, BUnionType targetType, List unresolvedTypes) { + // If we encounter two types that we are still resolving, then skip it. + // This is done to avoid recursive checking of the same type. + sourceType = getImpliedType(sourceType); + TypePair pair = new TypePair(sourceType, targetType); + if (unresolvedTypes.contains(pair)) { + return true; + } + unresolvedTypes.add(pair); + + return switch (sourceType.getTag()) { + case TypeTags.UNION_TAG, + TypeTags.JSON_TAG, + TypeTags.ANYDATA_TAG -> isUnionTypeMatch((BUnionType) sourceType, targetType, unresolvedTypes); + case TypeTags.FINITE_TYPE_TAG -> isFiniteTypeMatch((BFiniteType) sourceType, targetType); + default -> { + for (Type type : targetType.getMemberTypes()) { + if (checkIsType(sourceType, type, unresolvedTypes)) { + yield true; + } + } + yield false; + } + }; } - private static boolean isSubType(Type source, Type target) { - if (source instanceof CacheableTypeDescriptor sourceCacheableType && - target instanceof CacheableTypeDescriptor targetCacheableType) { - return isSubTypeWithCache(sourceCacheableType, targetCacheableType); + private static boolean checkIsMapType(Type sourceType, BMapType targetType, List unresolvedTypes) { + Type targetConstrainedType = targetType.getConstrainedType(); + sourceType = getImpliedType(sourceType); + switch (sourceType.getTag()) { + case TypeTags.MAP_TAG: + return checkConstraints(((BMapType) sourceType).getConstrainedType(), targetConstrainedType, + unresolvedTypes); + case TypeTags.RECORD_TYPE_TAG: + BRecordType recType = (BRecordType) sourceType; + BUnionType wideTypeUnion = new BUnionType(getWideTypeComponents(recType)); + return checkConstraints(wideTypeUnion, targetConstrainedType, unresolvedTypes); + default: + return false; } - // This is really a workaround for Standard libraries that create record types that are not the "same". But - // with the same name and expect them to be same. - return isSubTypeInner(context(), source, target); } - private static boolean isSubTypeInner(Context cx, Type source, Type target) { - SemType sourceSemType = SemType.tryInto(source); - SemType targetSemType = SemType.tryInto(target); - return Core.isSubType(cx, sourceSemType, targetSemType); + private static boolean checkIsMapType(Object sourceVal, Type sourceType, BMapType targetType, + List unresolvedTypes) { + Type targetConstrainedType = targetType.getConstrainedType(); + sourceType = getImpliedType(sourceType); + return switch (sourceType.getTag()) { + case TypeTags.MAP_TAG -> checkConstraints(((BMapType) sourceType).getConstrainedType(), + targetConstrainedType, unresolvedTypes); + case TypeTags.RECORD_TYPE_TAG -> checkIsMapType((MapValue) sourceVal, (BRecordType) sourceType, + unresolvedTypes, targetConstrainedType); + default -> false; + }; } - private static boolean isSubTypeWithCache(CacheableTypeDescriptor source, CacheableTypeDescriptor target) { - Context cx = context(); - if (!source.shouldCache() || !target.shouldCache()) { - return isSubTypeInner(cx, source, target); + private static boolean checkIsMapType(MapValue sourceVal, BRecordType sourceType, List unresolvedTypes, + Type targetConstrainedType) { + for (Field field : sourceType.getFields().values()) { + if (!SymbolFlags.isFlagOn(field.getFlags(), SymbolFlags.READONLY)) { + if (!checkIsType(field.getFieldType(), targetConstrainedType, unresolvedTypes)) { + return false; + } + continue; + } + + BString name = StringUtils.fromString(field.getFieldName()); + + if (SymbolFlags.isFlagOn(field.getFlags(), SymbolFlags.OPTIONAL) && !sourceVal.containsKey(name)) { + continue; + } + + if (!checkIsLikeType(sourceVal.get(name), targetConstrainedType)) { + return false; + } } - Optional cachedResult = source.cachedTypeCheckResult(cx, target); - if (cachedResult.isPresent()) { - assert cachedResult.get() == isSubTypeInner(cx, source, target); - return cachedResult.get(); + + if (sourceType.sealed) { + return true; } - boolean result = isSubTypeInner(cx, source, target); - source.cacheTypeCheckResult(target, result); - return result; + + return checkIsType(sourceType.restFieldType, targetConstrainedType, unresolvedTypes); } - private static SemType widenedType(Context cx, Object value) { - if (value instanceof BValue bValue) { - return bValue.widenedType(); + private static boolean checkIsXMLType(Type sourceType, Type targetType, List unresolvedTypes) { + sourceType = getImpliedType(sourceType); + int sourceTag = sourceType.getTag(); + if (sourceTag == TypeTags.FINITE_TYPE_TAG) { + return isFiniteTypeMatch((BFiniteType) sourceType, targetType); } - if (value == null) { - return Builder.getNilType(); - } else if (value instanceof Double) { - return Builder.getFloatType(); - } else if (value instanceof Number) { - return Builder.getIntType(); - } else if (value instanceof BString) { - return Builder.getStringType(); - } else if (value instanceof Boolean) { - return Builder.getBooleanType(); + + BXmlType target = ((BXmlType) targetType); + if (sourceTag == TypeTags.XML_TAG) { + Type targetConstraint = getRecursiveTargetConstraintType(target); + BXmlType source = (BXmlType) sourceType; + if (source.constraint.getTag() == TypeTags.NEVER_TAG) { + if (targetConstraint.getTag() == TypeTags.UNION_TAG) { + return checkIsUnionType(sourceType, (BUnionType) targetConstraint, unresolvedTypes); + } + return targetConstraint.getTag() == TypeTags.XML_TEXT_TAG || + targetConstraint.getTag() == TypeTags.NEVER_TAG; + } + return checkIsType(source.constraint, targetConstraint, unresolvedTypes); + } + if (TypeTags.isXMLTypeTag(sourceTag)) { + return checkIsType(sourceType, target.constraint, unresolvedTypes); } - throw new IllegalArgumentException("Unexpected object type"); + return false; } - public static boolean isInherentlyImmutableType(Type sourceType) { - // readonly part is there to match to old API - return - Core.isSubType(context(), SemType.tryInto(sourceType), - InherentlyImmutableTypeHolder.INHERENTLY_IMMUTABLE_TYPE) || - sourceType instanceof ReadonlyType; + private static Type getRecursiveTargetConstraintType(BXmlType target) { + Type targetConstraint = getImpliedType(target.constraint); + // TODO: Revisit and check why xml>> on chained iteration + while (targetConstraint.getTag() == TypeTags.XML_TAG) { + target = (BXmlType) targetConstraint; + targetConstraint = getImpliedType(target.constraint); + } + return targetConstraint; } - // NOTE: this is not the same as selectively immutable as it stated in the spec - public static boolean isSelectivelyImmutableType(Type type, Set unresolvedTypes) { - if (!unresolvedTypes.add(type)) { + private static List getWideTypeComponents(BRecordType recType) { + List types = new ArrayList<>(); + for (Field f : recType.getFields().values()) { + types.add(f.getFieldType()); + } + if (!recType.sealed) { + types.add(recType.restFieldType); + } + return types; + } + + private static boolean checkIsStreamType(Type sourceType, BStreamType targetType, List unresolvedTypes) { + sourceType = getImpliedType(sourceType); + if (sourceType.getTag() != TypeTags.STREAM_TAG) { + return false; + } + return checkConstraints(((BStreamType) sourceType).getConstrainedType(), targetType.getConstrainedType(), + unresolvedTypes) + && checkConstraints(((BStreamType) sourceType).getCompletionType(), targetType.getCompletionType(), + unresolvedTypes); + } + + private static boolean checkIsTableType(Type sourceType, BTableType targetType, List unresolvedTypes) { + sourceType = getImpliedType(sourceType); + if (sourceType.getTag() != TypeTags.TABLE_TAG) { + return false; + } + + BTableType srcTableType = (BTableType) sourceType; + + if (!checkConstraints(srcTableType.getConstrainedType(), targetType.getConstrainedType(), + unresolvedTypes)) { + return false; + } + + if (targetType.getKeyType() == null && targetType.getFieldNames().length == 0) { return true; } - switch (type.getTag()) { - case TypeTags.ANY_TAG: - case TypeTags.ANYDATA_TAG: - case TypeTags.JSON_TAG: - case TypeTags.XML_TAG: - case TypeTags.XML_COMMENT_TAG: - case TypeTags.XML_ELEMENT_TAG: - case TypeTags.XML_PI_TAG: - case TypeTags.READONLY_TAG: + if (targetType.getKeyType() != null) { + if (srcTableType.getKeyType() != null && + (checkConstraints(srcTableType.getKeyType(), targetType.getKeyType(), unresolvedTypes))) { return true; - case TypeTags.ARRAY_TAG: - Type elementType = ((BArrayType) type).getElementType(); - return isInherentlyImmutableType(elementType) || - isSelectivelyImmutableType(elementType, unresolvedTypes); - case TypeTags.TUPLE_TAG: - BTupleType tupleType = (BTupleType) type; - for (Type tupMemType : tupleType.getTupleTypes()) { - if (!isInherentlyImmutableType(tupMemType) && - !isSelectivelyImmutableType(tupMemType, unresolvedTypes)) { - return false; - } - } + } - Type tupRestType = tupleType.getRestType(); - if (tupRestType == null) { - return true; - } + if (srcTableType.getFieldNames().length == 0) { + return false; + } - return isInherentlyImmutableType(tupRestType) || - isSelectivelyImmutableType(tupRestType, unresolvedTypes); + List fieldTypes = new ArrayList<>(); + Arrays.stream(srcTableType.getFieldNames()).forEach(field -> fieldTypes + .add(Objects.requireNonNull(getTableConstraintField(srcTableType.getConstrainedType(), field)) + .getFieldType())); + + if (fieldTypes.size() == 1) { + return checkConstraints(fieldTypes.get(0), targetType.getKeyType(), unresolvedTypes); + } + + BTupleType tupleType = new BTupleType(fieldTypes); + return checkConstraints(tupleType, targetType.getKeyType(), unresolvedTypes); + } + + return Arrays.equals(srcTableType.getFieldNames(), targetType.getFieldNames()); + } + + static BField getTableConstraintField(Type constraintType, String fieldName) { + switch (constraintType.getTag()) { case TypeTags.RECORD_TYPE_TAG: - BRecordType recordType = (BRecordType) type; - for (Field field : recordType.getFields().values()) { - Type fieldType = field.getFieldType(); - if (!isInherentlyImmutableType(fieldType) && - !isSelectivelyImmutableType(fieldType, unresolvedTypes)) { - return false; - } + Map fieldList = ((BRecordType) constraintType).getFields(); + return (BField) fieldList.get(fieldName); + case TypeTags.INTERSECTION_TAG: + Type effectiveType = ((BIntersectionType) constraintType).getEffectiveType(); + return getTableConstraintField(effectiveType, fieldName); + case TypeTags.TYPE_REFERENCED_TYPE_TAG: + Type referredType = ((BTypeReferenceType) constraintType).getReferredType(); + return getTableConstraintField(referredType, fieldName); + case TypeTags.UNION_TAG: + BUnionType unionType = (BUnionType) constraintType; + List memTypes = unionType.getMemberTypes(); + List fields = memTypes.stream().map(type -> getTableConstraintField(type, fieldName)) + .filter(Objects::nonNull).toList(); + + if (fields.size() != memTypes.size()) { + return null; } - Type recordRestType = recordType.restFieldType; - if (recordRestType == null) { - return true; + if (fields.stream().allMatch(field -> isSameType(field.getFieldType(), fields.get(0).getFieldType()))) { + return fields.get(0); + } + return null; + default: + return null; + } + } + + private static boolean checkIsJSONType(Type sourceType, List unresolvedTypes) { + BJsonType jsonType = (BJsonType) TYPE_JSON; + sourceType = getImpliedType(sourceType); + // If we encounter two types that we are still resolving, then skip it. + // This is done to avoid recursive checking of the same type. + TypePair pair = new TypePair(sourceType, jsonType); + if (unresolvedTypes.contains(pair)) { + return true; + } + unresolvedTypes.add(pair); + + switch (sourceType.getTag()) { + case TypeTags.STRING_TAG: + case TypeTags.CHAR_STRING_TAG: + case TypeTags.INT_TAG: + case TypeTags.SIGNED32_INT_TAG: + case TypeTags.SIGNED16_INT_TAG: + case TypeTags.SIGNED8_INT_TAG: + case TypeTags.UNSIGNED32_INT_TAG: + case TypeTags.UNSIGNED16_INT_TAG: + case TypeTags.UNSIGNED8_INT_TAG: + case TypeTags.BYTE_TAG: + case TypeTags.FLOAT_TAG: + case TypeTags.DECIMAL_TAG: + case TypeTags.BOOLEAN_TAG: + case TypeTags.NULL_TAG: + case TypeTags.JSON_TAG: + return true; + case TypeTags.ARRAY_TAG: + // Element type of the array should be 'is type' JSON + return checkIsType(((BArrayType) sourceType).getElementType(), jsonType, unresolvedTypes); + case TypeTags.FINITE_TYPE_TAG: + return isFiniteTypeMatch((BFiniteType) sourceType, jsonType); + case TypeTags.MAP_TAG: + return checkIsType(((BMapType) sourceType).getConstrainedType(), jsonType, unresolvedTypes); + case TypeTags.RECORD_TYPE_TAG: + BRecordType recordType = (BRecordType) sourceType; + for (Field field : recordType.getFields().values()) { + if (!checkIsJSONType(field.getFieldType(), unresolvedTypes)) { + return false; + } + } + + if (!recordType.sealed) { + return checkIsJSONType(recordType.restFieldType, unresolvedTypes); + } + return true; + case TypeTags.TUPLE_TAG: + BTupleType sourceTupleType = (BTupleType) sourceType; + for (Type memberType : sourceTupleType.getTupleTypes()) { + if (!checkIsJSONType(memberType, unresolvedTypes)) { + return false; + } + } + Type tupleRestType = sourceTupleType.getRestType(); + if (tupleRestType != null) { + return checkIsJSONType(tupleRestType, unresolvedTypes); + } + return true; + case TypeTags.UNION_TAG: + for (Type memberType : ((BUnionType) sourceType).getMemberTypes()) { + if (!checkIsJSONType(memberType, unresolvedTypes)) { + return false; + } + } + return true; + default: + return false; + } + } + + private static boolean checkIsRecordType(Type sourceType, BRecordType targetType, List unresolvedTypes) { + sourceType = getImpliedType(sourceType); + return switch (sourceType.getTag()) { + case TypeTags.RECORD_TYPE_TAG -> checkIsRecordType((BRecordType) sourceType, targetType, unresolvedTypes); + case TypeTags.MAP_TAG -> checkIsRecordType((BMapType) sourceType, targetType, unresolvedTypes); + default -> false; + }; + } + + private static boolean checkIsRecordType(BRecordType sourceRecordType, BRecordType targetType, + List unresolvedTypes) { + // If we encounter two types that we are still resolving, then skip it. + // This is done to avoid recursive checking of the same type. + TypePair pair = new TypePair(sourceRecordType, targetType); + if (unresolvedTypes.contains(pair)) { + return true; + } + unresolvedTypes.add(pair); + + // Unsealed records are not equivalent to sealed records, unless their rest field type is 'never'. But + // vice-versa is allowed. + if (targetType.sealed && !sourceRecordType.sealed && (sourceRecordType.restFieldType == null || + getImpliedType(sourceRecordType.restFieldType).getTag() != TypeTags.NEVER_TAG)) { + return false; + } + + // If both are sealed check the rest field type + if (!sourceRecordType.sealed && !targetType.sealed && + !checkIsType(sourceRecordType.restFieldType, targetType.restFieldType, unresolvedTypes)) { + return false; + } + + Map sourceFields = sourceRecordType.getFields(); + Set targetFieldNames = targetType.getFields().keySet(); + + for (Map.Entry targetFieldEntry : targetType.getFields().entrySet()) { + Field targetField = targetFieldEntry.getValue(); + Field sourceField = sourceFields.get(targetFieldEntry.getKey()); + + if (sourceField == null) { + if (!SymbolFlags.isFlagOn(targetField.getFlags(), SymbolFlags.OPTIONAL)) { + return false; + } + + if (!sourceRecordType.sealed && !checkIsType(sourceRecordType.restFieldType, targetField.getFieldType(), + unresolvedTypes)) { + return false; + } + + continue; + } + + if (hasIncompatibleReadOnlyFlags(targetField, sourceField)) { + return false; + } + + // If the target field is required, the source field should be required as well. + if (!SymbolFlags.isFlagOn(targetField.getFlags(), SymbolFlags.OPTIONAL) + && SymbolFlags.isFlagOn(sourceField.getFlags(), SymbolFlags.OPTIONAL)) { + return false; + } + + if (!checkIsType(sourceField.getFieldType(), targetField.getFieldType(), unresolvedTypes)) { + return false; + } + } + + // If there are fields remaining in the source record, first check if it's a closed record. Closed records + // should only have the fields specified by its type. + if (targetType.sealed) { + return targetFieldNames.containsAll(sourceFields.keySet()); + } + + // If it's an open record, check if they are compatible with the rest field of the target type. + for (Map.Entry sourceFieldEntry : sourceFields.entrySet()) { + if (targetFieldNames.contains(sourceFieldEntry.getKey())) { + continue; + } + + if (!checkIsType(sourceFieldEntry.getValue().getFieldType(), targetType.restFieldType, unresolvedTypes)) { + return false; + } + } + return true; + } + + private static boolean checkIsRecordType(BMapType sourceType, BRecordType targetType, + List unresolvedTypes) { + // If we encounter two types that we are still resolving, then skip it. + // This is done to avoid recursive checking of the same type. + TypePair pair = new TypePair(sourceType, targetType); + if (unresolvedTypes.contains(pair)) { + return true; + } + unresolvedTypes.add(pair); + + if (targetType.sealed) { + return false; + } + + Type constraintType = sourceType.getConstrainedType(); + + for (Field field : targetType.getFields().values()) { + long flags = field.getFlags(); + if (!SymbolFlags.isFlagOn(flags, SymbolFlags.OPTIONAL)) { + return false; + } + + if (SymbolFlags.isFlagOn(flags, SymbolFlags.READONLY) && !sourceType.isReadOnly()) { + return false; + } + + if (!checkIsType(constraintType, field.getFieldType(), unresolvedTypes)) { + return false; + } + } + + return checkIsType(constraintType, targetType.restFieldType, unresolvedTypes); + } + + private static boolean checkRecordBelongsToAnydataType(MapValue sourceVal, BRecordType recordType, + List unresolvedTypes) { + Type targetType = TYPE_ANYDATA; + TypePair pair = new TypePair(recordType, targetType); + if (unresolvedTypes.contains(pair)) { + return true; + } + unresolvedTypes.add(pair); + + Map fields = recordType.getFields(); + + for (Map.Entry fieldEntry : fields.entrySet()) { + String fieldName = fieldEntry.getKey(); + Field field = fieldEntry.getValue(); + + if (SymbolFlags.isFlagOn(field.getFlags(), SymbolFlags.READONLY)) { + BString fieldNameBString = StringUtils.fromString(fieldName); + + if (SymbolFlags + .isFlagOn(field.getFlags(), SymbolFlags.OPTIONAL) && !sourceVal.containsKey(fieldNameBString)) { + continue; + } + + if (!checkIsLikeType(sourceVal.get(fieldNameBString), targetType)) { + return false; + } + } else { + if (!checkIsType(field.getFieldType(), targetType, unresolvedTypes)) { + return false; + } + } + } + + if (recordType.sealed) { + return true; + } + + return checkIsType(recordType.restFieldType, targetType, unresolvedTypes); + } + + private static boolean checkIsRecordType(Object sourceVal, Type sourceType, BRecordType targetType, + List unresolvedTypes) { + sourceType = getImpliedType(sourceType); + return switch (sourceType.getTag()) { + case TypeTags.RECORD_TYPE_TAG -> + checkIsRecordType((MapValue) sourceVal, (BRecordType) sourceType, targetType, unresolvedTypes); + case TypeTags.MAP_TAG -> checkIsRecordType((BMapType) sourceType, targetType, unresolvedTypes); + default -> false; + }; + } + + private static boolean checkIsRecordType(MapValue sourceRecordValue, BRecordType sourceRecordType, + BRecordType targetType, List unresolvedTypes) { + TypePair pair = new TypePair(sourceRecordType, targetType); + if (unresolvedTypes.contains(pair)) { + return true; + } + unresolvedTypes.add(pair); + + // Unsealed records are not equivalent to sealed records, unless their rest field type is 'never'. But + // vice-versa is allowed. + if (targetType.sealed && !sourceRecordType.sealed && (sourceRecordType.restFieldType == null || + getImpliedType(sourceRecordType.restFieldType).getTag() != TypeTags.NEVER_TAG)) { + return false; + } + + // If both are sealed check the rest field type + if (!sourceRecordType.sealed && !targetType.sealed && + !checkIsType(sourceRecordType.restFieldType, targetType.restFieldType, unresolvedTypes)) { + return false; + } + + Map sourceFields = sourceRecordType.getFields(); + Set targetFieldNames = targetType.getFields().keySet(); + + for (Map.Entry targetFieldEntry : targetType.getFields().entrySet()) { + String fieldName = targetFieldEntry.getKey(); + Field targetField = targetFieldEntry.getValue(); + Field sourceField = sourceFields.get(fieldName); + + if (getImpliedType(targetField.getFieldType()).getTag() == TypeTags.NEVER_TAG && + containsInvalidNeverField(sourceField, sourceRecordType)) { + return false; + } + + if (sourceField == null) { + if (!SymbolFlags.isFlagOn(targetField.getFlags(), SymbolFlags.OPTIONAL)) { + return false; + } + + if (!sourceRecordType.sealed && !checkIsType(sourceRecordType.restFieldType, targetField.getFieldType(), + unresolvedTypes)) { + return false; + } + + continue; + } + + if (hasIncompatibleReadOnlyFlags(targetField, sourceField)) { + return false; + } + + boolean optionalTargetField = SymbolFlags.isFlagOn(targetField.getFlags(), SymbolFlags.OPTIONAL); + boolean optionalSourceField = SymbolFlags.isFlagOn(sourceField.getFlags(), SymbolFlags.OPTIONAL); + + if (SymbolFlags.isFlagOn(sourceField.getFlags(), SymbolFlags.READONLY)) { + BString fieldNameBString = StringUtils.fromString(fieldName); + + if (optionalSourceField && !sourceRecordValue.containsKey(fieldNameBString)) { + if (!optionalTargetField) { + return false; + } + continue; + } + + if (!checkIsLikeType(sourceRecordValue.get(fieldNameBString), targetField.getFieldType())) { + return false; + } + } else { + if (!optionalTargetField && optionalSourceField) { + return false; + } + + if (!checkIsType(sourceField.getFieldType(), targetField.getFieldType(), unresolvedTypes)) { + return false; + } + } + } + + if (targetType.sealed) { + for (String sourceFieldName : sourceFields.keySet()) { + if (targetFieldNames.contains(sourceFieldName)) { + continue; + } + + if (!checkIsNeverTypeOrStructureTypeWithARequiredNeverMember( + sourceFields.get(sourceFieldName).getFieldType())) { + return false; + } + } + return true; + } + + for (Map.Entry targetFieldEntry : sourceFields.entrySet()) { + String fieldName = targetFieldEntry.getKey(); + Field field = targetFieldEntry.getValue(); + if (targetFieldNames.contains(fieldName)) { + continue; + } + + if (SymbolFlags.isFlagOn(field.getFlags(), SymbolFlags.READONLY)) { + if (!checkIsLikeType(sourceRecordValue.get(StringUtils.fromString(fieldName)), + targetType.restFieldType)) { + return false; + } + } else if (!checkIsType(field.getFieldType(), targetType.restFieldType, unresolvedTypes)) { + return false; + } + } + return true; + } + + private static boolean containsInvalidNeverField(Field sourceField, BRecordType sourceRecordType) { + if (sourceField != null) { + return !containsNeverType(sourceField.getFieldType()); + } + if (sourceRecordType.isSealed()) { + return true; + } + return !containsNeverType(sourceRecordType.getRestFieldType()); + } + + private static boolean containsNeverType(Type fieldType) { + fieldType = getImpliedType(fieldType); + int fieldTag = fieldType.getTag(); + if (fieldTag == TypeTags.NEVER_TAG) { + return true; + } + if (fieldTag == TypeTags.UNION_TAG) { + List memberTypes = ((BUnionType) fieldType).getOriginalMemberTypes(); + for (Type member : memberTypes) { + if (getImpliedType(member).getTag() == TypeTags.NEVER_TAG) { + return true; + } + } + } + return false; + } + + private static boolean hasIncompatibleReadOnlyFlags(Field targetField, Field sourceField) { + return SymbolFlags.isFlagOn(targetField.getFlags(), SymbolFlags.READONLY) && !SymbolFlags + .isFlagOn(sourceField.getFlags(), + SymbolFlags.READONLY); + } + + private static boolean checkIsArrayType(BArrayType sourceType, BArrayType targetType, + List unresolvedTypes) { + switch (sourceType.getState()) { + case OPEN: + if (targetType.getState() != ArrayState.OPEN) { + return false; + } + break; + case CLOSED: + if (targetType.getState() == ArrayState.CLOSED && + sourceType.getSize() != targetType.getSize()) { + return false; + } + break; + default: + break; + } + return checkIsType(sourceType.getElementType(), targetType.getElementType(), unresolvedTypes); + } + + private static boolean checkIsArrayType(BTupleType sourceType, BArrayType targetType, + List unresolvedTypes) { + List tupleTypes = sourceType.getTupleTypes(); + Type sourceRestType = sourceType.getRestType(); + Type targetElementType = targetType.getElementType(); + + if (targetType.getState() == ArrayState.OPEN) { + for (Type sourceElementType : tupleTypes) { + if (!checkIsType(sourceElementType, targetElementType, unresolvedTypes)) { + return false; + } + } + if (sourceRestType != null) { + return checkIsType(sourceRestType, targetElementType, unresolvedTypes); + } + return true; + } + if (sourceRestType != null) { + return false; + } + if (tupleTypes.size() != targetType.getSize()) { + return false; + } + for (Type sourceElementType : tupleTypes) { + if (!checkIsType(sourceElementType, targetElementType, unresolvedTypes)) { + return false; + } + } + return true; + } + + private static boolean checkIsArrayType(Type sourceType, BArrayType targetType, List unresolvedTypes) { + sourceType = getImpliedType(sourceType); + int sourceTypeTag = sourceType.getTag(); + + if (sourceTypeTag == TypeTags.UNION_TAG) { + for (Type memberType : ((BUnionType) sourceType).getMemberTypes()) { + if (!checkIsArrayType(memberType, targetType, unresolvedTypes)) { + return false; + } + } + return true; + } + + if (sourceTypeTag != TypeTags.ARRAY_TAG && sourceTypeTag != TypeTags.TUPLE_TAG) { + return false; + } + + if (sourceTypeTag == TypeTags.ARRAY_TAG) { + return checkIsArrayType((BArrayType) sourceType, targetType, unresolvedTypes); + } + return checkIsArrayType((BTupleType) sourceType, targetType, unresolvedTypes); + } + + private static boolean checkIsTupleType(BArrayType sourceType, BTupleType targetType, + List unresolvedTypes) { + Type sourceElementType = sourceType.getElementType(); + List targetTypes = targetType.getTupleTypes(); + Type targetRestType = targetType.getRestType(); + + switch (sourceType.getState()) { + case OPEN: + if (targetRestType == null) { + return false; + } + if (targetTypes.isEmpty()) { + return checkIsType(sourceElementType, targetRestType, unresolvedTypes); + } + return false; + case CLOSED: + if (sourceType.getSize() < targetTypes.size()) { + return false; + } + if (targetTypes.isEmpty()) { + if (targetRestType != null) { + return checkIsType(sourceElementType, targetRestType, unresolvedTypes); + } + return sourceType.getSize() == 0; + } + + for (Type targetElementType : targetTypes) { + if (!(checkIsType(sourceElementType, targetElementType, unresolvedTypes))) { + return false; + } + } + if (sourceType.getSize() == targetTypes.size()) { + return true; + } + if (targetRestType != null) { + return checkIsType(sourceElementType, targetRestType, unresolvedTypes); + } + return false; + default: + return false; + } + } + + private static boolean checkIsTupleType(BTupleType sourceType, BTupleType targetType, + List unresolvedTypes) { + List sourceTypes = sourceType.getTupleTypes(); + Type sourceRestType = sourceType.getRestType(); + List targetTypes = targetType.getTupleTypes(); + Type targetRestType = targetType.getRestType(); + + if (sourceRestType != null && targetRestType == null) { + return false; + } + int sourceTypeSize = sourceTypes.size(); + int targetTypeSize = targetTypes.size(); + + if (sourceRestType == null && targetRestType == null && sourceTypeSize != targetTypeSize) { + return false; + } + + if (sourceTypeSize < targetTypeSize) { + return false; + } + + for (int i = 0; i < targetTypeSize; i++) { + if (!checkIsType(sourceTypes.get(i), targetTypes.get(i), unresolvedTypes)) { + return false; + } + } + if (sourceTypeSize == targetTypeSize) { + if (sourceRestType != null) { + return checkIsType(sourceRestType, targetRestType, unresolvedTypes); + } + return true; + } + + for (int i = targetTypeSize; i < sourceTypeSize; i++) { + if (!checkIsType(sourceTypes.get(i), targetRestType, unresolvedTypes)) { + return false; + } + } + if (sourceRestType != null) { + return checkIsType(sourceRestType, targetRestType, unresolvedTypes); + } + return true; + } + + private static boolean checkIsTupleType(Type sourceType, BTupleType targetType, List unresolvedTypes) { + sourceType = getImpliedType(sourceType); + int sourceTypeTag = sourceType.getTag(); + + if (sourceTypeTag == TypeTags.UNION_TAG) { + for (Type memberType : ((BUnionType) sourceType).getMemberTypes()) { + if (!checkIsTupleType(memberType, targetType, unresolvedTypes)) { + return false; + } + } + return true; + } + + if (sourceTypeTag != TypeTags.ARRAY_TAG && sourceTypeTag != TypeTags.TUPLE_TAG) { + return false; + } + + if (sourceTypeTag == TypeTags.ARRAY_TAG) { + return checkIsTupleType((BArrayType) sourceType, targetType, unresolvedTypes); + } + return checkIsTupleType((BTupleType) sourceType, targetType, unresolvedTypes); + } + + private static boolean checkIsAnyType(Type sourceType) { + sourceType = getImpliedType(sourceType); + return switch (sourceType.getTag()) { + case TypeTags.ERROR_TAG, + TypeTags.READONLY_TAG -> false; + case TypeTags.UNION_TAG, + TypeTags.ANYDATA_TAG, + TypeTags.JSON_TAG -> { + for (Type memberType : ((BUnionType) sourceType).getMemberTypes()) { + if (!checkIsAnyType(memberType)) { + yield false; + } + } + yield true; + } + default -> true; + }; + } + + private static boolean checkIsFiniteType(Type sourceType, BFiniteType targetType) { + sourceType = getImpliedType(sourceType); + if (sourceType.getTag() != TypeTags.FINITE_TYPE_TAG) { + return false; + } + + BFiniteType sourceFiniteType = (BFiniteType) sourceType; + if (sourceFiniteType.valueSpace.size() != targetType.valueSpace.size()) { + return false; + } + + return targetType.valueSpace.containsAll(sourceFiniteType.valueSpace); + } + + private static boolean checkIsFutureType(Type sourceType, BFutureType targetType, List unresolvedTypes) { + sourceType = getImpliedType(sourceType); + if (sourceType.getTag() != TypeTags.FUTURE_TAG) { + return false; + } + return checkConstraints(((BFutureType) sourceType).getConstrainedType(), targetType.getConstrainedType(), + unresolvedTypes); + } + + private static boolean checkObjectEquivalency(Type sourceType, BObjectType targetType, + List unresolvedTypes) { + return checkObjectEquivalency(null, sourceType, targetType, unresolvedTypes); + } + + private static boolean checkObjectEquivalency(Object sourceVal, Type sourceType, BObjectType targetType, + List unresolvedTypes) { + sourceType = getImpliedType(sourceType); + if (sourceType.getTag() != TypeTags.OBJECT_TYPE_TAG && sourceType.getTag() != TypeTags.SERVICE_TAG) { + return false; + } + // If we encounter two types that we are still resolving, then skip it. + // This is done to avoid recursive checking of the same type. + TypePair pair = new TypePair(sourceType, targetType); + if (unresolvedTypes.contains(pair)) { + return true; + } + unresolvedTypes.add(pair); + + BObjectType sourceObjectType = (BObjectType) sourceType; + + if (SymbolFlags.isFlagOn(targetType.flags, SymbolFlags.ISOLATED) && + !SymbolFlags.isFlagOn(sourceObjectType.flags, SymbolFlags.ISOLATED)) { + return false; + } + + Map targetFields = targetType.getFields(); + Map sourceFields = sourceObjectType.getFields(); + List targetFuncs = getAllFunctionsList(targetType); + List sourceFuncs = getAllFunctionsList(sourceObjectType); + + if (targetType.getFields().values().stream().anyMatch(field -> SymbolFlags + .isFlagOn(field.getFlags(), SymbolFlags.PRIVATE)) + || targetFuncs.stream().anyMatch(func -> SymbolFlags.isFlagOn(func.getFlags(), + SymbolFlags.PRIVATE))) { + return false; + } + + if (targetFields.size() > sourceFields.size() || targetFuncs.size() > sourceFuncs.size()) { + return false; + } + + String targetTypeModule = Optional.ofNullable(targetType.getPackage()).map(Module::toString).orElse(""); + String sourceTypeModule = Optional.ofNullable(sourceObjectType.getPackage()).map(Module::toString).orElse(""); + + if (sourceVal == null) { + if (!checkObjectSubTypeForFields(targetFields, sourceFields, targetTypeModule, sourceTypeModule, + unresolvedTypes)) { + return false; + } + } else if (!checkObjectSubTypeForFieldsByValue(targetFields, sourceFields, targetTypeModule, sourceTypeModule, + (BObject) sourceVal, unresolvedTypes)) { + return false; + } + + return checkObjectSubTypeForMethods(unresolvedTypes, targetFuncs, sourceFuncs, targetTypeModule, + sourceTypeModule, sourceObjectType, targetType); + } + + private static List getAllFunctionsList(BObjectType objectType) { + List functionList = new ArrayList<>(Arrays.asList(objectType.getMethods())); + if (objectType.getTag() == TypeTags.SERVICE_TAG || + (objectType.flags & SymbolFlags.CLIENT) == SymbolFlags.CLIENT) { + Collections.addAll(functionList, ((BNetworkObjectType) objectType).getResourceMethods()); + } + + return functionList; + } + + private static boolean checkObjectSubTypeForFields(Map targetFields, + Map sourceFields, String targetTypeModule, + String sourceTypeModule, List unresolvedTypes) { + for (Field lhsField : targetFields.values()) { + Field rhsField = sourceFields.get(lhsField.getFieldName()); + if (rhsField == null || + !isInSameVisibilityRegion(targetTypeModule, sourceTypeModule, lhsField.getFlags(), + rhsField.getFlags()) || hasIncompatibleReadOnlyFlags(lhsField, + rhsField) || + !checkIsType(rhsField.getFieldType(), lhsField.getFieldType(), unresolvedTypes)) { + return false; + } + } + return true; + } + + private static boolean checkObjectSubTypeForFieldsByValue(Map targetFields, + Map sourceFields, String targetTypeModule, + String sourceTypeModule, BObject sourceObjVal, + List unresolvedTypes) { + for (Field lhsField : targetFields.values()) { + String name = lhsField.getFieldName(); + Field rhsField = sourceFields.get(name); + if (rhsField == null || + !isInSameVisibilityRegion(targetTypeModule, sourceTypeModule, lhsField.getFlags(), + rhsField.getFlags()) || hasIncompatibleReadOnlyFlags(lhsField, + rhsField)) { + return false; + } + + if (SymbolFlags.isFlagOn(rhsField.getFlags(), SymbolFlags.FINAL)) { + Object fieldValue = sourceObjVal.get(StringUtils.fromString(name)); + Type fieldValueType = getType(fieldValue); + + if (fieldValueType.isReadOnly()) { + if (!checkIsLikeType(fieldValue, lhsField.getFieldType())) { + return false; + } + continue; + } + + if (!checkIsType(fieldValueType, lhsField.getFieldType(), unresolvedTypes)) { + return false; + } + } else if (!checkIsType(rhsField.getFieldType(), lhsField.getFieldType(), unresolvedTypes)) { + return false; + } + } + return true; + } + + private static boolean checkObjectSubTypeForMethods(List unresolvedTypes, + List targetFuncs, + List sourceFuncs, + String targetTypeModule, String sourceTypeModule, + BObjectType sourceType, BObjectType targetType) { + for (MethodType lhsFunc : targetFuncs) { + Optional rhsFunction = getMatchingInvokableType(sourceFuncs, lhsFunc, unresolvedTypes); + if (rhsFunction.isEmpty()) { + return false; + } + + MethodType rhsFunc = rhsFunction.get(); + if (!isInSameVisibilityRegion(targetTypeModule, sourceTypeModule, lhsFunc.getFlags(), rhsFunc.getFlags())) { + return false; + } + if (SymbolFlags.isFlagOn(lhsFunc.getFlags(), SymbolFlags.REMOTE) != SymbolFlags + .isFlagOn(rhsFunc.getFlags(), SymbolFlags.REMOTE)) { + return false; + } + } + + // Target type is not a distinct type, no need to match type-ids + BTypeIdSet targetTypeIdSet = targetType.typeIdSet; + if (targetTypeIdSet == null) { + return true; + } + + BTypeIdSet sourceTypeIdSet = sourceType.typeIdSet; + if (sourceTypeIdSet == null) { + return false; + } + + return sourceTypeIdSet.containsAll(targetTypeIdSet); + } + + private static boolean isInSameVisibilityRegion(String lhsTypePkg, String rhsTypePkg, long lhsFlags, + long rhsFlags) { + if (SymbolFlags.isFlagOn(lhsFlags, SymbolFlags.PRIVATE)) { + return lhsTypePkg.equals(rhsTypePkg); + } else if (SymbolFlags.isFlagOn(lhsFlags, SymbolFlags.PUBLIC)) { + return SymbolFlags.isFlagOn(rhsFlags, SymbolFlags.PUBLIC); + } + return !SymbolFlags.isFlagOn(rhsFlags, SymbolFlags.PRIVATE) && !SymbolFlags + .isFlagOn(rhsFlags, SymbolFlags.PUBLIC) && + lhsTypePkg.equals(rhsTypePkg); + } + + private static Optional getMatchingInvokableType(List rhsFuncs, + MethodType lhsFunc, + List unresolvedTypes) { + Optional matchingFunction = rhsFuncs.stream() + .filter(rhsFunc -> lhsFunc.getName().equals(rhsFunc.getName())) + .filter(rhsFunc -> checkFunctionTypeEqualityForObjectType(rhsFunc.getType(), lhsFunc.getType(), + unresolvedTypes)) + .findFirst(); + + if (matchingFunction.isEmpty()) { + return matchingFunction; + } + // For resource function match, we need to check whether lhs function resource path type belongs to + // rhs function resource path type + MethodType matchingFunc = matchingFunction.get(); + boolean lhsFuncIsResource = SymbolFlags.isFlagOn(lhsFunc.getFlags(), SymbolFlags.RESOURCE); + boolean matchingFuncIsResource = SymbolFlags.isFlagOn(matchingFunc.getFlags(), SymbolFlags.RESOURCE); + + if (!lhsFuncIsResource && !matchingFuncIsResource) { + return matchingFunction; + } + + if (!lhsFuncIsResource || !matchingFuncIsResource) { + return Optional.empty(); + } + + Type[] lhsFuncResourcePathTypes = ((BResourceMethodType) lhsFunc).pathSegmentTypes; + Type[] rhsFuncResourcePathTypes = ((BResourceMethodType) matchingFunc).pathSegmentTypes; + + int lhsFuncResourcePathTypesSize = lhsFuncResourcePathTypes.length; + if (lhsFuncResourcePathTypesSize != rhsFuncResourcePathTypes.length) { + return Optional.empty(); + } + + for (int i = 0; i < lhsFuncResourcePathTypesSize; i++) { + if (!checkIsType(lhsFuncResourcePathTypes[i], rhsFuncResourcePathTypes[i])) { + return Optional.empty(); + } + } + + return matchingFunction; + } + + private static boolean checkFunctionTypeEqualityForObjectType(FunctionType source, FunctionType target, + List unresolvedTypes) { + if (hasIncompatibleIsolatedFlags(target, source)) { + return false; + } + + if (source.getParameters().length != target.getParameters().length) { + return false; + } + + for (int i = 0; i < source.getParameters().length; i++) { + if (!checkIsType(target.getParameters()[i].type, source.getParameters()[i].type, unresolvedTypes)) { + return false; + } + } + + if (source.getReturnType() == null && target.getReturnType() == null) { + return true; + } else if (source.getReturnType() == null || target.getReturnType() == null) { + return false; + } + + return checkIsType(source.getReturnType(), target.getReturnType(), unresolvedTypes); + } + + private static boolean checkIsFunctionType(Type sourceType, BFunctionType targetType) { + sourceType = getImpliedType(sourceType); + if (sourceType.getTag() != TypeTags.FUNCTION_POINTER_TAG) { + return false; + } + + BFunctionType source = (BFunctionType) sourceType; + if (hasIncompatibleIsolatedFlags(targetType, source) || hasIncompatibleTransactionalFlags(targetType, source)) { + return false; + } + + if (SymbolFlags.isFlagOn(targetType.getFlags(), SymbolFlags.ANY_FUNCTION)) { + return true; + } + + if (source.parameters.length != targetType.parameters.length) { + return false; + } + + for (int i = 0; i < source.parameters.length; i++) { + if (!checkIsType(targetType.parameters[i].type, source.parameters[i].type, new ArrayList<>())) { + return false; + } + } + + return checkIsType(source.retType, targetType.retType, new ArrayList<>()); + } + + private static boolean hasIncompatibleIsolatedFlags(FunctionType target, FunctionType source) { + return SymbolFlags.isFlagOn(target.getFlags(), SymbolFlags.ISOLATED) && !SymbolFlags + .isFlagOn(source.getFlags(), SymbolFlags.ISOLATED); + } + + private static boolean hasIncompatibleTransactionalFlags(FunctionType target, FunctionType source) { + return SymbolFlags.isFlagOn(source.getFlags(), SymbolFlags.TRANSACTIONAL) && !SymbolFlags + .isFlagOn(target.getFlags(), SymbolFlags.TRANSACTIONAL); + } + + private static boolean checkIsServiceType(Type sourceType, Type targetType, List unresolvedTypes) { + sourceType = getImpliedType(sourceType); + if (sourceType.getTag() == TypeTags.SERVICE_TAG) { + return checkObjectEquivalency(sourceType, (BObjectType) targetType, unresolvedTypes); + } + + if (sourceType.getTag() == TypeTags.OBJECT_TYPE_TAG) { + long flags = ((BObjectType) sourceType).flags; + return (flags & SymbolFlags.SERVICE) == SymbolFlags.SERVICE; + } + + return false; + } + + public static boolean isInherentlyImmutableType(Type sourceType) { + sourceType = getImpliedType(sourceType); + if (isSimpleBasicType(sourceType)) { + return true; + } + + return switch (sourceType.getTag()) { + case TypeTags.XML_TEXT_TAG, + TypeTags.FINITE_TYPE_TAG, // Assuming a finite type will only have members from simple basic types. + TypeTags.READONLY_TAG, + TypeTags.NULL_TAG, + TypeTags.NEVER_TAG, + TypeTags.ERROR_TAG, + TypeTags.INVOKABLE_TAG, + TypeTags.SERVICE_TAG, + TypeTags.TYPEDESC_TAG, + TypeTags.FUNCTION_POINTER_TAG, + TypeTags.HANDLE_TAG, + TypeTags.REG_EXP_TYPE_TAG -> true; + case TypeTags.XML_TAG -> ((BXmlType) sourceType).constraint.getTag() == TypeTags.NEVER_TAG; + case TypeTags.TYPE_REFERENCED_TYPE_TAG -> + isInherentlyImmutableType(((BTypeReferenceType) sourceType).getReferredType()); + default -> false; + }; + } + + public static boolean isSelectivelyImmutableType(Type type, Set unresolvedTypes) { + if (!unresolvedTypes.add(type)) { + return true; + } + + switch (type.getTag()) { + case TypeTags.ANY_TAG: + case TypeTags.ANYDATA_TAG: + case TypeTags.JSON_TAG: + case TypeTags.XML_TAG: + case TypeTags.XML_COMMENT_TAG: + case TypeTags.XML_ELEMENT_TAG: + case TypeTags.XML_PI_TAG: + return true; + case TypeTags.ARRAY_TAG: + Type elementType = ((BArrayType) type).getElementType(); + return isInherentlyImmutableType(elementType) || + isSelectivelyImmutableType(elementType, unresolvedTypes); + case TypeTags.TUPLE_TAG: + BTupleType tupleType = (BTupleType) type; + for (Type tupMemType : tupleType.getTupleTypes()) { + if (!isInherentlyImmutableType(tupMemType) && + !isSelectivelyImmutableType(tupMemType, unresolvedTypes)) { + return false; + } + } + + Type tupRestType = tupleType.getRestType(); + if (tupRestType == null) { + return true; + } + + return isInherentlyImmutableType(tupRestType) || + isSelectivelyImmutableType(tupRestType, unresolvedTypes); + case TypeTags.RECORD_TYPE_TAG: + BRecordType recordType = (BRecordType) type; + for (Field field : recordType.getFields().values()) { + Type fieldType = field.getFieldType(); + if (!isInherentlyImmutableType(fieldType) && + !isSelectivelyImmutableType(fieldType, unresolvedTypes)) { + return false; + } + } + + Type recordRestType = recordType.restFieldType; + if (recordRestType == null) { + return true; } return isInherentlyImmutableType(recordRestType) || @@ -713,165 +1981,788 @@ public static boolean isSelectivelyImmutableType(Type type, Set unresolved case TypeTags.OBJECT_TYPE_TAG: BObjectType objectType = (BObjectType) type; - if (SymbolFlags.isFlagOn(objectType.flags, SymbolFlags.CLASS) && - !SymbolFlags.isFlagOn(objectType.flags, SymbolFlags.READONLY)) { + if (SymbolFlags.isFlagOn(objectType.flags, SymbolFlags.CLASS) && + !SymbolFlags.isFlagOn(objectType.flags, SymbolFlags.READONLY)) { + return false; + } + + for (Field field : objectType.getFields().values()) { + Type fieldType = field.getFieldType(); + if (!isInherentlyImmutableType(fieldType) && + !isSelectivelyImmutableType(fieldType, unresolvedTypes)) { + return false; + } + } + return true; + case TypeTags.MAP_TAG: + Type constraintType = ((BMapType) type).getConstrainedType(); + return isInherentlyImmutableType(constraintType) || + isSelectivelyImmutableType(constraintType, unresolvedTypes); + case TypeTags.TABLE_TAG: + Type tableConstraintType = ((BTableType) type).getConstrainedType(); + return isInherentlyImmutableType(tableConstraintType) || + isSelectivelyImmutableType(tableConstraintType, unresolvedTypes); + case TypeTags.UNION_TAG: + boolean readonlyIntersectionExists = false; + for (Type memberType : ((BUnionType) type).getMemberTypes()) { + if (isInherentlyImmutableType(memberType) || + isSelectivelyImmutableType(memberType, unresolvedTypes)) { + readonlyIntersectionExists = true; + break; + } + } + return readonlyIntersectionExists; + case TypeTags.INTERSECTION_TAG: + return isSelectivelyImmutableType(((BIntersectionType) type).getEffectiveType(), unresolvedTypes); + case TypeTags.TYPE_REFERENCED_TYPE_TAG: + return isSelectivelyImmutableType(((BTypeReferenceType) type).getReferredType(), unresolvedTypes); + default: + return false; + } + } + + private static boolean checkConstraints(Type sourceConstraint, Type targetConstraint, + List unresolvedTypes) { + if (sourceConstraint == null) { + sourceConstraint = TYPE_ANY; + } + + if (targetConstraint == null) { + targetConstraint = TYPE_ANY; + } + + return checkIsType(sourceConstraint, targetConstraint, unresolvedTypes); + } + + private static boolean isMutable(Object value, Type sourceType) { + // All the value types are immutable + sourceType = getImpliedType(sourceType); + if (value == null || sourceType.getTag() < TypeTags.NULL_TAG || + sourceType.getTag() == TypeTags.FINITE_TYPE_TAG) { + return false; + } + + return !((BRefValue) value).isFrozen(); + } + + private static boolean checkIsNeverTypeOrStructureTypeWithARequiredNeverMember(Type type) { + Set visitedTypeSet = new HashSet<>(); + return checkIsNeverTypeOrStructureTypeWithARequiredNeverMember(type, visitedTypeSet); + } + + private static boolean checkIsNeverTypeOrStructureTypeWithARequiredNeverMember(Type type, + Set visitedTypeSet) { + switch (type.getTag()) { + case TypeTags.NEVER_TAG: + return true; + case TypeTags.RECORD_TYPE_TAG: + BRecordType recordType = (BRecordType) type; + visitedTypeSet.add(recordType.getName()); + for (Field field : recordType.getFields().values()) { + // skip check for fields with self referencing type and not required fields. + if ((SymbolFlags.isFlagOn(field.getFlags(), SymbolFlags.REQUIRED) || + !SymbolFlags.isFlagOn(field.getFlags(), SymbolFlags.OPTIONAL)) && + !visitedTypeSet.contains(field.getFieldType()) && + checkIsNeverTypeOrStructureTypeWithARequiredNeverMember(field.getFieldType(), + visitedTypeSet)) { + return true; + } + } + return false; + case TypeTags.TUPLE_TAG: + BTupleType tupleType = (BTupleType) type; + visitedTypeSet.add(tupleType.getName()); + List tupleTypes = tupleType.getTupleTypes(); + for (Type mem : tupleTypes) { + if (!visitedTypeSet.add(mem.getName())) { + continue; + } + if (checkIsNeverTypeOrStructureTypeWithARequiredNeverMember(mem, visitedTypeSet)) { + return true; + } + } + return false; + case TypeTags.ARRAY_TAG: + BArrayType arrayType = (BArrayType) type; + visitedTypeSet.add(arrayType.getName()); + Type elemType = arrayType.getElementType(); + visitedTypeSet.add(elemType.getName()); + return arrayType.getState() != ArrayState.OPEN && + checkIsNeverTypeOrStructureTypeWithARequiredNeverMember(elemType, visitedTypeSet); + case TypeTags.TYPE_REFERENCED_TYPE_TAG: + return checkIsNeverTypeOrStructureTypeWithARequiredNeverMember( + ((BTypeReferenceType) type).getReferredType(), visitedTypeSet); + case TypeTags.INTERSECTION_TAG: + return checkIsNeverTypeOrStructureTypeWithARequiredNeverMember( + ((BIntersectionType) type).getEffectiveType(), visitedTypeSet); + default: + return false; + } + } + + /** + * Check whether a given value confirms to a given type. First it checks if the type of the value, and + * if fails then falls back to checking the value. + * + * @param errors list to collect typecast errors + * @param sourceValue Value to check + * @param targetType Target type + * @param unresolvedValues Values that are unresolved so far + * @param allowNumericConversion Flag indicating whether to perform numeric conversions + * @param varName variable name to identify the parent of a record field + * @return True if the value confirms to the provided type. False, otherwise. + */ + private static boolean checkIsLikeType(List errors, Object sourceValue, Type targetType, + List unresolvedValues, + boolean allowNumericConversion, String varName) { + Type sourceType = getType(sourceValue); + if (checkIsType(sourceType, targetType, new ArrayList<>())) { + return true; + } + + return checkIsLikeOnValue(errors, sourceValue, sourceType, targetType, unresolvedValues, allowNumericConversion, + varName); + } + + /** + * Check whether a given value confirms to a given type. Strictly checks the value only, and does not consider the + * type of the value for consideration. + * + * @param errors list to collect typecast errors + * @param sourceValue Value to check + * @param sourceType Type of the value + * @param targetType Target type + * @param unresolvedValues Values that are unresolved so far + * @param allowNumericConversion Flag indicating whether to perform numeric conversions + * @param varName variable name to identify the parent of a record field + * @return True if the value confirms to the provided type. False, otherwise. + */ + private static boolean checkIsLikeOnValue(List errors, Object sourceValue, Type sourceType, Type targetType, + List unresolvedValues, boolean allowNumericConversion, + String varName) { + int sourceTypeTag = sourceType.getTag(); + int targetTypeTag = targetType.getTag(); + + switch (sourceTypeTag) { + case TypeTags.INTERSECTION_TAG: + return checkIsLikeOnValue(errors, sourceValue, ((BIntersectionType) sourceType).getEffectiveType(), + targetTypeTag != TypeTags.INTERSECTION_TAG ? targetType : + ((BIntersectionType) targetType).getEffectiveType(), + unresolvedValues, allowNumericConversion, varName); + case TypeTags.PARAMETERIZED_TYPE_TAG: + if (targetTypeTag != TypeTags.PARAMETERIZED_TYPE_TAG) { + return checkIsLikeOnValue(errors, sourceValue, + ((BParameterizedType) sourceType).getParamValueType(), targetType, unresolvedValues, + allowNumericConversion, varName); + } + return checkIsLikeOnValue(errors, sourceValue, ((BParameterizedType) sourceType).getParamValueType(), + ((BParameterizedType) targetType).getParamValueType(), unresolvedValues, + allowNumericConversion, varName); + default: + break; + } + + return switch (targetTypeTag) { + case TypeTags.READONLY_TAG -> true; + case TypeTags.BYTE_TAG -> { + if (TypeTags.isIntegerTypeTag(sourceTypeTag)) { + yield isByteLiteral((Long) sourceValue); + } + yield allowNumericConversion && TypeConverter.isConvertibleToByte(sourceValue); + } + case TypeTags.INT_TAG -> allowNumericConversion && TypeConverter.isConvertibleToInt(sourceValue); + case TypeTags.SIGNED32_INT_TAG, + TypeTags.SIGNED16_INT_TAG, + TypeTags.SIGNED8_INT_TAG, + TypeTags.UNSIGNED32_INT_TAG, + TypeTags.UNSIGNED16_INT_TAG, + TypeTags.UNSIGNED8_INT_TAG -> { + if (TypeTags.isIntegerTypeTag(sourceTypeTag)) { + yield TypeConverter.isConvertibleToIntSubType(sourceValue, targetType); + } + yield allowNumericConversion && TypeConverter.isConvertibleToIntSubType(sourceValue, targetType); + } + case TypeTags.FLOAT_TAG, + TypeTags.DECIMAL_TAG -> + allowNumericConversion && TypeConverter.isConvertibleToFloatingPointTypes(sourceValue); + case TypeTags.CHAR_STRING_TAG -> TypeConverter.isConvertibleToChar(sourceValue); + case TypeTags.RECORD_TYPE_TAG -> + checkIsLikeRecordType(sourceValue, (BRecordType) targetType, unresolvedValues, + allowNumericConversion, varName, errors); + case TypeTags.TABLE_TAG -> checkIsLikeTableType(sourceValue, (BTableType) targetType, unresolvedValues, + allowNumericConversion); + case TypeTags.JSON_TAG -> + checkIsLikeJSONType(sourceValue, sourceType, (BJsonType) targetType, unresolvedValues, + allowNumericConversion); + case TypeTags.MAP_TAG -> + checkIsLikeMapType(sourceValue, (BMapType) targetType, unresolvedValues, allowNumericConversion); + case TypeTags.STREAM_TAG -> checkIsLikeStreamType(sourceValue, (BStreamType) targetType); + case TypeTags.ARRAY_TAG -> checkIsLikeArrayType(sourceValue, (BArrayType) targetType, unresolvedValues, + allowNumericConversion); + case TypeTags.TUPLE_TAG -> checkIsLikeTupleType(sourceValue, (BTupleType) targetType, unresolvedValues, + allowNumericConversion); + case TypeTags.ERROR_TAG -> checkIsLikeErrorType(sourceValue, (BErrorType) targetType, unresolvedValues, + allowNumericConversion); + case TypeTags.ANYDATA_TAG -> + checkIsLikeAnydataType(sourceValue, sourceType, unresolvedValues, allowNumericConversion); + case TypeTags.FINITE_TYPE_TAG -> + checkFiniteTypeAssignable(sourceValue, sourceType, (BFiniteType) targetType, + unresolvedValues, allowNumericConversion); + case TypeTags.XML_ELEMENT_TAG, + TypeTags.XML_COMMENT_TAG, + TypeTags.XML_PI_TAG, + TypeTags.XML_TEXT_TAG -> { + if (TypeTags.isXMLTypeTag(sourceTypeTag)) { + yield checkIsLikeXmlValueSingleton((XmlValue) sourceValue, targetType); + } + yield false; + } + case TypeTags.XML_TAG -> { + if (TypeTags.isXMLTypeTag(sourceTypeTag)) { + yield checkIsLikeXMLSequenceType((XmlValue) sourceValue, targetType); + } + yield false; + } + case TypeTags.UNION_TAG -> + checkIsLikeUnionType(errors, sourceValue, (BUnionType) targetType, unresolvedValues, + allowNumericConversion, varName); + case TypeTags.INTERSECTION_TAG -> checkIsLikeOnValue(errors, sourceValue, sourceType, + ((BIntersectionType) targetType).getEffectiveType(), unresolvedValues, allowNumericConversion, + varName); + case TypeTags.TYPE_REFERENCED_TYPE_TAG -> checkIsLikeOnValue(errors, sourceValue, sourceType, + ((BTypeReferenceType) targetType).getReferredType(), unresolvedValues, allowNumericConversion, + varName); + default -> false; + }; + } + + private static boolean checkIsLikeUnionType(List errors, Object sourceValue, BUnionType targetType, + List unresolvedValues, boolean allowNumericConversion, + String varName) { + if (allowNumericConversion) { + List compatibleTypesWithNumConversion = new ArrayList<>(); + List compatibleTypesWithoutNumConversion = new ArrayList<>(); + for (Type type : targetType.getMemberTypes()) { + List tempList = new ArrayList<>(unresolvedValues.size()); + tempList.addAll(unresolvedValues); + + if (checkIsLikeType(null, sourceValue, type, tempList, false, varName)) { + compatibleTypesWithoutNumConversion.add(type); + } + + if (checkIsLikeType(null, sourceValue, type, unresolvedValues, true, varName)) { + compatibleTypesWithNumConversion.add(type); + } + } + // Conversion should only be possible to one other numeric type. + return !compatibleTypesWithNumConversion.isEmpty() && + compatibleTypesWithNumConversion.size() - compatibleTypesWithoutNumConversion.size() <= 1; + } else { + return checkIsLikeUnionType(errors, sourceValue, targetType, unresolvedValues, varName); + } + } + + private static boolean checkIsLikeUnionType(List errors, Object sourceValue, BUnionType targetType, + List unresolvedValues, String varName) { + if (errors == null) { + for (Type type : targetType.getMemberTypes()) { + if (checkIsLikeType(null, sourceValue, type, unresolvedValues, false, varName)) { + return true; + } + } + } else { + int initialErrorCount; + errors.add(ERROR_MESSAGE_UNION_START); + int initialErrorListSize = errors.size(); + for (Type type : targetType.getMemberTypes()) { + initialErrorCount = errors.size(); + if (checkIsLikeType(errors, sourceValue, type, unresolvedValues, false, varName)) { + errors.subList(initialErrorListSize - 1, errors.size()).clear(); + return true; + } + if (initialErrorCount != errors.size()) { + errors.add(ERROR_MESSAGE_UNION_SEPARATOR); + } + } + int currentErrorListSize = errors.size(); + errors.remove(currentErrorListSize - 1); + if (initialErrorListSize != currentErrorListSize) { + errors.add(ERROR_MESSAGE_UNION_END); + } + } + return false; + } + + private static XmlNodeType getXmlNodeType(Type type) { + return switch (getImpliedType(type).getTag()) { + case TypeTags.XML_ELEMENT_TAG -> XmlNodeType.ELEMENT; + case TypeTags.XML_COMMENT_TAG -> XmlNodeType.COMMENT; + case TypeTags.XML_PI_TAG -> XmlNodeType.PI; + default -> XmlNodeType.TEXT; + }; + } + + private static boolean checkIsLikeXmlValueSingleton(XmlValue xmlSource, Type targetType) { + XmlNodeType targetXmlNodeType = getXmlNodeType(targetType); + XmlNodeType xmlSourceNodeType = xmlSource.getNodeType(); + + if (xmlSourceNodeType == targetXmlNodeType) { + return true; + } + + if (xmlSourceNodeType == XmlNodeType.SEQUENCE) { + XmlSequence seq = (XmlSequence) xmlSource; + return seq.size() == 1 && seq.getChildrenList().get(0).getNodeType() == targetXmlNodeType || + (targetXmlNodeType == XmlNodeType.TEXT && seq.isEmpty()); + } + + return false; + } + + private static void populateTargetXmlNodeTypes(Set nodeTypes, Type targetType) { + // there are only 4 xml subtypes + if (nodeTypes.size() == 4) { + return; + } + + Type referredType = getImpliedType(targetType); + switch (referredType.getTag()) { + case TypeTags.UNION_TAG: + for (Type memberType : ((UnionType) referredType).getMemberTypes()) { + populateTargetXmlNodeTypes(nodeTypes, memberType); + } + break; + case TypeTags.INTERSECTION_TAG: + populateTargetXmlNodeTypes(nodeTypes, ((IntersectionType) referredType).getEffectiveType()); + break; + case TypeTags.XML_ELEMENT_TAG: + nodeTypes.add(XmlNodeType.ELEMENT); + break; + case TypeTags.XML_COMMENT_TAG: + nodeTypes.add(XmlNodeType.COMMENT); + break; + case TypeTags.XML_PI_TAG: + nodeTypes.add(XmlNodeType.PI); + break; + case TypeTags.XML_TEXT_TAG: + nodeTypes.add(XmlNodeType.TEXT); + break; + case TypeTags.XML_TAG: + populateTargetXmlNodeTypes(nodeTypes, ((BXmlType) referredType).constraint); + break; + default: + break; + + } + } + + private static boolean checkIsLikeXMLSequenceType(XmlValue xmlSource, Type targetType) { + Set acceptedNodeTypes = new HashSet<>(); + populateTargetXmlNodeTypes(acceptedNodeTypes, targetType); + + XmlNodeType xmlSourceNodeType = xmlSource.getNodeType(); + if (xmlSourceNodeType != XmlNodeType.SEQUENCE) { + return acceptedNodeTypes.contains(xmlSourceNodeType); + } + + XmlSequence seq = (XmlSequence) xmlSource; + for (BXml m : seq.getChildrenList()) { + if (!acceptedNodeTypes.contains(m.getNodeType())) { + return false; + } + } + return true; + } + + public static boolean isNumericType(Type type) { + type = getImpliedType(type); + return type.getTag() < TypeTags.STRING_TAG || TypeTags.isIntegerTypeTag(type.getTag()); + } + + private static boolean checkIsLikeAnydataType(Object sourceValue, Type sourceType, + List unresolvedValues, + boolean allowNumericConversion) { + sourceType = getImpliedType(sourceType); + switch (sourceType.getTag()) { + case TypeTags.RECORD_TYPE_TAG: + case TypeTags.MAP_TAG: + return isLikeAnydataType(((MapValueImpl) sourceValue).values().toArray(), + unresolvedValues, allowNumericConversion); + case TypeTags.TABLE_TAG: + return isLikeAnydataType(((TableValueImpl) sourceValue).values().toArray(), + unresolvedValues, allowNumericConversion); + case TypeTags.ARRAY_TAG: + ArrayValue arr = (ArrayValue) sourceValue; + BArrayType arrayType = (BArrayType) getImpliedType(arr.getType()); + return switch (getImpliedType(arrayType.getElementType()).getTag()) { + case TypeTags.INT_TAG, + TypeTags.FLOAT_TAG, + TypeTags.DECIMAL_TAG, + TypeTags.STRING_TAG, + TypeTags.BOOLEAN_TAG, + TypeTags.BYTE_TAG -> true; + default -> isLikeAnydataType(arr.getValues(), unresolvedValues, allowNumericConversion); + }; + case TypeTags.TUPLE_TAG: + return isLikeAnydataType(((ArrayValue) sourceValue).getValues(), unresolvedValues, + allowNumericConversion); + default: + return sourceType.isAnydata(); + } + } + + private static boolean isLikeAnydataType(Object[] objects, List unresolvedValues, + boolean allowNumericConversion) { + for (Object value : objects) { + if (!checkIsLikeType(null, value, TYPE_ANYDATA, unresolvedValues, allowNumericConversion, + null)) { + return false; + } + } + return true; + } + + private static boolean checkIsLikeTupleType(Object sourceValue, BTupleType targetType, + List unresolvedValues, boolean allowNumericConversion) { + if (!(sourceValue instanceof ArrayValue source)) { + return false; + } + + List targetTypes = targetType.getTupleTypes(); + int sourceTypeSize = source.size(); + int targetTypeSize = targetTypes.size(); + Type targetRestType = targetType.getRestType(); + + if (sourceTypeSize < targetTypeSize) { + return false; + } + if (targetRestType == null && sourceTypeSize > targetTypeSize) { + return false; + } + + for (int i = 0; i < targetTypeSize; i++) { + if (!checkIsLikeType(null, source.getRefValue(i), targetTypes.get(i), unresolvedValues, + allowNumericConversion, null)) { + return false; + } + } + for (int i = targetTypeSize; i < sourceTypeSize; i++) { + if (!checkIsLikeType(null, source.getRefValue(i), targetRestType, unresolvedValues, + allowNumericConversion, null)) { + return false; + } + } + return true; + } + + public static boolean isByteLiteral(long longValue) { + return (longValue >= BBYTE_MIN_VALUE && longValue <= BBYTE_MAX_VALUE); + } + + static boolean isSigned32LiteralValue(Long longObject) { + + return (longObject >= SIGNED32_MIN_VALUE && longObject <= SIGNED32_MAX_VALUE); + } + + static boolean isSigned16LiteralValue(Long longObject) { + + return (longObject.intValue() >= SIGNED16_MIN_VALUE && longObject.intValue() <= SIGNED16_MAX_VALUE); + } + + static boolean isSigned8LiteralValue(Long longObject) { + + return (longObject.intValue() >= SIGNED8_MIN_VALUE && longObject.intValue() <= SIGNED8_MAX_VALUE); + } + + static boolean isUnsigned32LiteralValue(Long longObject) { + + return (longObject >= 0 && longObject <= UNSIGNED32_MAX_VALUE); + } + + static boolean isUnsigned16LiteralValue(Long longObject) { + + return (longObject.intValue() >= 0 && longObject.intValue() <= UNSIGNED16_MAX_VALUE); + } + + static boolean isUnsigned8LiteralValue(Long longObject) { + + return (longObject.intValue() >= 0 && longObject.intValue() <= UNSIGNED8_MAX_VALUE); + } + + static boolean isCharLiteralValue(Object object) { + String value; + if (object instanceof BString bString) { + value = bString.getValue(); + } else if (object instanceof String s) { + value = s; + } else { + return false; + } + return value.codePoints().count() == 1; + } + + private static boolean checkIsLikeArrayType(Object sourceValue, BArrayType targetType, + List unresolvedValues, boolean allowNumericConversion) { + if (!(sourceValue instanceof ArrayValue source)) { + return false; + } + + Type targetTypeElementType = targetType.getElementType(); + if (source.getType().getTag() == TypeTags.ARRAY_TAG) { + Type sourceElementType = ((BArrayType) source.getType()).getElementType(); + if (isValueType(sourceElementType)) { + + if (checkIsType(sourceElementType, targetTypeElementType, new ArrayList<>())) { + return true; + } + + if (allowNumericConversion && isNumericType(sourceElementType)) { + if (isNumericType(targetTypeElementType)) { + return true; + } + + if (targetTypeElementType.getTag() != TypeTags.UNION_TAG) { + return false; + } + + List targetNumericTypes = new ArrayList<>(); + for (Type memType : ((BUnionType) targetTypeElementType).getMemberTypes()) { + if (isNumericType(memType) && !targetNumericTypes.contains(memType)) { + targetNumericTypes.add(memType); + } + } + return targetNumericTypes.size() == 1; + } + + if (targetTypeElementType.getTag() == TypeTags.FLOAT_TAG || + targetTypeElementType.getTag() == TypeTags.DECIMAL_TAG) { return false; } + } + } - for (Field field : objectType.getFields().values()) { - Type fieldType = field.getFieldType(); - if (!isInherentlyImmutableType(fieldType) && - !isSelectivelyImmutableType(fieldType, unresolvedTypes)) { + int sourceSize = source.size(); + if ((targetType.getState() != ArrayState.OPEN) && (sourceSize != targetType.getSize())) { + return false; + } + for (int i = 0; i < sourceSize; i++) { + if (!checkIsLikeType(null, source.get(i), targetTypeElementType, unresolvedValues, + allowNumericConversion, null)) { + return false; + } + } + return true; + } + + private static boolean checkIsLikeMapType(Object sourceValue, BMapType targetType, + List unresolvedValues, boolean allowNumericConversion) { + if (!(sourceValue instanceof MapValueImpl sourceMapValue)) { + return false; + } + + for (Object mapEntry : sourceMapValue.values()) { + if (!checkIsLikeType(null, mapEntry, targetType.getConstrainedType(), unresolvedValues, + allowNumericConversion, null)) { + return false; + } + } + return true; + } + + private static boolean checkIsLikeStreamType(Object sourceValue, BStreamType targetType) { + if (!(sourceValue instanceof StreamValue streamValue)) { + return false; + } + + BStreamType streamType = (BStreamType) streamValue.getType(); + + return streamType.getConstrainedType() == targetType.getConstrainedType(); + } + + private static boolean checkIsLikeJSONType(Object sourceValue, Type sourceType, BJsonType targetType, + List unresolvedValues, boolean allowNumericConversion) { + Type referredSourceType = getImpliedType(sourceType); + switch (referredSourceType.getTag()) { + case TypeTags.ARRAY_TAG: + ArrayValue source = (ArrayValue) sourceValue; + Type elementType = ((BArrayType) referredSourceType).getElementType(); + if (checkIsType(elementType, targetType, new ArrayList<>())) { + return true; + } + + Object[] arrayValues = source.getValues(); + for (int i = 0; i < source.size(); i++) { + if (!checkIsLikeType(null, arrayValues[i], targetType, unresolvedValues, + allowNumericConversion, null)) { return false; } } return true; - case TypeTags.MAP_TAG: - Type constraintType = ((MapType) type).getConstrainedType(); - return isInherentlyImmutableType(constraintType) || - isSelectivelyImmutableType(constraintType, unresolvedTypes); - case TypeTags.TABLE_TAG: - Type tableConstraintType = ((BTableType) type).getConstrainedType(); - return isInherentlyImmutableType(tableConstraintType) || - isSelectivelyImmutableType(tableConstraintType, unresolvedTypes); - case TypeTags.UNION_TAG: - boolean readonlyIntersectionExists = false; - for (Type memberType : ((BUnionType) type).getMemberTypes()) { - if (isInherentlyImmutableType(memberType) || - isSelectivelyImmutableType(memberType, unresolvedTypes)) { - readonlyIntersectionExists = true; - break; + case TypeTags.TUPLE_TAG: + for (Object obj : ((TupleValueImpl) sourceValue).getValues()) { + if (!checkIsLikeType(null, obj, targetType, unresolvedValues, allowNumericConversion, + null)) { + return false; } } - return readonlyIntersectionExists; - case TypeTags.INTERSECTION_TAG: - return isSelectivelyImmutableType(((BIntersectionType) type).getEffectiveType(), unresolvedTypes); - case TypeTags.TYPE_REFERENCED_TYPE_TAG: - return isSelectivelyImmutableType(((BTypeReferenceType) type).getReferredType(), unresolvedTypes); + return true; + case TypeTags.MAP_TAG: + return checkIsMappingLikeJsonType((MapValueImpl) sourceValue, targetType, unresolvedValues, + allowNumericConversion); + case TypeTags.RECORD_TYPE_TAG: + TypeValuePair typeValuePair = new TypeValuePair(sourceValue, targetType); + if (unresolvedValues.contains(typeValuePair)) { + return true; + } + unresolvedValues.add(typeValuePair); + return checkIsMappingLikeJsonType((MapValueImpl) sourceValue, targetType, unresolvedValues, + allowNumericConversion); default: return false; } } - static boolean isSigned32LiteralValue(Long longObject) { - - return (longObject >= SIGNED32_MIN_VALUE && longObject <= SIGNED32_MAX_VALUE); + private static boolean checkIsMappingLikeJsonType(MapValueImpl sourceValue, BJsonType targetType, + List unresolvedValues, + boolean allowNumericConversion) { + for (Object value : sourceValue.values()) { + if (!checkIsLikeType(null, value, targetType, unresolvedValues, allowNumericConversion, + null)) { + return false; + } + } + return true; } - static boolean isSigned16LiteralValue(Long longObject) { + private static boolean checkIsLikeRecordType(Object sourceValue, BRecordType targetType, + List unresolvedValues, boolean allowNumericConversion, + String varName, List errors) { + if (!(sourceValue instanceof MapValueImpl sourceMapValue)) { + return false; + } - return (longObject.intValue() >= SIGNED16_MIN_VALUE && longObject.intValue() <= SIGNED16_MAX_VALUE); - } + TypeValuePair typeValuePair = new TypeValuePair(sourceValue, targetType); + if (unresolvedValues.contains(typeValuePair)) { + return true; + } + unresolvedValues.add(typeValuePair); - static boolean isSigned8LiteralValue(Long longObject) { + Map targetFieldTypes = new HashMap<>(); + Type restFieldType = targetType.restFieldType; + boolean returnVal = true; - return (longObject.intValue() >= SIGNED8_MIN_VALUE && longObject.intValue() <= SIGNED8_MAX_VALUE); - } + for (Field field : targetType.getFields().values()) { + targetFieldTypes.put(field.getFieldName(), field.getFieldType()); + } - static boolean isUnsigned32LiteralValue(Long longObject) { + for (Map.Entry targetTypeEntry : targetFieldTypes.entrySet()) { + String fieldName = targetTypeEntry.getKey().toString(); + String fieldNameLong = TypeConverter.getLongFieldName(varName, fieldName); + Field targetField = targetType.getFields().get(fieldName); - return (longObject >= 0 && longObject <= UNSIGNED32_MAX_VALUE); - } + if (!(sourceMapValue.containsKey(StringUtils.fromString(fieldName))) && + !SymbolFlags.isFlagOn(targetField.getFlags(), SymbolFlags.OPTIONAL)) { + addErrorMessage((errors == null) ? 0 : errors.size(), "missing required field '" + fieldNameLong + + "' of type '" + targetField.getFieldType().toString() + "' in record '" + targetType + "'", + errors); + if ((errors == null) || (errors.size() >= MAX_TYPECAST_ERROR_COUNT + 1)) { + return false; + } + returnVal = false; + } + } - static boolean isUnsigned16LiteralValue(Long longObject) { + for (Object object : sourceMapValue.entrySet()) { + Map.Entry valueEntry = (Map.Entry) object; + String fieldName = valueEntry.getKey().toString(); + String fieldNameLong = TypeConverter.getLongFieldName(varName, fieldName); + int initialErrorCount = (errors == null) ? 0 : errors.size(); - return (longObject.intValue() >= 0 && longObject.intValue() <= UNSIGNED16_MAX_VALUE); + if (targetFieldTypes.containsKey(fieldName)) { + if (!checkIsLikeType(errors, (valueEntry.getValue()), targetFieldTypes.get(fieldName), + unresolvedValues, allowNumericConversion, fieldNameLong)) { + addErrorMessage(initialErrorCount, "field '" + fieldNameLong + "' in record '" + targetType + + "' should be of type '" + targetFieldTypes.get(fieldName) + "', found '" + + TypeConverter.getShortSourceValue(valueEntry.getValue()) + "'", errors); + returnVal = false; + } + } else { + if (!targetType.sealed) { + if (!checkIsLikeType(errors, (valueEntry.getValue()), restFieldType, unresolvedValues, + allowNumericConversion, fieldNameLong)) { + addErrorMessage(initialErrorCount, "value of field '" + valueEntry.getKey() + + "' adding to the record '" + targetType + "' should be of type '" + restFieldType + + "', found '" + TypeConverter.getShortSourceValue(valueEntry.getValue()) + "'", errors); + returnVal = false; + } + } else { + addErrorMessage(initialErrorCount, "field '" + fieldNameLong + + "' cannot be added to the closed record '" + targetType + "'", errors); + returnVal = false; + } + } + if ((!returnVal) && ((errors == null) || (errors.size() >= MAX_TYPECAST_ERROR_COUNT + 1))) { + return false; + } + } + return returnVal; } - static boolean isUnsigned8LiteralValue(Long longObject) { - - return (longObject.intValue() >= 0 && longObject.intValue() <= UNSIGNED8_MAX_VALUE); + private static void addErrorMessage(int initialErrorCount, String errorMessage, List errors) { + if ((errors != null) && (errors.size() <= MAX_TYPECAST_ERROR_COUNT) && + ((errors.size() - initialErrorCount) == 0)) { + errors.add(errorMessage); + } } - static boolean isCharLiteralValue(Object object) { - String value; - if (object instanceof BString) { - value = ((BString) object).getValue(); - } else if (object instanceof String) { - value = (String) object; - } else { + private static boolean checkIsLikeTableType(Object sourceValue, BTableType targetType, + List unresolvedValues, boolean allowNumericConversion) { + if (!(sourceValue instanceof TableValueImpl tableValue)) { return false; } - return value.codePoints().count() == 1; - } - - /** - * Deep value equality check for anydata. - * - * @param lhsValue The value on the left hand side - * @param rhsValue The value on the right hand side - * @param checkedValues Structured value pairs already compared or being compared - * @return True if values are equal, else false. - */ - public static boolean isEqual(Object lhsValue, Object rhsValue, Set checkedValues) { - if (lhsValue == rhsValue) { - return true; + BTableType sourceType = (BTableType) getImpliedType(tableValue.getType()); + if (targetType.getKeyType() != null && sourceType.getFieldNames().length == 0) { + return false; } - if (null == lhsValue || null == rhsValue) { + if (sourceType.getKeyType() != null && !checkIsType(tableValue.getKeyType(), targetType.getKeyType())) { return false; } - return checkValueEqual(lhsValue, rhsValue, new HashSet<>(checkedValues)); - } - - private static boolean checkValueEqual(Object lhsValue, Object rhsValue, Set checkedValues) { - Context cx = context(); - SemType lhsShape = ShapeAnalyzer.inherentTypeOf(cx, lhsValue).orElseThrow(); - SemType rhsShape = ShapeAnalyzer.inherentTypeOf(cx, rhsValue).orElseThrow(); - Predicate belongToSameBasicType = (basicType) -> Core.containsBasicType(lhsShape, basicType) && - Core.containsBasicType(rhsShape, basicType); - if (belongToSameBasicType.test(Builder.getStringType()) || - belongToSameBasicType.test(Builder.getBooleanType())) { - return lhsValue.equals(rhsValue); - } - if (belongToSameBasicType.test(Builder.getIntType())) { - // TODO: is this correct if one of the values are bytes (shouldn't we check of unsigned etc) - return ((Number) lhsValue).longValue() == ((Number) rhsValue).longValue(); - } - if (belongToSameBasicType.test(Builder.getFloatType())) { - Double lhs = (Double) lhsValue; - Double rhs = (Double) rhsValue; - // directly doing equals don't work with -0 and 0 - return (Double.isNaN(lhs) && Double.isNaN(rhs)) || lhs.doubleValue() == rhs.doubleValue(); - } - if (belongToSameBasicType.test(Builder.getDecimalType())) { - return checkDecimalEqual((DecimalValue) lhsValue, (DecimalValue) rhsValue); + TypeValuePair typeValuePair = new TypeValuePair(sourceValue, targetType); + if (unresolvedValues.contains(typeValuePair)) { + return true; } - if (belongToSameBasicType.test(RefValueTypeMaskHolder.REF_TYPE_MASK)) { - RefValue lhs = (RefValue) lhsValue; - return lhs.equals(rhsValue, checkedValues); + + Object[] objects = tableValue.values().toArray(); + for (Object object : objects) { + if (!checkIsLikeType(object, targetType.getConstrainedType(), allowNumericConversion)) { + return false; + } } - return false; + return true; } - public static boolean isRegExpType(Type targetType) { - if (targetType.getTag() == TypeTags.TYPE_REFERENCED_TYPE_TAG) { - Type referredType = ((BTypeReferenceType) targetType).getReferredType(); - Module referredTypePackage = referredType.getPackage(); - if ((referredTypePackage != null) && BALLERINA_BUILTIN_PKG_PREFIX.equals(referredTypePackage.getOrg()) - && REGEXP_LANG_LIB.equals(referredTypePackage.getName()) - && REG_EXP_TYPENAME.equals(referredType.getName())) { + private static boolean checkFiniteTypeAssignable(Object sourceValue, Type sourceType, BFiniteType targetType, + List unresolvedValues, + boolean allowNumericConversion) { + if (targetType.valueSpace.size() == 1) { + Type valueType = getImpliedType(getType(targetType.valueSpace.iterator().next())); + if (!isSimpleBasicType(valueType) && valueType.getTag() != TypeTags.NULL_TAG) { + return checkIsLikeOnValue(null, sourceValue, sourceType, valueType, unresolvedValues, + allowNumericConversion, null); + } + } + + for (Object valueSpaceItem : targetType.valueSpace) { + // TODO: 8/13/19 Maryam fix for conversion + if (isFiniteTypeValue(sourceValue, sourceType, valueSpaceItem, allowNumericConversion)) { return true; } - return isRegExpType(referredType); } return false; } - static boolean isStructuredType(Type type) { - Type referredType = getImpliedType(type); - return switch (referredType.getTag()) { - case TypeTags.ARRAY_TAG, - TypeTags.TUPLE_TAG, - TypeTags.MAP_TAG, - TypeTags.RECORD_TYPE_TAG, - TypeTags.TABLE_TAG -> - true; - default -> false; - }; - } - static boolean isFiniteTypeValue(Object sourceValue, Type sourceType, Object valueSpaceItem, boolean allowNumericConversion) { Type valueSpaceItemType = getType(valueSpaceItem); @@ -917,8 +2808,7 @@ static boolean isFiniteTypeValue(Object sourceValue, Type sourceType, Object val DecimalValue.valueOf(((Number) valueSpaceItem).longValue())) && allowNumericConversion; case TypeTags.FLOAT_TAG: return checkDecimalEqual((DecimalValue) sourceValue, - DecimalValue.valueOf(((Number) valueSpaceItem).doubleValue())) && - allowNumericConversion; + DecimalValue.valueOf(((Number) valueSpaceItem).doubleValue())) && allowNumericConversion; case TypeTags.DECIMAL_TAG: return checkDecimalEqual((DecimalValue) sourceValue, (DecimalValue) valueSpaceItem); } @@ -930,8 +2820,183 @@ static boolean isFiniteTypeValue(Object sourceValue, Type sourceType, Object val } } - public static Env getEnv() { - return Env.getInstance(); + private static boolean checkIsErrorType(Type sourceType, BErrorType targetType, List unresolvedTypes) { + if (sourceType.getTag() != TypeTags.ERROR_TAG) { + return false; + } + // Handle recursive error types. + TypePair pair = new TypePair(sourceType, targetType); + if (unresolvedTypes.contains(pair)) { + return true; + } + unresolvedTypes.add(pair); + BErrorType bErrorType = (BErrorType) sourceType; + + if (!checkIsType(bErrorType.detailType, targetType.detailType, unresolvedTypes)) { + return false; + } + + if (targetType.typeIdSet == null) { + return true; + } + + BTypeIdSet sourceTypeIdSet = bErrorType.typeIdSet; + if (sourceTypeIdSet == null) { + return false; + } + + return sourceTypeIdSet.containsAll(targetType.typeIdSet); + } + + private static boolean checkIsLikeErrorType(Object sourceValue, BErrorType targetType, + List unresolvedValues, boolean allowNumericConversion) { + Type sourceTypeReferredType = getImpliedType(getType(sourceValue)); + if (sourceValue == null || sourceTypeReferredType.getTag() != TypeTags.ERROR_TAG) { + return false; + } + if (!checkIsLikeType(null, ((ErrorValue) sourceValue).getDetails(), targetType.detailType, + unresolvedValues, allowNumericConversion, null)) { + return false; + } + if (targetType.typeIdSet == null) { + return true; + } + BTypeIdSet sourceIdSet = ((BErrorType) sourceTypeReferredType).typeIdSet; + if (sourceIdSet == null) { + return false; + } + return sourceIdSet.containsAll(targetType.typeIdSet); + } + + static boolean isSimpleBasicType(Type type) { + return getImpliedType(type).getTag() < TypeTags.NULL_TAG; + } + + /** + * Deep value equality check for anydata. + * + * @param lhsValue The value on the left hand side + * @param rhsValue The value on the right hand side + * @param checkedValues Structured value pairs already compared or being compared + * @return True if values are equal, else false. + */ + public static boolean isEqual(Object lhsValue, Object rhsValue, Set checkedValues) { + if (lhsValue == rhsValue) { + return true; + } + + if (null == lhsValue || null == rhsValue) { + return false; + } + + return checkValueEquals(lhsValue, rhsValue, checkedValues, getType(lhsValue), getType(rhsValue)); + } + + private static boolean checkValueEquals(Object lhsValue, Object rhsValue, Set checkedValues, + Type lhsValType, Type rhsValType) { + lhsValType = getImpliedType(lhsValType); + rhsValType = getImpliedType(rhsValType); + int lhsValTypeTag = lhsValType.getTag(); + int rhsValTypeTag = rhsValType.getTag(); + + switch (lhsValTypeTag) { + case TypeTags.STRING_TAG: + case TypeTags.BOOLEAN_TAG: + return lhsValue.equals(rhsValue); + case TypeTags.INT_TAG: + if (rhsValTypeTag != TypeTags.BYTE_TAG && rhsValTypeTag != TypeTags.INT_TAG) { + return false; + } + return lhsValue.equals(((Number) rhsValue).longValue()); + case TypeTags.BYTE_TAG: + if (rhsValTypeTag != TypeTags.BYTE_TAG && rhsValTypeTag != TypeTags.INT_TAG) { + return false; + } + return ((Number) lhsValue).byteValue() == ((Number) rhsValue).byteValue(); + case TypeTags.FLOAT_TAG: + if (rhsValTypeTag != TypeTags.FLOAT_TAG) { + return false; + } + if (Double.isNaN((Double) lhsValue) && Double.isNaN((Double) rhsValue)) { + return true; + } + return ((Number) lhsValue).doubleValue() == ((Number) rhsValue).doubleValue(); + case TypeTags.DECIMAL_TAG: + if (rhsValTypeTag != TypeTags.DECIMAL_TAG) { + return false; + } + return checkDecimalEqual((DecimalValue) lhsValue, (DecimalValue) rhsValue); + case TypeTags.XML_TAG: + // Instance of xml never + if (lhsValue instanceof XmlText xmlText) { + return TypeTags.isXMLTypeTag(rhsValTypeTag) && xmlText.equals(rhsValue, checkedValues); + } + return TypeTags.isXMLTypeTag(rhsValTypeTag) && ((XmlSequence) lhsValue).equals(rhsValue, checkedValues); + case TypeTags.XML_ELEMENT_TAG: + return TypeTags.isXMLTypeTag(rhsValTypeTag) && ((XmlItem) lhsValue).equals(rhsValue, checkedValues); + case TypeTags.XML_COMMENT_TAG: + return TypeTags.isXMLTypeTag(rhsValTypeTag) && ((XmlComment) lhsValue).equals(rhsValue, checkedValues); + case TypeTags.XML_TEXT_TAG: + return TypeTags.isXMLTypeTag(rhsValTypeTag) && ((XmlText) lhsValue).equals(rhsValue, checkedValues); + case TypeTags.XML_PI_TAG: + return TypeTags.isXMLTypeTag(rhsValTypeTag) && ((XmlPi) lhsValue).equals(rhsValue, checkedValues); + case TypeTags.MAP_TAG: + case TypeTags.JSON_TAG: + case TypeTags.RECORD_TYPE_TAG: + return isMappingType(rhsValTypeTag) && ((MapValueImpl) lhsValue).equals(rhsValue, checkedValues); + case TypeTags.TUPLE_TAG: + case TypeTags.ARRAY_TAG: + return isListType(rhsValTypeTag) && ((ArrayValue) lhsValue).equals(rhsValue, checkedValues); + case TypeTags.ERROR_TAG: + return rhsValTypeTag == TypeTags.ERROR_TAG && ((ErrorValue) lhsValue).equals(rhsValue, checkedValues); + case TypeTags.TABLE_TAG: + return rhsValTypeTag == TypeTags.TABLE_TAG && + ((TableValueImpl) lhsValue).equals(rhsValue, checkedValues); + case TypeTags.TYPE_REFERENCED_TYPE_TAG: + return checkValueEquals(lhsValue, rhsValue, checkedValues, + ((BTypeReferenceType) lhsValType).getReferredType(), rhsValType); + case TypeTags.SERVICE_TAG: + default: + if (lhsValue instanceof RegExpValue lhsRegExpValue) { + return lhsRegExpValue.equals(rhsValue, checkedValues); + } + return false; + } + } + + private static boolean isListType(int typeTag) { + return typeTag == TypeTags.ARRAY_TAG || typeTag == TypeTags.TUPLE_TAG; + } + + private static boolean isMappingType(int typeTag) { + return typeTag == TypeTags.MAP_TAG || typeTag == TypeTags.RECORD_TYPE_TAG || typeTag == TypeTags.JSON_TAG; + } + + public static boolean isRegExpType(Type targetType) { + if (targetType.getTag() == TypeTags.TYPE_REFERENCED_TYPE_TAG) { + Type referredType = ((BTypeReferenceType) targetType).getReferredType(); + Module referredTypePackage = referredType.getPackage(); + if ((referredTypePackage != null) && BALLERINA_BUILTIN_PKG_PREFIX.equals(referredTypePackage.getOrg()) + && REGEXP_LANG_LIB.equals(referredTypePackage.getName()) + && REG_EXP_TYPENAME.equals(referredType.getName())) { + return true; + } + return isRegExpType(referredType); + } + return false; + } + + static boolean isStructuredType(Type type) { + Type referredType = getImpliedType(type); + return switch (referredType.getTag()) { + case TypeTags.ARRAY_TAG, + TypeTags.TUPLE_TAG, + TypeTags.MAP_TAG, + TypeTags.RECORD_TYPE_TAG, + TypeTags.TABLE_TAG -> + true; + default -> false; + }; } /** @@ -939,7 +3004,7 @@ public static Env getEnv() { * * @since 0.995.0 */ - static class TypePair { + private static class TypePair { Type sourceType; Type targetType; @@ -979,35 +3044,11 @@ public static boolean hasFillerValue(Type type) { return hasFillerValue(type, new ArrayList<>()); } - private enum FillerValueResult { - TRUE, FALSE, MAYBE - } - - private static FillerValueResult hasFillerValueSemType(Context cx, SemType type) { - if (Core.containsBasicType(type, Builder.getNilType())) { - return FillerValueResult.TRUE; - } - if (Integer.bitCount(type.all() | type.some()) > 1) { - return FillerValueResult.FALSE; - } - if (type.some() != 0) { - return FillerValueResult.MAYBE; - } - return Core.containsBasicType(type, TopTypesWithFillValueMaskHolder.TOP_TYPES_WITH_ALWAYS_FILLING) ? - FillerValueResult.TRUE : - FillerValueResult.FALSE; - } - private static boolean hasFillerValue(Type type, List unanalyzedTypes) { if (type == null) { return true; } - FillerValueResult fastResult = hasFillerValueSemType(context(), SemType.tryInto(type)); - if (fastResult != FillerValueResult.MAYBE) { - return fastResult == FillerValueResult.TRUE; - } - int typeTag = type.getTag(); if (TypeTags.isXMLTypeTag(typeTag)) { return typeTag == TypeTags.XML_TAG || typeTag == TypeTags.XML_TEXT_TAG; @@ -1036,7 +3077,7 @@ private static boolean hasFillerValue(Type type, List unanalyzedTypes) { }; } - private static boolean checkFillerValue(BTupleType tupleType, List unAnalyzedTypes) { + private static boolean checkFillerValue(BTupleType tupleType, List unAnalyzedTypes) { if (unAnalyzedTypes.contains(tupleType)) { return true; } @@ -1133,7 +3174,7 @@ private static boolean isSameBasicType(Type sourceType, Type targetType) { } private static boolean isIntegerSubTypeTag(int typeTag) { - return TypeTags.isIntegerTypeTag(typeTag); + return TypeTags.isIntegerTypeTag(typeTag) || typeTag == TypeTags.BYTE_TAG; } private static boolean isFillerValueOfFiniteTypeBasicType(Object value) { @@ -1212,8 +3253,7 @@ private static boolean hasFillerValueInValueSpace(Set finiteTypeValueSpa if (firstElement instanceof BString) { return containsElement(finiteTypeValueSpace, ""); - } else if ((firstElement instanceof Integer) || (firstElement instanceof Long) || - (firstElement instanceof BDecimal)) { + } else if ((firstElement instanceof Long) || (firstElement instanceof BDecimal)) { return containsElement(finiteTypeValueSpace, "0"); } else if (firstElement instanceof Double) { return containsElement(finiteTypeValueSpace, "0.0"); @@ -1249,96 +3289,6 @@ private static BError createTypeCastError(Object value, Type targetType, List - ErrorUtils.createTypeCastError(inputValue, PredefinedTypes.TYPE_BYTE)); - } - Predicate isIntSubType = (subType) -> Core.isSameType(cx, targetType, SemType.tryInto(subType)); - if (isIntSubType.test(PredefinedTypes.TYPE_INT_SIGNED_32)) { - return anyToSigned32(inputValue); - } - if (isIntSubType.test(PredefinedTypes.TYPE_INT_SIGNED_16)) { - return anyToSigned16(inputValue); - } - if (isIntSubType.test(PredefinedTypes.TYPE_INT_SIGNED_8)) { - return anyToSigned8(inputValue); - } - if (isIntSubType.test(PredefinedTypes.TYPE_INT_UNSIGNED_32)) { - return anyToUnsigned32(inputValue); - } - if (isIntSubType.test(PredefinedTypes.TYPE_INT_UNSIGNED_16)) { - return anyToUnsigned16(inputValue); - } - if (isIntSubType.test(PredefinedTypes.TYPE_INT_UNSIGNED_8)) { - return anyToUnsigned8(inputValue); - } - return anyToIntCast(inputValue, () -> - ErrorUtils.createTypeCastError(inputValue, PredefinedTypes.TYPE_INT)); - } - public static Object castValues(Type targetType, Object inputValue) { - return castValuesInner(SemType.tryInto(targetType), inputValue, - () -> ErrorUtils.createTypeCastError(inputValue, targetType)); - } - - static Object castValuesInner(SemType targetType, Object inputValue, Supplier errorSupplier) { - Context cx = TypeChecker.context(); - if (Core.isSubType(cx, targetType, Builder.getIntType())) { - return castValueToInt(targetType, inputValue); - } - if (Core.isSubType(cx, targetType, Builder.getDecimalType())) { - return anyToDecimalCast(inputValue, () -> + return switch (targetType.getTag()) { + case TypeTags.SIGNED32_INT_TAG -> anyToSigned32(inputValue); + case TypeTags.SIGNED16_INT_TAG -> anyToSigned16(inputValue); + case TypeTags.SIGNED8_INT_TAG -> anyToSigned8(inputValue); + case TypeTags.UNSIGNED32_INT_TAG -> anyToUnsigned32(inputValue); + case TypeTags.UNSIGNED16_INT_TAG -> anyToUnsigned16(inputValue); + case TypeTags.UNSIGNED8_INT_TAG -> anyToUnsigned8(inputValue); + case TypeTags.INT_TAG -> anyToIntCast(inputValue, () -> + ErrorUtils.createTypeCastError(inputValue, PredefinedTypes.TYPE_INT)); + case TypeTags.DECIMAL_TAG -> anyToDecimalCast(inputValue, () -> ErrorUtils.createTypeCastError(inputValue, PredefinedTypes.TYPE_DECIMAL)); - } - if (Core.isSubType(cx, targetType, Builder.getFloatType())) { - return anyToFloatCast(inputValue, () -> + case TypeTags.FLOAT_TAG -> anyToFloatCast(inputValue, () -> ErrorUtils.createTypeCastError(inputValue, PredefinedTypes.TYPE_FLOAT)); - } - if (Core.isSubType(cx, targetType, Builder.getStringType())) { - return anyToStringCast(inputValue, () -> + case TypeTags.STRING_TAG -> anyToStringCast(inputValue, () -> ErrorUtils.createTypeCastError(inputValue, PredefinedTypes.TYPE_STRING)); - } - if (Core.isSubType(cx, targetType, Builder.getBooleanType())) { - return anyToBooleanCast(inputValue, () -> + case TypeTags.BOOLEAN_TAG -> anyToBooleanCast(inputValue, () -> ErrorUtils.createTypeCastError(inputValue, PredefinedTypes.TYPE_BOOLEAN)); - } - throw errorSupplier.get(); + case TypeTags.BYTE_TAG -> anyToByteCast(inputValue, () -> + ErrorUtils.createTypeCastError(inputValue, PredefinedTypes.TYPE_BYTE)); + default -> throw ErrorUtils.createTypeCastError(inputValue, targetType); + }; } static boolean isConvertibleToByte(Object value) { @@ -308,7 +266,7 @@ public static Type getConvertibleType(Object inputValue, Type targetType, String } break; case TypeTags.MAP_TAG: - if (isConvertibleToMapType(inputValue, (MapType) targetType, unresolvedValues, varName, errors, + if (isConvertibleToMapType(inputValue, (BMapType) targetType, unresolvedValues, varName, errors, allowNumericConversion)) { return targetType; } @@ -427,7 +385,7 @@ public static Type getConvertibleFiniteType(Object inputValue, BFiniteType targe // only the first matching type is returned. if (targetFiniteType.valueSpace.size() == 1) { Type valueType = getType(targetFiniteType.valueSpace.iterator().next()); - if (!belongToSingleBasicTypeOrString(valueType) && valueType.getTag() != TypeTags.NULL_TAG) { + if (!isSimpleBasicType(valueType) && valueType.getTag() != TypeTags.NULL_TAG) { return getConvertibleType(inputValue, valueType, varName, unresolvedValues, errors, allowNumericConversion); } @@ -541,7 +499,7 @@ static String getShortSourceValue(Object sourceValue) { return "()"; } String sourceValueName = sourceValue.toString(); - if (TypeChecker.checkIsType(sourceValue, TYPE_STRING)) { + if (TypeChecker.getType(sourceValue) == TYPE_STRING) { sourceValueName = "\"" + sourceValueName + "\""; } if (sourceValueName.length() > MAX_DISPLAYED_SOURCE_VALUE_LENGTH) { @@ -619,7 +577,7 @@ private static boolean isConvertibleToTableType(Object sourceValue, BTableType t } } - private static boolean isConvertibleToMapType(Object sourceValue, MapType targetType, + private static boolean isConvertibleToMapType(Object sourceValue, BMapType targetType, Set unresolvedValues, String varName, List errors, boolean allowNumericConversion) { if (!(sourceValue instanceof MapValueImpl)) { diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/json/JsonInternalUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/json/JsonInternalUtils.java index e77b4b4aa9fb..0fe77bbde9da 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/json/JsonInternalUtils.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/json/JsonInternalUtils.java @@ -43,6 +43,7 @@ import io.ballerina.runtime.internal.types.BArrayType; import io.ballerina.runtime.internal.types.BFiniteType; import io.ballerina.runtime.internal.types.BJsonType; +import io.ballerina.runtime.internal.types.BMapType; import io.ballerina.runtime.internal.types.BStructureType; import io.ballerina.runtime.internal.types.BUnionType; import io.ballerina.runtime.internal.values.ArrayValue; @@ -61,7 +62,6 @@ import java.util.Map.Entry; import static io.ballerina.runtime.api.constants.RuntimeConstants.MAP_LANG_LIB; -import static io.ballerina.runtime.internal.TypeChecker.isByteLiteral; import static io.ballerina.runtime.internal.errors.ErrorReasons.INHERENT_TYPE_VIOLATION_ERROR_IDENTIFIER; import static io.ballerina.runtime.internal.errors.ErrorReasons.JSON_OPERATION_ERROR; import static io.ballerina.runtime.internal.errors.ErrorReasons.MAP_KEY_NOT_FOUND_ERROR; @@ -317,8 +317,6 @@ public static Object convertJSON(Object jsonValue, Type targetType) { targetType = TypeUtils.getImpliedType(targetType); Type matchingType; switch (targetType.getTag()) { - case TypeTags.BYTE_TAG: - return jsonNodeToByte(jsonValue); case TypeTags.INT_TAG: return jsonNodeToInt(jsonValue); case TypeTags.FLOAT_TAG: @@ -362,7 +360,7 @@ public static Object convertJSON(Object jsonValue, Type targetType) { case TypeTags.ARRAY_TAG: return convertJSONToBArray(jsonValue, (BArrayType) targetType); case TypeTags.MAP_TAG: - return jsonToMap(jsonValue, (MapType) targetType); + return jsonToMap(jsonValue, (BMapType) targetType); case TypeTags.NULL_TAG: if (jsonValue == null) { return null; @@ -565,30 +563,12 @@ public static BError createJsonConversionError(Throwable throwable, String prefi * @return BInteger value of the JSON, if its a integer or a long JSON node. Error, otherwise. */ private static long jsonNodeToInt(Object json) { - if (!(json instanceof Long || json instanceof Integer)) { + if (!(json instanceof Long l)) { throw ErrorHelper.getRuntimeException(ErrorCodes.INCOMPATIBLE_TYPE_FOR_CASTING_JSON, PredefinedTypes.TYPE_INT, getTypeName(json)); } - return ((Number) json).longValue(); - } - - /** - * Convert to byte. - * - * @param json node to be converted - * @return JSON value as a long, if the value is within byte range. Error, otherwise. - */ - private static long jsonNodeToByte(Object json) { - if (json instanceof Long || json instanceof Integer) { - long x = ((Number) json).longValue(); - if (isByteLiteral(x)) { - return x; - } - } - - throw ErrorHelper.getRuntimeException(ErrorCodes.INCOMPATIBLE_TYPE_FOR_CASTING_JSON, - PredefinedTypes.TYPE_BYTE, getTypeName(json)); + return l; } /** diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BAnyType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BAnyType.java index adb22bc0bdde..feb9d147bf7c 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BAnyType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BAnyType.java @@ -25,10 +25,6 @@ import io.ballerina.runtime.api.types.PredefinedTypes; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.ConcurrentLazySupplier; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.SemType; import io.ballerina.runtime.internal.values.RefValue; import java.util.Optional; @@ -38,7 +34,11 @@ * * @since 0.995.0 */ -public final class BAnyType extends BSemTypeWrapper implements AnyType { +public class BAnyType extends BType implements AnyType { + + private final boolean readonly; + private IntersectionType immutableType; + private IntersectionType intersectionType = null; /** * Create a {@code BAnyType} which represents the any type. @@ -46,98 +46,58 @@ public final class BAnyType extends BSemTypeWrapper imple * @param typeName string name of the type */ public BAnyType(String typeName, Module pkg, boolean readonly) { - super(new ConcurrentLazySupplier<>(() -> new BAnyTypeImpl(typeName, pkg, readonly)), - typeName, pkg, TypeTags.ANY_TAG, pickSemType(readonly)); + super(typeName, pkg, RefValue.class); + this.readonly = readonly; + + if (!readonly) { + BAnyType immutableAnyType = new BAnyType(TypeConstants.READONLY_ANY_TNAME, pkg, true); + this.immutableType = new BIntersectionType(pkg, new Type[]{ this, PredefinedTypes.TYPE_READONLY}, + immutableAnyType, TypeFlags.asMask(TypeFlags.NILABLE), true); + } } @Override - public Optional getIntersectionType() { - return this.getbType().getIntersectionType(); + public V getZeroValue() { + return null; } @Override - public void setIntersectionType(IntersectionType intersectionType) { - this.getbType().setIntersectionType(intersectionType); + public V getEmptyValue() { + return null; } @Override - public Type getReferredType() { - return this.getbType().getReferredType(); + public int getTag() { + return TypeTags.ANY_TAG; } @Override - public IntersectionType getImmutableType() { - return this.getbType().getImmutableType(); + public boolean isNilable() { + return true; } - protected static final class BAnyTypeImpl extends BType implements AnyType { - - private final boolean readonly; - private IntersectionType immutableType; - private IntersectionType intersectionType = null; - - private BAnyTypeImpl(String typeName, Module pkg, boolean readonly) { - super(typeName, pkg, RefValue.class); - this.readonly = readonly; - - if (!readonly) { - BAnyType immutableAnyType = new BAnyType(TypeConstants.READONLY_ANY_TNAME, pkg, true); - this.immutableType = new BIntersectionType(pkg, new Type[]{this, PredefinedTypes.TYPE_READONLY}, - immutableAnyType, TypeFlags.asMask(TypeFlags.NILABLE), true); - } - } - - @Override - public V getZeroValue() { - return null; - } - - @Override - public V getEmptyValue() { - return null; - } - - @Override - public int getTag() { - return TypeTags.ANY_TAG; - } - - public boolean isNilable() { - return true; - } - - @Override - public boolean isReadOnly() { - return this.readonly; - } - - @Override - public IntersectionType getImmutableType() { - return this.immutableType; - } - - @Override - public void setImmutableType(IntersectionType immutableType) { - this.immutableType = immutableType; - } + @Override + public boolean isReadOnly() { + return this.readonly; + } - @Override - public Optional getIntersectionType() { - return this.intersectionType == null ? Optional.empty() : Optional.of(this.intersectionType); - } + @Override + public IntersectionType getImmutableType() { + return this.immutableType; + } - @Override - public void setIntersectionType(IntersectionType intersectionType) { - this.intersectionType = intersectionType; - } + @Override + public void setImmutableType(IntersectionType immutableType) { + this.immutableType = immutableType; + } + @Override + public Optional getIntersectionType() { + return this.intersectionType == null ? Optional.empty() : Optional.of(this.intersectionType); } - private static SemType pickSemType(boolean readonly) { - SemType semType = Builder.getAnyType(); - if (readonly) { - semType = Core.intersect(semType, Builder.getReadonlyType()); - } - return semType; + @Override + public void setIntersectionType(IntersectionType intersectionType) { + this.intersectionType = intersectionType; } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BAnydataType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BAnydataType.java index 71dcdc374f48..0bc38e99f4fb 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BAnydataType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BAnydataType.java @@ -24,9 +24,6 @@ import io.ballerina.runtime.api.types.PredefinedTypes; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.SemType; import io.ballerina.runtime.internal.values.RefValue; /** @@ -89,16 +86,4 @@ public String toString() { } return super.toString(); } - - // TODO: this type don't have mutable parts so this should be a immutable - // semtype. But some things could depend on this being a union type descriptor - // as well (which has to be mutable) - @Override - public SemType createSemType() { - SemType semType = Builder.getAnyDataType(); - if (isReadOnly()) { - semType = Core.intersect(semType, Builder.getReadonlyType()); - } - return semType; - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BArrayType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BArrayType.java index 07834065c87d..a399bcddf71a 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BArrayType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BArrayType.java @@ -22,26 +22,12 @@ import io.ballerina.runtime.api.types.IntersectionType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.ShapeAnalyzer; import io.ballerina.runtime.internal.TypeChecker; -import io.ballerina.runtime.internal.types.semtype.CellAtomicType; -import io.ballerina.runtime.internal.types.semtype.DefinitionContainer; -import io.ballerina.runtime.internal.types.semtype.ListDefinition; -import io.ballerina.runtime.internal.values.AbstractArrayValue; import io.ballerina.runtime.internal.values.ArrayValue; import io.ballerina.runtime.internal.values.ArrayValueImpl; import io.ballerina.runtime.internal.values.ReadOnlyUtils; import java.util.Optional; -import java.util.Set; - -import static io.ballerina.runtime.api.types.semtype.Builder.getNeverType; -import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_LIMITED; -import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_NONE; -import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_UNLIMITED; /** * {@code BArrayType} represents a type of an arrays in Ballerina. @@ -54,9 +40,7 @@ * @since 0.995.0 */ @SuppressWarnings("unchecked") -public class BArrayType extends BType implements ArrayType, TypeWithShape { - - private static final SemType[] EMPTY_SEMTYPE_ARR = new SemType[0]; +public class BArrayType extends BType implements ArrayType { private Type elementType; private int dimensions = 1; private int size = -1; @@ -67,8 +51,6 @@ public class BArrayType extends BType implements ArrayType, TypeWithShape { private IntersectionType immutableType; private IntersectionType intersectionType = null; private int typeFlags; - private final DefinitionContainer defn = new DefinitionContainer<>(); - private final DefinitionContainer acceptedTypeDefn = new DefinitionContainer<>(); public BArrayType(Type elementType) { this(elementType, false); } @@ -103,9 +85,6 @@ public BArrayType(int typeFlags, int size, boolean readonly, boolean hasFillerVa } public void setElementType(Type elementType, int dimensions, boolean elementRO) { - if (this.elementType != null) { - resetSemType(); - } this.elementType = readonly && !elementRO ? ReadOnlyUtils.getReadOnlyType(elementType) : elementType; this.dimensions = dimensions; } @@ -150,7 +129,7 @@ public int hashCode() { @Override public boolean equals(Object obj) { if (obj instanceof BArrayType other) { - if ((other.state == ArrayState.CLOSED || this.state == ArrayState.CLOSED) && this.size != other.size) { + if (other.state == ArrayState.CLOSED && this.size != other.size) { return false; } return this.elementType.equals(other.elementType) && this.readonly == other.readonly; @@ -225,101 +204,4 @@ public Optional getIntersectionType() { public void setIntersectionType(IntersectionType intersectionType) { this.intersectionType = intersectionType; } - - @Override - public SemType createSemType() { - Env env = Env.getInstance(); - if (defn.isDefinitionReady()) { - return defn.getSemType(env); - } - var result = defn.trySetDefinition(ListDefinition::new); - if (!result.updated()) { - return defn.getSemType(env); - } - ListDefinition ld = result.definition(); - CellAtomicType.CellMutability mut = isReadOnly() ? CellAtomicType.CellMutability.CELL_MUT_NONE : - CellAtomicType.CellMutability.CELL_MUT_LIMITED; - return getSemTypePart(env, ld, size, tryInto(getElementType()), mut); - } - - private SemType getSemTypePart(Env env, ListDefinition defn, int size, SemType elementType, - CellAtomicType.CellMutability mut) { - if (size == -1) { - return defn.defineListTypeWrapped(env, EMPTY_SEMTYPE_ARR, 0, elementType, mut); - } else { - SemType[] initial = {elementType}; - return defn.defineListTypeWrapped(env, initial, size, getNeverType(), mut); - } - } - - @Override - public void resetSemType() { - defn.clear(); - super.resetSemType(); - } - - @Override - protected boolean isDependentlyTypedInner(Set visited) { - return elementType instanceof MayBeDependentType eType && eType.isDependentlyTyped(visited); - } - - @Override - public Optional inherentTypeOf(Context cx, ShapeSupplier shapeSupplier, Object object) { - if (!couldInherentTypeBeDifferent()) { - return Optional.of(getSemType()); - } - AbstractArrayValue value = (AbstractArrayValue) object; - SemType cachedShape = value.shapeOf(); - if (cachedShape != null) { - return Optional.of(cachedShape); - } - SemType semType = shapeOfInner(cx, shapeSupplier, value); - value.cacheShape(semType); - return Optional.of(semType); - } - - @Override - public boolean couldInherentTypeBeDifferent() { - return isReadOnly(); - } - - @Override - public Optional shapeOf(Context cx, ShapeSupplier shapeSupplier, Object object) { - return Optional.of(shapeOfInner(cx, shapeSupplier, (AbstractArrayValue) object)); - } - - @Override - public Optional acceptedTypeOf(Context cx) { - Env env = cx.env; - if (acceptedTypeDefn.isDefinitionReady()) { - return Optional.of(acceptedTypeDefn.getSemType(cx.env)); - } - var result = acceptedTypeDefn.trySetDefinition(ListDefinition::new); - if (!result.updated()) { - return Optional.of(acceptedTypeDefn.getSemType(env)); - } - ListDefinition ld = result.definition(); - SemType elementType = ShapeAnalyzer.acceptedTypeOf(cx, getElementType()).orElseThrow(); - return Optional.of(getSemTypePart(env, ld, size, elementType, CELL_MUT_UNLIMITED)); - } - - private SemType shapeOfInner(Context cx, ShapeSupplier shapeSupplier, AbstractArrayValue value) { - ListDefinition readonlyShapeDefinition = value.getReadonlyShapeDefinition(); - if (readonlyShapeDefinition != null) { - return readonlyShapeDefinition.getSemType(cx.env); - } - int size = value.size(); - SemType[] memberTypes = new SemType[size]; - ListDefinition ld = new ListDefinition(); - value.setReadonlyShapeDefinition(ld); - for (int i = 0; i < size; i++) { - Optional memberType = shapeSupplier.get(cx, value.get(i)); - assert memberType.isPresent(); - memberTypes[i] = memberType.get(); - } - CellAtomicType.CellMutability mut = isReadOnly() ? CELL_MUT_NONE : CELL_MUT_LIMITED; - SemType semType = ld.defineListTypeWrapped(cx.env, memberTypes, memberTypes.length, getNeverType(), mut); - value.resetReadonlyShapeDefinition(); - return semType; - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BBooleanType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BBooleanType.java index f5a6c275ccda..6fd5b0afb07d 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BBooleanType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BBooleanType.java @@ -18,29 +18,15 @@ package io.ballerina.runtime.internal.types; import io.ballerina.runtime.api.Module; -import io.ballerina.runtime.api.constants.TypeConstants; import io.ballerina.runtime.api.types.BooleanType; -import io.ballerina.runtime.api.types.PredefinedTypes; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.ConcurrentLazySupplier; -import io.ballerina.runtime.api.types.semtype.SemType; - -import java.util.function.Supplier; /** * {@code BBooleanType} represents boolean type in Ballerina. * * @since 0.995.0 */ -public final class BBooleanType extends BSemTypeWrapper implements BooleanType { - - private static final BBooleanType TRUE = - new BBooleanType(() -> new BBooleanTypeImpl(TypeConstants.BOOLEAN_TNAME, PredefinedTypes.EMPTY_MODULE), - TypeConstants.BOOLEAN_TNAME, PredefinedTypes.EMPTY_MODULE, Builder.getBooleanConst(true)); - private static final BBooleanType FALSE = - new BBooleanType(() -> new BBooleanTypeImpl(TypeConstants.BOOLEAN_TNAME, PredefinedTypes.EMPTY_MODULE), - TypeConstants.BOOLEAN_TNAME, PredefinedTypes.EMPTY_MODULE, Builder.getBooleanConst(false)); +public class BBooleanType extends BType implements BooleanType { /** * Create a {@code BBooleanType} which represents the boolean type. @@ -48,43 +34,28 @@ public final class BBooleanType extends BSemTypeWrapper new BBooleanTypeImpl(typeName, pkg), typeName, pkg, Builder.getBooleanType()); + super(typeName, pkg, Boolean.class); } - public static BBooleanType singletonType(boolean value) { - return value ? TRUE : FALSE; + @Override + @SuppressWarnings("unchecked") + public V getZeroValue() { + return (V) Boolean.FALSE; } - private BBooleanType(Supplier bTypeSupplier, String typeName, Module pkg, SemType semType) { - super(new ConcurrentLazySupplier<>(bTypeSupplier), typeName, pkg, TypeTags.BOOLEAN_TAG, semType); + @SuppressWarnings("unchecked") + @Override + public V getEmptyValue() { + return (V) Boolean.FALSE; } - protected static final class BBooleanTypeImpl extends BType implements BooleanType { - - private BBooleanTypeImpl(String typeName, Module pkg) { - super(typeName, pkg, Boolean.class); - } - - @Override - @SuppressWarnings("unchecked") - public V getZeroValue() { - return (V) Boolean.FALSE; - } - - @SuppressWarnings("unchecked") - @Override - public V getEmptyValue() { - return (V) Boolean.FALSE; - } - - @Override - public int getTag() { - return TypeTags.BOOLEAN_TAG; - } + @Override + public int getTag() { + return TypeTags.BOOLEAN_TAG; + } - @Override - public boolean isReadOnly() { - return true; - } + @Override + public boolean isReadOnly() { + return true; } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BByteType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BByteType.java index d69b43dc9b8d..97aca3f82894 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BByteType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BByteType.java @@ -19,26 +19,15 @@ package io.ballerina.runtime.internal.types; import io.ballerina.runtime.api.Module; -import io.ballerina.runtime.api.constants.TypeConstants; import io.ballerina.runtime.api.types.ByteType; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.ConcurrentLazySupplier; -import io.ballerina.runtime.api.types.semtype.SemType; - -import java.util.function.Supplier; - -import static io.ballerina.runtime.api.constants.RuntimeConstants.UNSIGNED8_MAX_VALUE; -import static io.ballerina.runtime.api.types.PredefinedTypes.EMPTY_MODULE; /** * {@code BByteType} represents byte type in Ballerina. * * @since 0.995.0 */ -public final class BByteType extends BSemTypeWrapper implements ByteType { - - private static final BByteTypeImpl DEFAULT_B_TYPE = new BByteTypeImpl(TypeConstants.BYTE_TNAME, EMPTY_MODULE); +public class BByteType extends BType implements ByteType { /** * Create a {@code BByteType} which represents the byte type. @@ -46,50 +35,28 @@ public final class BByteType extends BSemTypeWrapper im * @param typeName string name of the type */ public BByteType(String typeName, Module pkg) { - this(() -> new BByteTypeImpl(typeName, pkg), typeName, EMPTY_MODULE, - Builder.createIntRange(0, UNSIGNED8_MAX_VALUE)); + super(typeName, pkg, Integer.class); } - private BByteType(Supplier bTypeSupplier, String typeName, Module pkg, SemType semType) { - super(new ConcurrentLazySupplier<>(bTypeSupplier), typeName, pkg, TypeTags.BYTE_TAG, semType); + @Override + @SuppressWarnings("unchecked") + public V getZeroValue() { + return (V) new Integer(0); } - public static BByteType singletonType(long value) { - return new BByteType(() -> (BByteTypeImpl) DEFAULT_B_TYPE.clone(), TypeConstants.BYTE_TNAME, EMPTY_MODULE, - Builder.getIntConst(value)); + @Override + @SuppressWarnings("unchecked") + public V getEmptyValue() { + return (V) new Integer(0); } - protected static final class BByteTypeImpl extends BType implements ByteType, Cloneable { - - private BByteTypeImpl(String typeName, Module pkg) { - super(typeName, pkg, Integer.class); - } - - @Override - @SuppressWarnings("unchecked") - public V getZeroValue() { - return (V) new Integer(0); - } - - @Override - @SuppressWarnings("unchecked") - public V getEmptyValue() { - return (V) new Integer(0); - } - - @Override - public int getTag() { - return TypeTags.BYTE_TAG; - } - - @Override - public boolean isReadOnly() { - return true; - } + @Override + public int getTag() { + return TypeTags.BYTE_TAG; + } - @Override - public BType clone() { - return super.clone(); - } + @Override + public boolean isReadOnly() { + return true; } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BDecimalType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BDecimalType.java index 441da73583d2..d1bf252d0f0b 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BDecimalType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BDecimalType.java @@ -19,18 +19,11 @@ package io.ballerina.runtime.internal.types; import io.ballerina.runtime.api.Module; -import io.ballerina.runtime.api.constants.TypeConstants; import io.ballerina.runtime.api.types.DecimalType; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.ConcurrentLazySupplier; -import io.ballerina.runtime.api.types.semtype.SemType; import io.ballerina.runtime.internal.values.DecimalValue; import java.math.BigDecimal; -import java.util.function.Supplier; - -import static io.ballerina.runtime.api.types.PredefinedTypes.EMPTY_MODULE; /** * {@code BDecimalType} represents decimal type in Ballerina. @@ -38,10 +31,7 @@ * * @since 0.995.0 */ -public final class BDecimalType extends BSemTypeWrapper implements DecimalType { - - private static final BDecimalTypeImpl DEFAULT_B_TYPE = - new BDecimalTypeImpl(TypeConstants.DECIMAL_TNAME, EMPTY_MODULE); +public class BDecimalType extends BType implements DecimalType { /** * Create a {@code BDecimalType} which represents the decimal type. @@ -49,49 +39,28 @@ public final class BDecimalType extends BSemTypeWrapper new BDecimalTypeImpl(typeName, pkg), typeName, pkg, Builder.getDecimalType()); + super(typeName, pkg, DecimalValue.class); } - public static BDecimalType singletonType(BigDecimal value) { - return new BDecimalType(() -> (BDecimalTypeImpl) DEFAULT_B_TYPE.clone(), TypeConstants.DECIMAL_TNAME, - EMPTY_MODULE, Builder.getDecimalConst(value)); + @Override + @SuppressWarnings("unchecked") + public V getZeroValue() { + return (V) new DecimalValue(BigDecimal.ZERO); } - private BDecimalType(Supplier bType, String typeName, Module pkg, SemType semType) { - super(new ConcurrentLazySupplier<>(bType), typeName, pkg, TypeTags.DECIMAL_TAG, semType); + @Override + @SuppressWarnings("unchecked") + public V getEmptyValue() { + return (V) new DecimalValue(BigDecimal.ZERO); } - protected static final class BDecimalTypeImpl extends BType implements DecimalType, Cloneable { - - private BDecimalTypeImpl(String typeName, Module pkg) { - super(typeName, pkg, DecimalValue.class); - } - - @Override - @SuppressWarnings("unchecked") - public V getZeroValue() { - return (V) new DecimalValue(BigDecimal.ZERO); - } - - @Override - @SuppressWarnings("unchecked") - public V getEmptyValue() { - return (V) new DecimalValue(BigDecimal.ZERO); - } - - @Override - public int getTag() { - return TypeTags.DECIMAL_TAG; - } - - @Override - public boolean isReadOnly() { - return true; - } + @Override + public int getTag() { + return TypeTags.DECIMAL_TAG; + } - @Override - public BType clone() { - return super.clone(); - } + @Override + public boolean isReadOnly() { + return true; } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BErrorType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BErrorType.java index 44e8d987ccbf..8c1002def149 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BErrorType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BErrorType.java @@ -24,30 +24,20 @@ import io.ballerina.runtime.api.types.PredefinedTypes; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.values.BError; -import io.ballerina.runtime.internal.TypeChecker; -import io.ballerina.runtime.internal.types.semtype.ErrorUtils; import io.ballerina.runtime.internal.values.ErrorValue; -import io.ballerina.runtime.internal.values.MapValueImpl; import java.util.Optional; -import java.util.Set; /** * {@code BErrorType} represents error type in Ballerina. * * @since 0.995.0 */ -public class BErrorType extends BAnnotatableType implements ErrorType, TypeWithShape { +public class BErrorType extends BAnnotatableType implements ErrorType { - public Type detailType = PredefinedTypes.TYPE_DETAIL; + public Type detailType = PredefinedTypes.TYPE_ERROR_DETAIL; public BTypeIdSet typeIdSet; private IntersectionType intersectionType = null; - private volatile DistinctIdSupplier distinctIdSupplier; public BErrorType(String typeName, Module pkg, Type detailType) { super(typeName, pkg, ErrorValue.class); @@ -60,9 +50,6 @@ public BErrorType(String typeName, Module pkg) { public void setTypeIdSet(BTypeIdSet typeIdSet) { this.typeIdSet = typeIdSet; - synchronized (this) { - this.distinctIdSupplier = null; - } } @Override @@ -126,76 +113,4 @@ public Optional getIntersectionType() { public void setIntersectionType(IntersectionType intersectionType) { this.intersectionType = intersectionType; } - - @Override - public SemType createSemType() { - SemType err; - if (detailType == null || isTopType()) { - err = Builder.getErrorType(); - } else { - err = ErrorUtils.errorDetail(tryInto(getDetailType())); - } - - initializeDistinctIdSupplierIfNeeded(); - return distinctIdSupplier.get().stream().map(ErrorUtils::errorDistinct).reduce(err, Core::intersect); - } - - private void initializeDistinctIdSupplierIfNeeded() { - if (distinctIdSupplier == null) { - synchronized (this) { - if (distinctIdSupplier == null) { - distinctIdSupplier = new DistinctIdSupplier(TypeChecker.context().env, getTypeIdSet()); - } - } - } - } - - @Override - protected boolean isDependentlyTypedInner(Set visited) { - return detailType instanceof MayBeDependentType mayBeDependentType && - mayBeDependentType.isDependentlyTyped(visited); - } - - private boolean isTopType() { - return detailType == PredefinedTypes.TYPE_DETAIL; - } - - @Override - public Optional inherentTypeOf(Context cx, ShapeSupplier shapeSupplier, Object object) { - if (!couldInherentTypeBeDifferent()) { - return Optional.of(getSemType()); - } - BError errorValue = (BError) object; - Object details = errorValue.getDetails(); - if (!(details instanceof MapValueImpl errorDetails)) { - return Optional.empty(); - } - initializeDistinctIdSupplierIfNeeded(); - // Should we actually pass the readonly shape supplier here? - return BMapType.shapeOfInner(cx, shapeSupplier, errorDetails) - .map(ErrorUtils::errorDetail) - .map(err -> distinctIdSupplier.get().stream().map(ErrorUtils::errorDistinct) - .reduce(err, Core::intersect)); - } - - @Override - public Optional shapeOf(Context cx, ShapeSupplier shapeSupplierFn, Object object) { - BError errorValue = (BError) object; - Object details = errorValue.getDetails(); - if (!(details instanceof MapValueImpl errorDetails)) { - return Optional.empty(); - } - return BMapType.shapeOfInner(cx, shapeSupplierFn, errorDetails).map(ErrorUtils::errorDetail); - } - - @Override - public Optional acceptedTypeOf(Context cx) { - return Optional.of(getSemType()); - } - - @Override - public boolean couldInherentTypeBeDifferent() { - // TODO: consider properly handling this - return true; - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BFiniteType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BFiniteType.java index bcef259ed050..de03a587aa95 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BFiniteType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BFiniteType.java @@ -21,17 +21,11 @@ import io.ballerina.runtime.api.flags.TypeFlags; import io.ballerina.runtime.api.types.FiniteType; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.ShapeAnalyzer; import io.ballerina.runtime.internal.TypeChecker; import io.ballerina.runtime.internal.values.RefValue; import java.util.Iterator; import java.util.LinkedHashSet; -import java.util.Optional; import java.util.Set; import java.util.StringJoiner; @@ -45,8 +39,8 @@ public class BFiniteType extends BType implements FiniteType { public Set valueSpace; - private int typeFlags; - private String originalName; + private final int typeFlags; + private final String originalName; public BFiniteType(String typeName) { this(typeName, new LinkedHashSet<>(), 0); @@ -193,27 +187,6 @@ public boolean equals(Object o) { if (!(o instanceof BFiniteType that)) { return false; } - if (this.valueSpace.size() != that.valueSpace.size()) { - return false; - } - for (var each : this.valueSpace) { - try { - if (!that.valueSpace.contains(each)) { - return false; - } - } catch (NullPointerException ex) { - // If one of the sets is an immutable collection this can happen - return false; - } - } - return true; - } - - @Override - public SemType createSemType() { - Context cx = TypeChecker.context(); - return this.valueSpace.stream().map(each -> ShapeAnalyzer.inherentTypeOf(cx, each)) - .map(Optional::orElseThrow) - .reduce(Builder.getNeverType(), Core::union); + return this.valueSpace.size() == that.valueSpace.size() && this.valueSpace.containsAll(that.valueSpace); } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BFloatType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BFloatType.java index 7d5aab69a070..50450df52beb 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BFloatType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BFloatType.java @@ -18,16 +18,8 @@ package io.ballerina.runtime.internal.types; import io.ballerina.runtime.api.Module; -import io.ballerina.runtime.api.constants.TypeConstants; import io.ballerina.runtime.api.types.FloatType; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.ConcurrentLazySupplier; -import io.ballerina.runtime.api.types.semtype.SemType; - -import java.util.function.Supplier; - -import static io.ballerina.runtime.api.types.PredefinedTypes.EMPTY_MODULE; /** * {@code BFloatType} represents a integer which is a 32-bit floating-point number according to the @@ -36,7 +28,7 @@ * @since 0.995.0 */ @SuppressWarnings("unchecked") -public final class BFloatType extends BSemTypeWrapper implements FloatType { +public class BFloatType extends BType implements FloatType { /** * Create a {@code BFloatType} which represents the boolean type. @@ -44,42 +36,26 @@ public final class BFloatType extends BSemTypeWrapper * @param typeName string name of the type */ public BFloatType(String typeName, Module pkg) { - this(() -> new BFloatTypeImpl(typeName, pkg), typeName, pkg, Builder.getFloatType()); + super(typeName, pkg, Double.class); } - private BFloatType(Supplier bType, String typeName, Module pkg, SemType semType) { - super(new ConcurrentLazySupplier<>(bType), typeName, pkg, TypeTags.FLOAT_TAG, semType); + @Override + public V getZeroValue() { + return (V) new Double(0); } - - public static BFloatType singletonType(Double value) { - return new BFloatType(() -> new BFloatTypeImpl(TypeConstants.FLOAT_TNAME, EMPTY_MODULE), - TypeConstants.FLOAT_TNAME, EMPTY_MODULE, Builder.getFloatConst(value)); + + @Override + public V getEmptyValue() { + return (V) new Double(0); } - protected static final class BFloatTypeImpl extends BType implements FloatType { - - private BFloatTypeImpl(String typeName, Module pkg) { - super(typeName, pkg, Double.class); - } - - @Override - public V getZeroValue() { - return (V) new Double(0); - } - - @Override - public V getEmptyValue() { - return (V) new Double(0); - } - - @Override - public int getTag() { - return TypeTags.FLOAT_TAG; - } + @Override + public int getTag() { + return TypeTags.FLOAT_TAG; + } - @Override - public boolean isReadOnly() { - return true; - } + @Override + public boolean isReadOnly() { + return true; } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BFunctionType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BFunctionType.java index ecc2a44c1f98..dbef43081922 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BFunctionType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BFunctionType.java @@ -25,18 +25,8 @@ import io.ballerina.runtime.api.types.PredefinedTypes; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.internal.types.semtype.CellAtomicType; -import io.ballerina.runtime.internal.types.semtype.DefinitionContainer; -import io.ballerina.runtime.internal.types.semtype.FunctionDefinition; -import io.ballerina.runtime.internal.types.semtype.FunctionQualifiers; -import io.ballerina.runtime.internal.types.semtype.ListDefinition; import java.util.Arrays; -import java.util.Objects; -import java.util.Set; /** * {@code {@link BFunctionType }} represents a function type in ballerina. @@ -49,10 +39,6 @@ public class BFunctionType extends BAnnotatableType implements FunctionType { public Type retType; public long flags; public Parameter[] parameters; - private static final Env env = Env.getInstance(); - private static final SemType ISOLATED_TOP = createIsolatedTop(env); - - private final DefinitionContainer defn = new DefinitionContainer<>(); public BFunctionType(Module pkg) { super("function ()", pkg, Object.class); @@ -134,14 +120,31 @@ public boolean equals(Object o) { return false; } - if (this.flags != that.flags) { + boolean isSourceAnyFunction = SymbolFlags.isFlagOn(this.flags, SymbolFlags.ANY_FUNCTION); + boolean isTargetAnyFunction = SymbolFlags.isFlagOn(that.flags, SymbolFlags.ANY_FUNCTION); + + if (isSourceAnyFunction && isTargetAnyFunction) { + return true; + } + + if (isSourceAnyFunction != isTargetAnyFunction) { + return false; + } + + if (SymbolFlags.isFlagOn(that.flags, SymbolFlags.ISOLATED) != SymbolFlags + .isFlagOn(this.flags, SymbolFlags.ISOLATED)) { + return false; + } + + if (SymbolFlags.isFlagOn(that.flags, SymbolFlags.TRANSACTIONAL) != SymbolFlags + .isFlagOn(this.flags, SymbolFlags.TRANSACTIONAL)) { return false; } if (!Arrays.equals(parameters, that.parameters)) { return false; } - return Objects.equals(retType, that.retType) && Objects.equals(restType, that.restType); + return retType.equals(that.retType); } @Override @@ -215,96 +218,4 @@ public Type getReturnType() { public long getFlags() { return flags; } - - private static SemType createIsolatedTop(Env env) { - FunctionDefinition fd = new FunctionDefinition(); - SemType ret = Builder.getValType(); - return fd.define(env, Builder.getNeverType(), ret, FunctionQualifiers.create(true, false)); - } - - @Override - public SemType createSemType() { - if (isFunctionTop()) { - return getTopType(); - } - if (defn.isDefinitionReady()) { - return defn.getSemType(env); - } - var result = defn.trySetDefinition(FunctionDefinition::new); - if (!result.updated()) { - return defn.getSemType(env); - } - FunctionDefinition fd = result.definition(); - SemType[] params = new SemType[parameters.length]; - for (int i = 0; i < parameters.length; i++) { - params[i] = getSemType(parameters[i].type); - } - SemType rest; - if (restType instanceof BArrayType arrayType) { - rest = getSemType(arrayType.getElementType()); - } else { - rest = Builder.getNeverType(); - } - - SemType returnType = resolveReturnType(); - ListDefinition paramListDefinition = new ListDefinition(); - SemType paramType = paramListDefinition.defineListTypeWrapped(env, params, params.length, rest, - CellAtomicType.CellMutability.CELL_MUT_NONE); - return fd.define(env, paramType, returnType, getQualifiers()); - } - - private SemType getTopType() { - if (SymbolFlags.isFlagOn(flags, SymbolFlags.ISOLATED)) { - return ISOLATED_TOP; - } - return Builder.getFunctionType(); - } - - FunctionQualifiers getQualifiers() { - return FunctionQualifiers.create(SymbolFlags.isFlagOn(flags, SymbolFlags.ISOLATED), - SymbolFlags.isFlagOn(flags, SymbolFlags.TRANSACTIONAL)); - } - - private SemType getSemType(Type type) { - return tryInto(type); - } - - private boolean isFunctionTop() { - return parameters == null && restType == null && retType == null; - } - - @Override - public synchronized void resetSemType() { - defn.clear(); - super.resetSemType(); - } - - @Override - protected boolean isDependentlyTypedInner(Set visited) { - return (restType instanceof BType rest && rest.isDependentlyTyped(visited)) || - (retType instanceof BType ret && ret.isDependentlyTyped(visited)) || - isDependentlyTypeParameters(visited); - } - - private boolean isDependentlyTypeParameters(Set visited) { - if (parameters == null) { - return false; - } - return Arrays.stream(parameters).map(each -> each.type).filter(each -> each instanceof MayBeDependentType) - .anyMatch(each -> ((MayBeDependentType) each).isDependentlyTyped(visited)); - } - - private SemType resolveReturnType() { - if (retType == null) { - return Builder.getNilType(); - } - MayBeDependentType retBType = (MayBeDependentType) retType; - SemType returnType = getSemType(retType); - ListDefinition ld = new ListDefinition(); - SemType dependentlyTypedBit = - retBType.isDependentlyTyped() ? Builder.getBooleanConst(true) : Builder.getBooleanType(); - SemType[] innerType = new SemType[]{dependentlyTypedBit, returnType}; - return ld.defineListTypeWrapped(env, innerType, 2, Builder.getNeverType(), - CellAtomicType.CellMutability.CELL_MUT_NONE); - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BFutureType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BFutureType.java index 8839a92922fe..3eb490648562 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BFutureType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BFutureType.java @@ -22,13 +22,7 @@ import io.ballerina.runtime.api.types.FutureType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.SemType; import io.ballerina.runtime.internal.TypeChecker; -import io.ballerina.runtime.internal.types.semtype.FutureUtils; - -import java.util.Objects; -import java.util.Set; /** * {@code BFutureType} represents a future value in Ballerina. @@ -37,7 +31,7 @@ */ public class BFutureType extends BType implements FutureType { - private final Type constraint; + private Type constraint; /** * Create a {@code {@link BFutureType}} which represents the future value. @@ -47,7 +41,6 @@ public class BFutureType extends BType implements FutureType { */ public BFutureType(String typeName, Module pkg) { super(typeName, pkg, Object.class); - constraint = null; } public BFutureType(Type constraint) { @@ -88,7 +81,8 @@ public boolean equals(Object obj) { if (constraint == other.constraint) { return true; } - return Objects.equals(constraint, other.constraint); + + return TypeChecker.checkIsType(constraint, other.constraint); } @Override @@ -99,17 +93,4 @@ public String toString() { private String getConstraintString() { return constraint != null ? "<" + constraint + ">" : ""; } - - @Override - public SemType createSemType() { - if (constraint == null) { - return Builder.getFutureType(); - } - return FutureUtils.futureContaining(TypeChecker.context().env, tryInto(constraint)); - } - - @Override - protected boolean isDependentlyTypedInner(Set visited) { - return constraint instanceof MayBeDependentType constraintType && constraintType.isDependentlyTyped(visited); - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BHandleType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BHandleType.java index 9bd32efe9577..ed1065c1df9e 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BHandleType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BHandleType.java @@ -18,68 +18,44 @@ package io.ballerina.runtime.internal.types; import io.ballerina.runtime.api.Module; -import io.ballerina.runtime.api.constants.TypeConstants; import io.ballerina.runtime.api.types.HandleType; -import io.ballerina.runtime.api.types.PredefinedTypes; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.ConcurrentLazySupplier; import io.ballerina.runtime.internal.values.RefValue; /** - * {@code BHandleType} represents a handle type in Ballerina. A handle value is a reference to a storage managed - * externally by a Ballerina program. + * {@code BHandleType} represents a handle type in Ballerina. + * A handle value is a reference to a storage managed externally by a Ballerina program. * * @since 1.0.0 */ -public final class BHandleType extends BSemTypeWrapper implements HandleType { +public class BHandleType extends BType implements HandleType { /** - * Create a {@code BHandleType} which represents the handle type. + * Create a {@code BAnyType} which represents the any type. * * @param typeName string name of the type */ public BHandleType(String typeName, Module pkg) { - super(new ConcurrentLazySupplier<> - (() -> BHandleTypeImpl.create(typeName, pkg)), typeName, pkg, TypeTags.HANDLE_TAG, - Builder.getHandleType()); + super(typeName, pkg, RefValue.class); } - protected static final class BHandleTypeImpl extends BType implements HandleType { - - private static final BHandleTypeImpl DEFAULT = - new BHandleTypeImpl(TypeConstants.HANDLE_TNAME, PredefinedTypes.EMPTY_MODULE); - - private static BHandleTypeImpl create(String typeName, Module pkg) { - if (typeName.equals(TypeConstants.HANDLE_TNAME) && pkg == PredefinedTypes.EMPTY_MODULE) { - return DEFAULT; - } - return new BHandleTypeImpl(typeName, pkg); - } - - private BHandleTypeImpl(String typeName, Module pkg) { - super(typeName, pkg, RefValue.class); - } - - @Override - public V getZeroValue() { - return null; - } - - @Override - public V getEmptyValue() { - return null; - } + @Override + public V getZeroValue() { + return null; + } - @Override - public int getTag() { - return TypeTags.HANDLE_TAG; - } + @Override + public V getEmptyValue() { + return null; + } - @Override - public boolean isReadOnly() { - return true; - } + @Override + public int getTag() { + return TypeTags.HANDLE_TAG; + } + @Override + public boolean isReadOnly() { + return true; } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BIntegerType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BIntegerType.java index 0b7053f3c0d0..d8ec02af768b 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BIntegerType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BIntegerType.java @@ -1,42 +1,25 @@ /* - * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ +* Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. licenses this file to you under the Apache License, +* Version 2.0 (the "License"); you may not use this file except +* in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ package io.ballerina.runtime.internal.types; import io.ballerina.runtime.api.Module; -import io.ballerina.runtime.api.constants.TypeConstants; import io.ballerina.runtime.api.types.IntegerType; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.ConcurrentLazySupplier; -import io.ballerina.runtime.api.types.semtype.SemType; - -import java.util.function.Supplier; - -import static io.ballerina.runtime.api.constants.RuntimeConstants.SIGNED16_MAX_VALUE; -import static io.ballerina.runtime.api.constants.RuntimeConstants.SIGNED16_MIN_VALUE; -import static io.ballerina.runtime.api.constants.RuntimeConstants.SIGNED32_MAX_VALUE; -import static io.ballerina.runtime.api.constants.RuntimeConstants.SIGNED32_MIN_VALUE; -import static io.ballerina.runtime.api.constants.RuntimeConstants.SIGNED8_MAX_VALUE; -import static io.ballerina.runtime.api.constants.RuntimeConstants.SIGNED8_MIN_VALUE; -import static io.ballerina.runtime.api.constants.RuntimeConstants.UNSIGNED16_MAX_VALUE; -import static io.ballerina.runtime.api.constants.RuntimeConstants.UNSIGNED32_MAX_VALUE; -import static io.ballerina.runtime.api.constants.RuntimeConstants.UNSIGNED8_MAX_VALUE; -import static io.ballerina.runtime.api.types.PredefinedTypes.EMPTY_MODULE; /** * {@code BIntegerType} represents an integer which is a 32-bit signed number. @@ -44,10 +27,9 @@ * @since 0.995.0 */ @SuppressWarnings("unchecked") -public final class BIntegerType extends BSemTypeWrapper implements IntegerType { +public class BIntegerType extends BType implements IntegerType { - private static final BIntegerTypeImpl DEFAULT_B_TYPE = - new BIntegerTypeImpl(TypeConstants.INT_TNAME, EMPTY_MODULE, TypeTags.INT_TAG); + private final int tag; /** * Create a {@code BIntegerType} which represents the boolean type. @@ -55,89 +37,32 @@ public final class BIntegerType extends BSemTypeWrapper new BIntegerTypeImpl(typeName, pkg, TypeTags.INT_TAG), typeName, pkg, TypeTags.INT_TAG, - Builder.getIntType()); + super(typeName, pkg, Long.class); + tag = TypeTags.INT_TAG; } public BIntegerType(String typeName, Module pkg, int tag) { - this(() -> new BIntegerTypeImpl(typeName, pkg, tag), typeName, pkg, tag, pickSemType(tag)); - } - - private BIntegerType(Supplier bIntegerTypeSupplier, String typeName, Module pkg, int tag, - SemType semType) { - super(new ConcurrentLazySupplier<>(bIntegerTypeSupplier), typeName, pkg, tag, semType); - } - - private static SemType pickSemType(int tag) { - return switch (tag) { - case TypeTags.INT_TAG -> Builder.getIntType(); - case TypeTags.SIGNED8_INT_TAG -> Builder.createIntRange(SIGNED8_MIN_VALUE, SIGNED8_MAX_VALUE); - case TypeTags.SIGNED16_INT_TAG -> Builder.createIntRange(SIGNED16_MIN_VALUE, SIGNED16_MAX_VALUE); - case TypeTags.SIGNED32_INT_TAG -> Builder.createIntRange(SIGNED32_MIN_VALUE, SIGNED32_MAX_VALUE); - case TypeTags.UNSIGNED8_INT_TAG, TypeTags.BYTE_TAG -> Builder.createIntRange(0, UNSIGNED8_MAX_VALUE); - case TypeTags.UNSIGNED16_INT_TAG -> Builder.createIntRange(0, UNSIGNED16_MAX_VALUE); - case TypeTags.UNSIGNED32_INT_TAG -> Builder.createIntRange(0, UNSIGNED32_MAX_VALUE); - default -> throw new UnsupportedOperationException("Unexpected int tag"); - }; + super(typeName, pkg, Long.class); + this.tag = tag; } - public static BIntegerType singletonType(long value) { - if (value >= IntegerTypeCache.CACHE_MIN_VALUE && value <= IntegerTypeCache.CACHE_MAX_VALUE) { - return IntegerTypeCache.cache[(int) value - IntegerTypeCache.CACHE_MIN_VALUE]; - } - return createSingletonType(value); + @Override + public V getZeroValue() { + return (V) new Long(0); } - private static BIntegerType createSingletonType(long value) { - return new BIntegerType(() -> (BIntegerTypeImpl) DEFAULT_B_TYPE.clone(), TypeConstants.INT_TNAME, EMPTY_MODULE, - TypeTags.INT_TAG, Builder.getIntConst(value)); + @Override + public V getEmptyValue() { + return (V) new Long(0); } - protected static final class BIntegerTypeImpl extends BType implements IntegerType, Cloneable { - - private final int tag; - - private BIntegerTypeImpl(String typeName, Module pkg, int tag) { - super(typeName, pkg, Long.class); - this.tag = tag; - } - - @Override - public V getZeroValue() { - return (V) new Long(0); - } - - @Override - public V getEmptyValue() { - return (V) new Long(0); - } - - @Override - public int getTag() { - return tag; - } - - @Override - public boolean isReadOnly() { - return true; - } - - @Override - public BType clone() { - return super.clone(); - } + @Override + public int getTag() { + return tag; } - private static final class IntegerTypeCache { - - private static final BIntegerType[] cache; - private static final int CACHE_MAX_VALUE = 127; - private static final int CACHE_MIN_VALUE = -128; - static { - cache = new BIntegerType[CACHE_MAX_VALUE - CACHE_MIN_VALUE + 1]; - for (int i = CACHE_MIN_VALUE; i <= CACHE_MAX_VALUE; i++) { - cache[i - CACHE_MIN_VALUE] = createSingletonType(i); - } - } + @Override + public boolean isReadOnly() { + return true; } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BIntersectionType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BIntersectionType.java index dc1991feb42c..f9cf98a079df 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BIntersectionType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BIntersectionType.java @@ -24,32 +24,20 @@ import io.ballerina.runtime.api.types.IntersectionType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.ShapeAnalyzer; -import io.ballerina.runtime.internal.TypeChecker; -import io.ballerina.runtime.internal.types.semtype.ErrorUtils; -import io.ballerina.runtime.internal.types.semtype.ObjectDefinition; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Optional; -import java.util.Set; import java.util.StringJoiner; -import java.util.function.Function; - -import static io.ballerina.runtime.api.utils.TypeUtils.getImpliedType; /** * {@code BIntersectionType} represents an intersection type in Ballerina. * * @since 2.0.0 */ -public class BIntersectionType extends BType implements IntersectionType, TypeWithShape { +public class BIntersectionType extends BType implements IntersectionType { private static final String PADDED_AMPERSAND = " & "; private static final String OPENING_PARENTHESIS = "("; @@ -227,71 +215,4 @@ public Optional getIntersectionType() { public void setIntersectionType(IntersectionType intersectionType) { this.intersectionType = intersectionType; } - - @Override - public SemType createSemType() { - return createSemTypeInner(SemType::tryInto); - } - - @Override - protected boolean isDependentlyTypedInner(Set visited) { - return constituentTypes.stream().filter(each -> each instanceof MayBeDependentType) - .anyMatch(type -> ((MayBeDependentType) type).isDependentlyTyped(visited)); - } - - private SemType createSemTypeInner(Function semTypeFunction) { - if (constituentTypes.isEmpty()) { - return Builder.getNeverType(); - } - SemType result = constituentTypes.stream().map(semTypeFunction).reduce(Core::intersect).orElseThrow(); - Optional distinctPart = distinctTypePart(result); - if (distinctPart.isPresent()) { - result = Core.intersect(result, distinctPart.get()); - } - return result; - } - - private Optional distinctTypePart(SemType result) { - if (Core.isSubtypeSimple(result, Builder.getErrorType())) { - BErrorType effectiveErrorType = (BErrorType) getImpliedType(effectiveType); - DistinctIdSupplier distinctIdSupplier = - new DistinctIdSupplier(TypeChecker.context().env, effectiveErrorType.getTypeIdSet()); - return distinctIdSupplier.get().stream().map(ErrorUtils::errorDistinct).reduce(Core::intersect); - } else if (Core.isSubtypeSimple(result, Builder.getObjectType())) { - BObjectType effectiveObjectType = (BObjectType) getImpliedType(effectiveType); - DistinctIdSupplier distinctIdSupplier = - new DistinctIdSupplier(TypeChecker.context().env, effectiveObjectType.getTypeIdSet()); - return distinctIdSupplier.get().stream().map(ObjectDefinition::distinct).reduce(Core::intersect); - } - return Optional.empty(); - } - - @Override - public Optional shapeOf(Context cx, ShapeSupplier shapeSupplierFn, Object object) { - Type effectiveType = getEffectiveType(); - if (effectiveType instanceof TypeWithShape typeWithShape) { - return typeWithShape.shapeOf(cx, shapeSupplierFn, object); - } - return Optional.empty(); - } - - @Override - public Optional acceptedTypeOf(Context cx) { - return Optional.of(createSemTypeInner(type -> ShapeAnalyzer.acceptedTypeOf(cx, type).orElseThrow())); - } - - @Override - public Optional inherentTypeOf(Context cx, ShapeSupplier shapeSupplier, Object object) { - Type effectiveType = getEffectiveType(); - if (effectiveType instanceof TypeWithShape typeWithShape) { - return typeWithShape.inherentTypeOf(cx, shapeSupplier, object); - } - return Optional.empty(); - } - - @Override - public boolean couldInherentTypeBeDifferent() { - return true; - } - } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BMapType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BMapType.java index 43d2058cd4d9..fa47a26e06fc 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BMapType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BMapType.java @@ -24,24 +24,11 @@ import io.ballerina.runtime.api.types.PredefinedTypes; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.ShapeAnalyzer; import io.ballerina.runtime.api.values.BString; -import io.ballerina.runtime.internal.types.semtype.CellAtomicType; -import io.ballerina.runtime.internal.types.semtype.DefinitionContainer; -import io.ballerina.runtime.internal.types.semtype.MappingDefinition; import io.ballerina.runtime.internal.values.MapValueImpl; import io.ballerina.runtime.internal.values.ReadOnlyUtils; -import java.util.Map; import java.util.Optional; -import java.util.Set; - -import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_NONE; -import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_UNLIMITED; /** * {@code BMapType} represents a type of a map in Ballerina. @@ -54,15 +41,12 @@ * @since 0.995.0 */ @SuppressWarnings("unchecked") -public class BMapType extends BType implements MapType, TypeWithShape, Cloneable { +public class BMapType extends BType implements MapType { - public static final MappingDefinition.Field[] EMPTY_FIELD_ARR = new MappingDefinition.Field[0]; private final Type constraint; private final boolean readonly; private IntersectionType immutableType; private IntersectionType intersectionType = null; - private final DefinitionContainer defn = new DefinitionContainer<>(); - private final DefinitionContainer acceptedTypeDefn = new DefinitionContainer<>(); public BMapType(Type constraint) { this(constraint, false); @@ -185,104 +169,4 @@ public void setIntersectionType(IntersectionType intersectionType) { this.intersectionType = intersectionType; } - @Override - public SemType createSemType() { - Env env = Env.getInstance(); - if (defn.isDefinitionReady()) { - return defn.getSemType(env); - } - var result = defn.trySetDefinition(MappingDefinition::new); - if (!result.updated()) { - return defn.getSemType(env); - } - MappingDefinition md = result.definition(); - CellAtomicType.CellMutability mut = isReadOnly() ? CELL_MUT_NONE : - CellAtomicType.CellMutability.CELL_MUT_LIMITED; - return createSemTypeInner(env, md, tryInto(getConstrainedType()), mut); - } - - @Override - public void resetSemType() { - defn.clear(); - super.resetSemType(); - } - - @Override - public Optional inherentTypeOf(Context cx, ShapeSupplier shapeSupplier, Object object) { - if (!couldInherentTypeBeDifferent()) { - return Optional.of(getSemType()); - } - MapValueImpl value = (MapValueImpl) object; - SemType cachedShape = value.shapeOf(); - if (cachedShape != null) { - return Optional.of(cachedShape); - } - - return shapeOfInner(cx, shapeSupplier, value); - } - - @Override - public boolean couldInherentTypeBeDifferent() { - return isReadOnly(); - } - - @Override - public Optional shapeOf(Context cx, ShapeSupplier shapeSupplierFn, Object object) { - return shapeOfInner(cx, shapeSupplierFn, (MapValueImpl) object); - } - - @Override - public synchronized Optional acceptedTypeOf(Context cx) { - Env env = cx.env; - if (acceptedTypeDefn.isDefinitionReady()) { - return Optional.of(acceptedTypeDefn.getSemType(env)); - } - var result = acceptedTypeDefn.trySetDefinition(MappingDefinition::new); - if (!result.updated()) { - return Optional.of(acceptedTypeDefn.getSemType(env)); - } - MappingDefinition md = result.definition(); - SemType elementType = ShapeAnalyzer.acceptedTypeOf(cx, getConstrainedType()).orElseThrow(); - return Optional.of(createSemTypeInner(env, md, elementType, CELL_MUT_UNLIMITED)); - } - - static Optional shapeOfInner(Context cx, ShapeSupplier shapeSupplier, MapValueImpl value) { - MappingDefinition readonlyShapeDefinition = value.getReadonlyShapeDefinition(); - if (readonlyShapeDefinition != null) { - return Optional.of(readonlyShapeDefinition.getSemType(cx.env)); - } - int nFields = value.size(); - MappingDefinition md = new MappingDefinition(); - value.setReadonlyShapeDefinition(md); - MappingDefinition.Field[] fields = new MappingDefinition.Field[nFields]; - Map.Entry[] entries = value.entrySet().toArray(Map.Entry[]::new); - for (int i = 0; i < nFields; i++) { - Optional valueType = shapeSupplier.get(cx, entries[i].getValue()); - SemType fieldType = valueType.orElseThrow(); - fields[i] = new MappingDefinition.Field(entries[i].getKey().toString(), fieldType, true, false); - } - CellAtomicType.CellMutability mut = value.getType().isReadOnly() ? CELL_MUT_NONE : - CellAtomicType.CellMutability.CELL_MUT_LIMITED; - SemType semType = md.defineMappingTypeWrapped(cx.env, fields, Builder.getNeverType(), mut); - value.cacheShape(semType); - value.resetReadonlyShapeDefinition(); - return Optional.of(semType); - } - - private SemType createSemTypeInner(Env env, MappingDefinition defn, SemType restType, - CellAtomicType.CellMutability mut) { - return defn.defineMappingTypeWrapped(env, EMPTY_FIELD_ARR, restType, mut); - } - - @Override - public BMapType clone() { - BMapType clone = (BMapType) super.clone(); - clone.defn.clear(); - return clone; - } - - @Override - protected boolean isDependentlyTypedInner(Set visited) { - return constraint instanceof MayBeDependentType constraintType && constraintType.isDependentlyTyped(visited); - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BMethodType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BMethodType.java index 4332e1a2f49b..46d25842338c 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BMethodType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BMethodType.java @@ -84,8 +84,4 @@ public MethodType duplicate() { public boolean isIsolated() { return SymbolFlags.isFlagOn(flags, SymbolFlags.ISOLATED); } - - public String name() { - return funcName; - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BNetworkObjectType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BNetworkObjectType.java index 5478813f2dc3..c289e0bffd88 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BNetworkObjectType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BNetworkObjectType.java @@ -24,9 +24,6 @@ import io.ballerina.runtime.api.types.ResourceMethodType; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.stream.Stream; /** * {@code BNetworkObjectType} represents a network object in Ballerina. @@ -82,20 +79,4 @@ private RemoteMethodType[] getRemoteMethods(MethodType[] methodTypes) { public ResourceMethodType[] getResourceMethods() { return resourceMethods; } - - @Override - protected Collection allMethods() { - Stream methodStream = Arrays.stream(getMethods()) - .filter(methodType -> !(SymbolFlags.isFlagOn(methodType.getFlags(), SymbolFlags.REMOTE) || - SymbolFlags.isFlagOn(methodType.getFlags(), SymbolFlags.RESOURCE))) - .map(MethodData::fromMethod); - Stream remoteMethodStream = - Arrays.stream(getRemoteMethods()) - .map(MethodData::fromRemoteMethod); - Stream resourceMethodStream = - Arrays.stream(getResourceMethods()) - .map(method -> MethodData.fromResourceMethod( - (BResourceMethodType) method)); - return Stream.concat(methodStream, Stream.concat(remoteMethodStream, resourceMethodStream)).toList(); - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BNeverType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BNeverType.java index 299b860ca917..f57eedcc6dcf 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BNeverType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BNeverType.java @@ -21,25 +21,29 @@ import io.ballerina.runtime.api.constants.TypeConstants; import io.ballerina.runtime.api.types.NeverType; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Builder; /** * {@code BNeverType} represents the type of a {@code Never}. * * @since 2.0.0-preview1 */ -public final class BNeverType extends BNullType implements NeverType { +public class BNeverType extends BNullType implements NeverType { /** * Create a {@code BNeverType} represents the type of a {@code Never}. * * @param pkg package path */ public BNeverType(Module pkg) { - super(TypeConstants.NEVER_TNAME, pkg, Builder.getNeverType(), TypeTags.NEVER_TAG); + super(TypeConstants.NEVER_TNAME, pkg); } @Override public boolean isAnydata() { return true; } + + @Override + public int getTag() { + return TypeTags.NEVER_TAG; + } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BNullType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BNullType.java index 02e846517c71..9070784980fc 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BNullType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BNullType.java @@ -20,18 +20,13 @@ import io.ballerina.runtime.api.Module; import io.ballerina.runtime.api.types.NullType; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.ConcurrentLazySupplier; -import io.ballerina.runtime.api.types.semtype.SemType; - -import java.util.function.Supplier; /** * {@code BNullType} represents the type of a {@code NullLiteral}. * * @since 0.995.0 */ -public sealed class BNullType extends BSemTypeWrapper implements NullType permits BNeverType { +public class BNullType extends BType implements NullType { /** * Create a {@code BNullType} represents the type of a {@code NullLiteral}. @@ -40,47 +35,31 @@ public sealed class BNullType extends BSemTypeWrapper i * @param pkg package path */ public BNullType(String typeName, Module pkg) { - this(() -> new BNullTypeImpl(typeName, pkg), typeName, pkg, TypeTags.NULL_TAG, Builder.getNilType()); + super(typeName, pkg, null); } - protected BNullType(String typeName, Module pkg, SemType semType, int tag) { - this(() -> new BNullTypeImpl(typeName, pkg), typeName, pkg, tag, semType); + @Override + public V getZeroValue() { + return null; } - private BNullType(Supplier bNullTypeSupplier, String typeName, Module pkg, int tag, - SemType semType) { - super(new ConcurrentLazySupplier<>(bNullTypeSupplier), typeName, pkg, tag, semType); + @Override + public V getEmptyValue() { + return null; } - protected static final class BNullTypeImpl extends BType implements NullType { - - private BNullTypeImpl(String typeName, Module pkg) { - super(typeName, pkg, null); - } - - @Override - public V getZeroValue() { - return null; - } - - @Override - public V getEmptyValue() { - return null; - } - - @Override - public int getTag() { - return TypeTags.NULL_TAG; - } + @Override + public int getTag() { + return TypeTags.NULL_TAG; + } - @Override - public boolean isNilable() { - return true; - } + @Override + public boolean isNilable() { + return true; + } - @Override - public boolean isReadOnly() { - return true; - } + @Override + public boolean isReadOnly() { + return true; } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BObjectType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BObjectType.java index 713a96f0d469..05cd15e570fc 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BObjectType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BObjectType.java @@ -22,49 +22,25 @@ import io.ballerina.runtime.api.creators.ErrorCreator; import io.ballerina.runtime.api.flags.SymbolFlags; import io.ballerina.runtime.api.types.Field; -import io.ballerina.runtime.api.types.FunctionType; import io.ballerina.runtime.api.types.IntersectionType; import io.ballerina.runtime.api.types.MethodType; import io.ballerina.runtime.api.types.ObjectType; -import io.ballerina.runtime.api.types.Parameter; import io.ballerina.runtime.api.types.ResourceMethodType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeIdSet; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.ShapeAnalyzer; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.values.BObject; -import io.ballerina.runtime.api.values.BString; -import io.ballerina.runtime.internal.TypeChecker; import io.ballerina.runtime.internal.scheduling.Scheduler; import io.ballerina.runtime.internal.scheduling.Strand; -import io.ballerina.runtime.internal.types.semtype.CellAtomicType; -import io.ballerina.runtime.internal.types.semtype.DefinitionContainer; -import io.ballerina.runtime.internal.types.semtype.FunctionDefinition; -import io.ballerina.runtime.internal.types.semtype.ListDefinition; -import io.ballerina.runtime.internal.types.semtype.Member; -import io.ballerina.runtime.internal.types.semtype.ObjectDefinition; -import io.ballerina.runtime.internal.types.semtype.ObjectQualifiers; import io.ballerina.runtime.internal.utils.ValueUtils; -import io.ballerina.runtime.internal.values.AbstractObjectValue; import java.lang.reflect.Array; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Optional; -import java.util.Set; import java.util.StringJoiner; -import java.util.function.Function; import static io.ballerina.runtime.api.types.TypeTags.SERVICE_TAG; @@ -73,7 +49,7 @@ * * @since 0.995.0 */ -public class BObjectType extends BStructureType implements ObjectType, TypeWithShape { +public class BObjectType extends BStructureType implements ObjectType { private MethodType[] methodTypes; private MethodType initMethod; @@ -86,9 +62,6 @@ public class BObjectType extends BStructureType implements ObjectType, TypeWithS private String cachedToString; private boolean resolving; - private final DefinitionContainer defn = new DefinitionContainer<>(); - private final DefinitionContainer acceptedTypeDefn = new DefinitionContainer<>(); - private volatile DistinctIdSupplier distinctIdSupplier; /** * Create a {@code BObjectType} which represents the user defined struct type. @@ -242,10 +215,6 @@ public void setIntersectionType(IntersectionType intersectionType) { public void setTypeIdSet(BTypeIdSet typeIdSet) { this.typeIdSet = typeIdSet; - synchronized (this) { - this.distinctIdSupplier = null; - } - resetSemType(); } public BObjectType duplicate() { @@ -274,270 +243,6 @@ public boolean hasAnnotations() { @Override public TypeIdSet getTypeIdSet() { - if (typeIdSet == null) { - return new BTypeIdSet(); - } return new BTypeIdSet(new ArrayList<>(typeIdSet.ids)); } - - @Override - public final SemType createSemType() { - Env env = Env.getInstance(); - initializeDistinctIdSupplierIfNeeded(env); - CellAtomicType.CellMutability mut = - SymbolFlags.isFlagOn(getFlags(), SymbolFlags.READONLY) ? CellAtomicType.CellMutability.CELL_MUT_NONE : - CellAtomicType.CellMutability.CELL_MUT_LIMITED; - SemType innerType; - if (defn.isDefinitionReady()) { - innerType = defn.getSemType(env); - } else { - var result = defn.trySetDefinition(ObjectDefinition::new); - if (!result.updated()) { - innerType = defn.getSemType(env); - } else { - ObjectDefinition od = result.definition(); - innerType = semTypeInner(od, mut, SemType::tryInto); - } - } - return distinctIdSupplier.get().stream().map(ObjectDefinition::distinct).reduce(innerType, Core::intersect); - } - - private static boolean skipField(Set seen, String name) { - if (name.startsWith("$")) { - return true; - } - return !seen.add(name); - } - - private SemType semTypeInner(ObjectDefinition od, CellAtomicType.CellMutability mut, - Function semTypeSupplier) { - Env env = Env.getInstance(); - ObjectQualifiers qualifiers = getObjectQualifiers(); - List members = new ArrayList<>(); - Set seen = new HashSet<>(); - for (Entry entry : fields.entrySet()) { - String name = entry.getKey(); - if (skipField(seen, name)) { - continue; - } - Field field = entry.getValue(); - boolean isPublic = SymbolFlags.isFlagOn(field.getFlags(), SymbolFlags.PUBLIC); - boolean isImmutable = qualifiers.readonly() | SymbolFlags.isFlagOn(field.getFlags(), SymbolFlags.READONLY); - members.add(new Member(name, semTypeSupplier.apply(field.getFieldType()), Member.Kind.Field, - isPublic ? Member.Visibility.Public : Member.Visibility.Private, isImmutable)); - } - for (MethodData method : allMethods()) { - String name = method.name(); - if (skipField(seen, name)) { - continue; - } - boolean isPublic = SymbolFlags.isFlagOn(method.flags(), SymbolFlags.PUBLIC); - members.add(new Member(name, method.semType(), Member.Kind.Method, - isPublic ? Member.Visibility.Public : Member.Visibility.Private, true)); - } - return od.define(env, qualifiers, members, mut); - } - - private ObjectQualifiers getObjectQualifiers() { - boolean isolated = SymbolFlags.isFlagOn(getFlags(), SymbolFlags.ISOLATED); - boolean readonly = SymbolFlags.isFlagOn(getFlags(), SymbolFlags.READONLY); - ObjectQualifiers.NetworkQualifier networkQualifier; - if (SymbolFlags.isFlagOn(getFlags(), SymbolFlags.SERVICE)) { - networkQualifier = ObjectQualifiers.NetworkQualifier.Service; - } else if (SymbolFlags.isFlagOn(getFlags(), SymbolFlags.CLIENT)) { - networkQualifier = ObjectQualifiers.NetworkQualifier.Client; - } else { - networkQualifier = ObjectQualifiers.NetworkQualifier.None; - } - return new ObjectQualifiers(isolated, readonly, networkQualifier); - } - - @Override - public Optional inherentTypeOf(Context cx, ShapeSupplier shapeSupplier, Object object) { - if (!couldInherentTypeBeDifferent()) { - return Optional.of(getSemType()); - } - AbstractObjectValue abstractObjectValue = (AbstractObjectValue) object; - SemType cachedShape = abstractObjectValue.shapeOf(); - if (cachedShape != null) { - return Optional.of(cachedShape); - } - initializeDistinctIdSupplierIfNeeded(cx.env); - SemType shape = distinctIdSupplier.get().stream().map(ObjectDefinition::distinct) - .reduce(valueShape(cx, shapeSupplier, abstractObjectValue), Core::intersect); - abstractObjectValue.cacheShape(shape); - return Optional.of(shape); - } - - private void initializeDistinctIdSupplierIfNeeded(Env env) { - if (distinctIdSupplier == null) { - synchronized (this) { - if (distinctIdSupplier == null) { - distinctIdSupplier = new DistinctIdSupplier(env, typeIdSet); - } - } - } - } - - @Override - public Optional shapeOf(Context cx, ShapeSupplier shapeSupplierFn, Object object) { - return Optional.of(valueShape(cx, shapeSupplierFn, (AbstractObjectValue) object)); - } - - @Override - public final Optional acceptedTypeOf(Context cx) { - Env env = Env.getInstance(); - initializeDistinctIdSupplierIfNeeded(cx.env); - CellAtomicType.CellMutability mut = CellAtomicType.CellMutability.CELL_MUT_UNLIMITED; - SemType innerType; - if (acceptedTypeDefn.isDefinitionReady()) { - innerType = acceptedTypeDefn.getSemType(env); - } else { - var result = acceptedTypeDefn.trySetDefinition(ObjectDefinition::new); - if (!result.updated()) { - innerType = acceptedTypeDefn.getSemType(env); - } else { - ObjectDefinition od = result.definition(); - innerType = semTypeInner(od, mut, (type -> ShapeAnalyzer.acceptedTypeOf(cx, type).orElseThrow())); - } - } - return Optional.of( - distinctIdSupplier.get().stream().map(ObjectDefinition::distinct).reduce(innerType, Core::intersect)); - } - - @Override - public boolean couldInherentTypeBeDifferent() { - if (SymbolFlags.isFlagOn(getFlags(), SymbolFlags.READONLY)) { - return true; - } - return fields.values().stream().anyMatch( - field -> SymbolFlags.isFlagOn(field.getFlags(), SymbolFlags.READONLY) || - SymbolFlags.isFlagOn(field.getFlags(), SymbolFlags.FINAL)); - } - - private SemType valueShape(Context cx, ShapeSupplier shapeSupplier, AbstractObjectValue object) { - ObjectDefinition readonlyShapeDefinition = object.getReadonlyShapeDefinition(); - if (readonlyShapeDefinition != null) { - return readonlyShapeDefinition.getSemType(cx.env); - } - ObjectDefinition od = new ObjectDefinition(); - object.setReadonlyShapeDefinition(od); - List members = new ArrayList<>(); - Set seen = new HashSet<>(fields.size() + methodTypes.length); - ObjectQualifiers qualifiers = getObjectQualifiers(); - for (Entry entry : fields.entrySet()) { - String name = entry.getKey(); - if (skipField(seen, name)) { - continue; - } - Field field = entry.getValue(); - boolean isPublic = SymbolFlags.isFlagOn(field.getFlags(), SymbolFlags.PUBLIC); - boolean isImmutable = qualifiers.readonly() | SymbolFlags.isFlagOn(field.getFlags(), SymbolFlags.READONLY) | - SymbolFlags.isFlagOn(field.getFlags(), SymbolFlags.FINAL); - members.add(new Member(name, fieldShape(cx, shapeSupplier, field, object, isImmutable), Member.Kind.Field, - isPublic ? Member.Visibility.Public : Member.Visibility.Private, isImmutable)); - } - for (MethodData method : allMethods()) { - String name = method.name(); - if (skipField(seen, name)) { - continue; - } - boolean isPublic = SymbolFlags.isFlagOn(method.flags(), SymbolFlags.PUBLIC); - members.add(new Member(name, method.semType(), Member.Kind.Method, - isPublic ? Member.Visibility.Public : Member.Visibility.Private, true)); - } - return od.define(cx.env, qualifiers, members, - qualifiers.readonly() ? CellAtomicType.CellMutability.CELL_MUT_NONE : - CellAtomicType.CellMutability.CELL_MUT_LIMITED); - } - - private static SemType fieldShape(Context cx, ShapeSupplier shapeSupplier, Field field, - AbstractObjectValue objectValue, boolean isImmutable) { - if (!isImmutable) { - return SemType.tryInto(field.getFieldType()); - } - BString fieldName = StringUtils.fromString(field.getFieldName()); - Optional shape = shapeSupplier.get(cx, objectValue.get(fieldName)); - assert !shape.isEmpty(); - return shape.get(); - } - - @Override - public void resetSemType() { - defn.clear(); - super.resetSemType(); - } - - protected Collection allMethods() { - if (methodTypes == null) { - return List.of(); - } - return Arrays.stream(methodTypes) - .map(MethodData::fromMethod).toList(); - } - - protected record MethodData(String name, long flags, SemType semType) { - - static MethodData fromMethod(MethodType method) { - return new MethodData(method.getName(), method.getFlags(), - tryInto(method.getType())); - } - - static MethodData fromRemoteMethod(MethodType method) { - // Remote methods need to be distinct with remote methods only there can be instance methods with the same - // name - return new MethodData("@remote_" + method.getName(), method.getFlags(), - tryInto(method.getType())); - } - - static MethodData fromResourceMethod(BResourceMethodType method) { - StringBuilder sb = new StringBuilder(); - sb.append(method.getAccessor()); - for (var each : method.getResourcePath()) { - sb.append(each); - } - String methodName = sb.toString(); - - Type[] pathSegmentTypes = method.pathSegmentTypes; - FunctionType innerFn = method.getType(); - List paramTypes = new ArrayList<>(); - for (Type part : pathSegmentTypes) { - if (part == null) { - paramTypes.add(Builder.getAnyType()); - } else { - paramTypes.add(tryInto(part)); - } - } - for (Parameter paramType : innerFn.getParameters()) { - paramTypes.add(tryInto(paramType.type)); - } - SemType rest; - Type restType = innerFn.getRestType(); - if (restType instanceof BArrayType arrayType) { - rest = tryInto(arrayType.getElementType()); - } else { - rest = Builder.getNeverType(); - } - - SemType returnType; - if (innerFn.getReturnType() != null) { - returnType = tryInto(innerFn.getReturnType()); - } else { - returnType = Builder.getNilType(); - } - ListDefinition paramListDefinition = new ListDefinition(); - Env env = TypeChecker.context().env; - SemType paramType = paramListDefinition.defineListTypeWrapped(env, paramTypes.toArray(SemType[]::new), - paramTypes.size(), rest, CellAtomicType.CellMutability.CELL_MUT_NONE); - FunctionDefinition fd = new FunctionDefinition(); - SemType semType = fd.define(env, paramType, returnType, ((BFunctionType) innerFn).getQualifiers()); - return new MethodData(methodName, method.getFlags(), semType); - } - } - - @Override - protected boolean isDependentlyTypedInner(Set visited) { - return fields.values().stream().map(Field::getFieldType).filter(each -> each instanceof MayBeDependentType) - .anyMatch(each -> ((MayBeDependentType) each).isDependentlyTyped(visited)); - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BParameterizedType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BParameterizedType.java index 05b9229d68ac..9ab78cf7271c 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BParameterizedType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BParameterizedType.java @@ -21,9 +21,6 @@ import io.ballerina.runtime.api.types.ParameterizedType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.SemType; - -import java.util.Set; /** * {@code ParameterizedType} represents the parameterized type in dependently-typed functions. @@ -83,14 +80,4 @@ public Type getParamValueType() { public int getParamIndex() { return this.paramIndex; } - - @Override - public SemType createSemType() { - return SemType.tryInto(this.paramValueType); - } - - @Override - protected boolean isDependentlyTypedInner(Set visited) { - return true; - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BReadonlyType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BReadonlyType.java index c4366334b3fa..c945f4941839 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BReadonlyType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BReadonlyType.java @@ -20,8 +20,6 @@ import io.ballerina.runtime.api.Module; import io.ballerina.runtime.api.types.ReadonlyType; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.ConcurrentLazySupplier; import io.ballerina.runtime.internal.values.RefValue; /** @@ -29,41 +27,34 @@ * * @since 1.3.0 */ -public final class BReadonlyType extends BSemTypeWrapper implements ReadonlyType { +public class BReadonlyType extends BType implements ReadonlyType { public BReadonlyType(String typeName, Module pkg) { - super(new ConcurrentLazySupplier<>(() -> new BReadonlyTypeImpl(typeName, pkg)), typeName, pkg, - TypeTags.READONLY_TAG, Builder.getReadonlyType()); + super(typeName, pkg, RefValue.class); } - protected static final class BReadonlyTypeImpl extends BType implements ReadonlyType { - - private BReadonlyTypeImpl(String typeName, Module pkg) { - super(typeName, pkg, RefValue.class); - } - - @Override - public V getZeroValue() { - return null; - } + @Override + public V getZeroValue() { + return null; + } - @Override - public V getEmptyValue() { - return null; - } + @Override + public V getEmptyValue() { + return null; + } - @Override - public int getTag() { - return TypeTags.READONLY_TAG; - } + @Override + public int getTag() { + return TypeTags.READONLY_TAG; + } - public boolean isNilable() { - return true; - } + @Override + public boolean isNilable() { + return true; + } - @Override - public boolean isReadOnly() { - return true; - } + @Override + public boolean isReadOnly() { + return true; } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BRecordType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BRecordType.java index f64e13db2304..2af42d5596d2 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BRecordType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BRecordType.java @@ -20,7 +20,6 @@ import io.ballerina.identifier.Utils; import io.ballerina.runtime.api.Module; -import io.ballerina.runtime.api.creators.TypeCreator; import io.ballerina.runtime.api.creators.ValueCreator; import io.ballerina.runtime.api.flags.SymbolFlags; import io.ballerina.runtime.api.flags.TypeFlags; @@ -29,44 +28,26 @@ import io.ballerina.runtime.api.types.RecordType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.ShapeAnalyzer; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.values.BFunctionPointer; import io.ballerina.runtime.api.values.BMap; import io.ballerina.runtime.api.values.BString; import io.ballerina.runtime.internal.scheduling.Scheduler; -import io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability; -import io.ballerina.runtime.internal.types.semtype.DefinitionContainer; -import io.ballerina.runtime.internal.types.semtype.MappingDefinition; import io.ballerina.runtime.internal.values.MapValue; import io.ballerina.runtime.internal.values.MapValueImpl; import io.ballerina.runtime.internal.values.ReadOnlyUtils; -import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.Set; -import java.util.function.Function; - -import static io.ballerina.runtime.api.types.semtype.Builder.getNeverType; -import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_NONE; -import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_UNLIMITED; /** * {@code BRecordType} represents a user defined record type in Ballerina. * * @since 0.995.0 */ -public class BRecordType extends BStructureType implements RecordType, TypeWithShape { +public class BRecordType extends BStructureType implements RecordType { private final String internalName; public boolean sealed; public Type restFieldType; @@ -74,9 +55,6 @@ public class BRecordType extends BStructureType implements RecordType, TypeWithS private final boolean readonly; private IntersectionType immutableType; private IntersectionType intersectionType = null; - private final DefinitionContainer defn = new DefinitionContainer<>(); - private final DefinitionContainer acceptedTypeDefn = new DefinitionContainer<>(); - private byte couldInhereTypeBeDifferentCache = 0; private final Map defaultValues = new LinkedHashMap<>(); @@ -95,7 +73,6 @@ public BRecordType(String typeName, String internalName, Module pkg, long flags, this.sealed = sealed; this.typeFlags = typeFlags; this.readonly = SymbolFlags.isFlagOn(flags, SymbolFlags.READONLY); - TypeCreator.registerRecordType(this); } /** @@ -125,7 +102,6 @@ public BRecordType(String typeName, Module pkg, long flags, Map f this.fields = fields; } this.internalName = typeName; - TypeCreator.registerRecordType(this); } private Map getReadOnlyFields(Map fields) { @@ -242,190 +218,4 @@ public Map getDefaultValues() { return defaultValues; } - @Override - public SemType createSemType() { - Env env = Env.getInstance(); - if (defn.isDefinitionReady()) { - return defn.getSemType(env); - } - var result = defn.trySetDefinition(MappingDefinition::new); - if (!result.updated()) { - return defn.getSemType(env); - } - MappingDefinition md = result.definition(); - return createSemTypeInner(md, env, mut(), SemType::tryInto); - } - - private CellMutability mut() { - return isReadOnly() ? CELL_MUT_NONE : CellMutability.CELL_MUT_LIMITED; - } - - private SemType createSemTypeInner(MappingDefinition md, Env env, CellMutability mut, - Function semTypeFunction) { - Field[] fields = getFields().values().toArray(Field[]::new); - MappingDefinition.Field[] mappingFields = new MappingDefinition.Field[fields.length]; - for (int i = 0; i < fields.length; i++) { - Field field = fields[i]; - boolean isOptional = SymbolFlags.isFlagOn(field.getFlags(), SymbolFlags.OPTIONAL); - SemType fieldType = semTypeFunction.apply(field.getFieldType()); - if (!isOptional && Core.isNever(fieldType)) { - return getNeverType(); - } - boolean isReadonly = - SymbolFlags.isFlagOn(field.getFlags(), SymbolFlags.READONLY) || Core.isNever(fieldType); - mappingFields[i] = new MappingDefinition.Field(field.getFieldName(), fieldType, - isReadonly, isOptional); - } - SemType rest; - rest = restFieldType != null ? semTypeFunction.apply(restFieldType) : getNeverType(); - return md.defineMappingTypeWrapped(env, mappingFields, rest, mut); - } - - @Override - public void resetSemType() { - defn.clear(); - super.resetSemType(); - } - - @Override - public boolean isDependentlyTypedInner(Set visited) { - return fields.values().stream().map(Field::getFieldType).filter(each -> each instanceof MayBeDependentType) - .anyMatch(each -> ((MayBeDependentType) each).isDependentlyTyped(visited)); - } - - @Override - public Optional inherentTypeOf(Context cx, ShapeSupplier shapeSupplier, Object object) { - if (!couldInherentTypeBeDifferent()) { - return Optional.of(getSemType()); - } - MapValueImpl value = (MapValueImpl) object; - SemType cachedSemType = value.shapeOf(); - if (cachedSemType != null) { - return Optional.of(cachedSemType); - } - SemType semTypePart = shapeOfInner(cx, shapeSupplier, value, isReadOnly()); - value.cacheShape(semTypePart); - return Optional.of(semTypePart); - } - - private SemType shapeOfInner(Context cx, ShapeSupplier shapeSupplier, MapValueImpl value, - boolean takeFieldShape) { - Env env = cx.env; - int nFields = value.size(); - Map.Entry[] entries = value.entrySet().toArray(Map.Entry[]::new); - Set handledFields = new HashSet<>(nFields); - MappingDefinition md; - if (takeFieldShape) { - MappingDefinition readonlyShapeDefinition = value.getReadonlyShapeDefinition(); - if (readonlyShapeDefinition != null) { - return readonlyShapeDefinition.getSemType(env); - } else { - md = new MappingDefinition(); - value.setReadonlyShapeDefinition(md); - } - } else { - md = new MappingDefinition(); - } - List fields = new ArrayList<>(nFields); - for (int i = 0; i < nFields; i++) { - String fieldName = entries[i].getKey().toString(); - Object fieldValue = entries[i].getValue(); - handledFields.add(fieldName); - fields.add(fieldShape(cx, shapeSupplier, fieldName, fieldValue, takeFieldShape)); - } - if (!takeFieldShape) { - getFields().values().stream() - .filter(field -> !handledFields.contains(field.getFieldName())) - .map(field -> fieldShapeWithoutValue(field, field.getFieldName())) - .forEach(fields::add); - } - MappingDefinition.Field[] fieldsArray = fields.toArray(MappingDefinition.Field[]::new); - SemType rest; - if (takeFieldShape) { - rest = Builder.getNeverType(); - } else { - rest = restFieldType != null ? SemType.tryInto(restFieldType) : getNeverType(); - } - SemType shape = md.defineMappingTypeWrapped(env, fieldsArray, rest, mut()); - value.resetReadonlyShapeDefinition(); - return shape; - } - - private MappingDefinition.Field fieldShapeWithoutValue(Field field, String fieldName) { - boolean isOptional = fieldIsOptional(fieldName); - boolean isReadonly = fieldIsReadonly(fieldName); - SemType fieldType = SemType.tryInto(field.getFieldType()); - if (isReadonly && isOptional) { - fieldType = Builder.getUndefType(); - } - MappingDefinition.Field field1 = new MappingDefinition.Field(field.getFieldName(), fieldType, - isReadonly, isOptional); - return field1; - } - - @Override - public boolean couldInherentTypeBeDifferent() { - if (couldInhereTypeBeDifferentCache != 0) { - return couldInhereTypeBeDifferentCache == 1; - } - boolean result = couldShapeBeDifferentInner(); - couldInhereTypeBeDifferentCache = (byte) (result ? 1 : 2); - return result; - } - - private boolean couldShapeBeDifferentInner() { - if (isReadOnly()) { - return true; - } - return fields.values().stream().anyMatch(field -> SymbolFlags.isFlagOn(field.getFlags(), SymbolFlags.READONLY)); - } - - @Override - public Optional shapeOf(Context cx, ShapeSupplier shapeSupplier, Object object) { - return Optional.of(shapeOfInner(cx, shapeSupplier, (MapValueImpl) object, true)); - } - - @Override - public Optional acceptedTypeOf(Context cx) { - Env env = cx.env; - if (acceptedTypeDefn.isDefinitionReady()) { - return Optional.of(acceptedTypeDefn.getSemType(env)); - } - var result = acceptedTypeDefn.trySetDefinition(MappingDefinition::new); - if (!result.updated()) { - return Optional.of(acceptedTypeDefn.getSemType(env)); - } - MappingDefinition md = result.definition(); - return Optional.of(createSemTypeInner(md, env, CELL_MUT_UNLIMITED, - (type) -> ShapeAnalyzer.acceptedTypeOf(cx, type).orElseThrow())); - } - - private Type fieldType(String fieldName) { - Field field = fields.get(fieldName); - return field == null ? restFieldType : field.getFieldType(); - } - - private boolean fieldIsReadonly(String fieldName) { - Field field = fields.get(fieldName); - return field != null && SymbolFlags.isFlagOn(field.getFlags(), SymbolFlags.READONLY); - } - - private boolean fieldIsOptional(String fieldName) { - Field field = fields.get(fieldName); - return field != null && SymbolFlags.isFlagOn(field.getFlags(), SymbolFlags.OPTIONAL); - } - - private MappingDefinition.Field fieldShape(Context cx, ShapeSupplier shapeSupplier, String fieldName, - Object fieldValue, boolean alwaysTakeValueShape) { - boolean readonlyField = fieldIsReadonly(fieldName); - boolean optionalField = fieldIsOptional(fieldName); - SemType fieldType; - if (alwaysTakeValueShape || readonlyField) { - optionalField = false; - fieldType = shapeSupplier.get(cx, fieldValue).orElseThrow(); - } else { - fieldType = SemType.tryInto(fieldType(fieldName)); - } - return new MappingDefinition.Field(fieldName, fieldType, readonlyField, optionalField); - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BSemTypeWrapper.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BSemTypeWrapper.java deleted file mode 100644 index 4c1f5ed85391..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BSemTypeWrapper.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types; - -import io.ballerina.runtime.api.Module; -import io.ballerina.runtime.api.types.IntersectionType; -import io.ballerina.runtime.api.types.Type; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.internal.TypeChecker; -import io.ballerina.runtime.internal.types.semtype.ImmutableSemType; - -import java.util.Objects; -import java.util.Set; -import java.util.function.Supplier; - -/** - * Decorator on {@code BTypes} allowing them to behave as {@code SemType}. All - * {@code Types} that needs to behave as both a {@code BType} and a - * {@code SemType} should extend this class. - * - * @param The type of the {@code BType} that is being wrapped. - * @since 2201.11.0 - */ -public sealed class BSemTypeWrapper extends ImmutableSemType implements Type, MayBeDependentType - permits BAnyType, BBooleanType, BByteType, BDecimalType, BFloatType, BHandleType, BIntegerType, BNullType, - BReadonlyType, BStringType { - - private Type cachedReferredType = null; - private Type cachedImpliedType = null; - - private final Supplier bTypeSupplier; - private final int tag; - protected final String typeName; // Debugger uses this field to show the type name - private final Module pkg; - - protected BSemTypeWrapper(Supplier bTypeSupplier, String typeName, Module pkg, int tag, SemType semType) { - super(semType); - this.bTypeSupplier = bTypeSupplier; - this.typeName = typeName; - this.tag = tag; - this.pkg = pkg; - } - - public final Class getValueClass() { - return getbType().getValueClass(); - } - - @Override - public final V getZeroValue() { - return getbType().getZeroValue(); - } - - @Override - public final V getEmptyValue() { - return getbType().getEmptyValue(); - } - - @Override - public final int getTag() { - return tag; - } - - @Override - public final String toString() { - return getbType().toString(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof BSemTypeWrapper other)) { - return false; - } - return Objects.equals(this.typeName, other.typeName) && Objects.equals(this.pkg, other.pkg); - } - - @Override - public final boolean isNilable() { - return Core.containsBasicType(this, Builder.getNilType()); - } - - @Override - public final int hashCode() { - return Objects.hash(this.typeName, this.pkg); - } - - @Override - public String getName() { - return typeName == null ? "" : typeName; - } - - @Override - public String getQualifiedName() { - String name = getName(); - if (name.isEmpty()) { - return ""; - } - - return pkg == null ? name : pkg + ":" + name; - } - - @Override - public Module getPackage() { - return pkg; - } - - @Override - public boolean isPublic() { - return getbType().isPublic(); - } - - @Override - public boolean isNative() { - return getbType().isNative(); - } - - @Override - public boolean isAnydata() { - Context cx = TypeChecker.context(); - return Core.isSubType(cx, this, Builder.getAnyDataType()); - } - - @Override - public boolean isPureType() { - Context cx = TypeChecker.context(); - return Core.isSubType(cx, this, Builder.getErrorType()) || isAnydata(); - } - - @Override - public boolean isReadOnly() { - Context cx = TypeChecker.context(); - return Core.isSubType(cx, this, Builder.getReadonlyType()); - } - - @Override - public Type getImmutableType() { - return getbType().getImmutableType(); - } - - @Override - public void setImmutableType(IntersectionType immutableType) { - getbType().setImmutableType(immutableType); - } - - @Override - public Module getPkg() { - return pkg; - } - - @Override - public long getFlags() { - return getbType().getFlags(); - } - - @Override - public void setCachedReferredType(Type type) { - cachedReferredType = type; - } - - @Override - public Type getCachedReferredType() { - return cachedReferredType; - } - - @Override - public void setCachedImpliedType(Type type) { - cachedImpliedType = type; - } - - @Override - public Type getCachedImpliedType() { - return cachedImpliedType; - } - - protected E getbType() { - return bTypeSupplier.get(); - } - - @Override - public boolean isDependentlyTyped() { - return false; - } - - @Override - public boolean isDependentlyTyped(Set visited) { - return isDependentlyTyped(); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BStreamType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BStreamType.java index 1382a3e29943..494dc1d54642 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BStreamType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BStreamType.java @@ -24,16 +24,9 @@ import io.ballerina.runtime.api.types.StreamType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.internal.TypeChecker; -import io.ballerina.runtime.internal.types.semtype.DefinitionContainer; -import io.ballerina.runtime.internal.types.semtype.StreamDefinition; import io.ballerina.runtime.internal.values.StreamValue; import java.util.Objects; -import java.util.Set; /** * {@link BStreamType} represents streaming data in Ballerina. @@ -44,7 +37,6 @@ public class BStreamType extends BType implements StreamType { private final Type constraint; private final Type completionType; - private final DefinitionContainer definition = new DefinitionContainer<>(); /** * Creates a {@link BStreamType} which represents the stream type. @@ -143,29 +135,4 @@ public boolean equals(Object obj) { return Objects.equals(constraint, other.constraint) && Objects.equals(completionType, other.completionType); } - - @Override - public SemType createSemType() { - if (constraint == null) { - return Builder.getStreamType(); - } - Env env = TypeChecker.context().env; - if (definition.isDefinitionReady()) { - return definition.getSemType(env); - } - var result = definition.trySetDefinition(StreamDefinition::new); - if (!result.updated()) { - return definition.getSemType(env); - } - StreamDefinition sd = result.definition(); - return sd.define(env, tryInto(constraint), tryInto(completionType)); - } - - @Override - protected boolean isDependentlyTypedInner(Set visited) { - return (constraint instanceof MayBeDependentType constrainedType && - constrainedType.isDependentlyTyped(visited)) || - (completionType instanceof MayBeDependentType completionType && - completionType.isDependentlyTyped(visited)); - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BStringType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BStringType.java index 7ddbd3bf0f7c..0211eef19b38 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BStringType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BStringType.java @@ -19,14 +19,8 @@ import io.ballerina.runtime.api.Module; import io.ballerina.runtime.api.constants.RuntimeConstants; -import io.ballerina.runtime.api.constants.TypeConstants; import io.ballerina.runtime.api.types.StringType; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.ConcurrentLazySupplier; -import io.ballerina.runtime.api.types.semtype.SemType; - -import java.util.function.Supplier; /** * {@code BStringType} represents a String type in ballerina. @@ -34,13 +28,9 @@ * @since 0.995.0 */ @SuppressWarnings("unchecked") -public final class BStringType extends BSemTypeWrapper implements StringType { +public class BStringType extends BType implements StringType { - // We are creating separate empty module instead of reusing PredefinedTypes.EMPTY_MODULE to avoid cyclic - // dependencies. - private static final Module DEFAULT_MODULE = new Module(null, null, null); - private static final BStringTypeImpl DEFAULT_B_TYPE = - new BStringTypeImpl(TypeConstants.STRING_TNAME, DEFAULT_MODULE, TypeTags.STRING_TAG); + private final int tag; /** * Create a {@code BStringType} which represents the boolean type. @@ -48,64 +38,32 @@ public final class BStringType extends BSemTypeWrapper new BStringTypeImpl(typeName, pkg, TypeTags.STRING_TAG), typeName, pkg, TypeTags.STRING_TAG, - Builder.getStringType()); + super(typeName, pkg, String.class); + tag = TypeTags.STRING_TAG; } public BStringType(String typeName, Module pkg, int tag) { - this(() -> new BStringTypeImpl(typeName, pkg, tag), typeName, pkg, tag, pickSemtype(tag)); + super(typeName, pkg, String.class); + this.tag = tag; } - private BStringType(Supplier bTypeSupplier, String typeName, Module pkg, int tag, - SemType semType) { - super(new ConcurrentLazySupplier<>(bTypeSupplier), typeName, pkg, tag, semType); + @Override + public V getZeroValue() { + return (V) RuntimeConstants.STRING_EMPTY_VALUE; } - public static BStringType singletonType(String value) { - return new BStringType(() -> (BStringTypeImpl) DEFAULT_B_TYPE.clone(), TypeConstants.STRING_TNAME, - DEFAULT_MODULE, TypeTags.STRING_TAG, Builder.getStringConst(value)); + @Override + public V getEmptyValue() { + return (V) RuntimeConstants.STRING_EMPTY_VALUE; } - private static SemType pickSemtype(int tag) { - return switch (tag) { - case TypeTags.STRING_TAG -> Builder.getStringType(); - case TypeTags.CHAR_STRING_TAG -> Builder.getCharType(); - default -> throw new IllegalStateException("Unexpected string type tag: " + tag); - }; + @Override + public int getTag() { + return tag; } - protected static final class BStringTypeImpl extends BType implements StringType, Cloneable { - - private final int tag; - - private BStringTypeImpl(String typeName, Module pkg, int tag) { - super(typeName, pkg, String.class); - this.tag = tag; - } - - @Override - public V getZeroValue() { - return (V) RuntimeConstants.STRING_EMPTY_VALUE; - } - - @Override - public V getEmptyValue() { - return (V) RuntimeConstants.STRING_EMPTY_VALUE; - } - - @Override - public int getTag() { - return tag; - } - - @Override - public boolean isReadOnly() { - return true; - } - - @Override - public BType clone() { - return super.clone(); - } + @Override + public boolean isReadOnly() { + return true; } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BStructureType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BStructureType.java index 2acdcf181db7..64cf037ebde1 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BStructureType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BStructureType.java @@ -72,7 +72,6 @@ public Map getFields() { @Override public void setFields(Map fields) { this.fields = fields; - resetSemType(); } @Override diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BTableType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BTableType.java index df743c54c344..14c7d2b803e2 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BTableType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BTableType.java @@ -22,27 +22,18 @@ import io.ballerina.runtime.api.types.TableType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.ShapeAnalyzer; -import io.ballerina.runtime.api.values.BTable; -import io.ballerina.runtime.internal.TypeChecker; -import io.ballerina.runtime.internal.types.semtype.TableUtils; import io.ballerina.runtime.internal.values.ReadOnlyUtils; import io.ballerina.runtime.internal.values.TableValue; import io.ballerina.runtime.internal.values.TableValueImpl; import java.util.Optional; -import java.util.Set; /** * {@code BTableType} represents tabular data in Ballerina. * * @since 1.3.0 */ -public class BTableType extends BType implements TableType, TypeWithShape { +public class BTableType extends BType implements TableType { private final Type constraint; private Type keyType; @@ -171,85 +162,4 @@ public void setIntersectionType(IntersectionType intersectionType) { public boolean isAnydata() { return this.constraint.isAnydata(); } - - @Override - public SemType createSemType() { - return createSemTypeWithConstraint(tryInto(constraint)); - } - - private SemType createSemTypeWithConstraint(SemType constraintType) { - SemType semType; - Context cx = TypeChecker.context(); - if (fieldNames.length > 0) { - semType = TableUtils.tableContainingKeySpecifier(cx, constraintType, fieldNames); - } else if (keyType != null) { - semType = TableUtils.tableContainingKeyConstraint(cx, constraintType, tryInto(keyType)); - } else { - semType = TableUtils.tableContaining(cx.env, constraintType); - } - - if (isReadOnly()) { - semType = Core.intersect(semType, Builder.getReadonlyType()); - } - return semType; - } - - @Override - public Optional inherentTypeOf(Context cx, ShapeSupplier shapeSupplier, Object object) { - if (!couldInherentTypeBeDifferent()) { - return Optional.of(getSemType()); - } - BTable table = (BTable) object; - SemType cachedShape = table.shapeOf(); - if (cachedShape != null) { - return Optional.of(cachedShape); - } - SemType semtype = valueShape(cx, shapeSupplier, table); - return Optional.of(semtype); - } - - @Override - public boolean couldInherentTypeBeDifferent() { - return isReadOnly(); - } - - @Override - public Optional shapeOf(Context cx, ShapeSupplier shapeSupplierFn, Object object) { - return Optional.of(valueShape(cx, shapeSupplierFn, (BTable) object)); - } - - @Override - public Optional acceptedTypeOf(Context cx) { - SemType constraintType = ShapeAnalyzer.acceptedTypeOf(cx, this.constraint).orElseThrow(); - SemType semType; - if (fieldNames.length > 0) { - semType = TableUtils.acceptedTypeContainingKeySpecifier(cx, constraintType, fieldNames); - } else if (keyType != null) { - SemType keyAcceptedType = ShapeAnalyzer.acceptedTypeOf(cx, keyType).orElseThrow(); - semType = TableUtils.acceptedTypeContainingKeyConstraint(cx, constraintType, keyAcceptedType); - } else { - semType = TableUtils.acceptedType(cx.env, constraintType); - } - return Optional.of(semType); - } - - private SemType valueShape(Context cx, ShapeSupplier shapeSupplier, BTable table) { - SemType constraintType = Builder.getNeverType(); - for (var value : table.values()) { - SemType valueShape = shapeSupplier.get(cx, value).orElse(SemType.tryInto(constraint)); - constraintType = Core.union(constraintType, valueShape); - } - return createSemTypeWithConstraint(constraintType); - } - - @Override - public boolean shouldCache() { - // TODO: remove this once we have fixed equals - return false; - } - - @Override - protected boolean isDependentlyTypedInner(Set visited) { - return constraint instanceof MayBeDependentType constraintType && constraintType.isDependentlyTyped(visited); - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BTupleType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BTupleType.java index ccda11d6f298..e4758fd5e8b8 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BTupleType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BTupleType.java @@ -24,15 +24,6 @@ import io.ballerina.runtime.api.types.TupleType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.ShapeAnalyzer; -import io.ballerina.runtime.internal.types.semtype.CellAtomicType; -import io.ballerina.runtime.internal.types.semtype.DefinitionContainer; -import io.ballerina.runtime.internal.types.semtype.ListDefinition; -import io.ballerina.runtime.internal.values.AbstractArrayValue; import io.ballerina.runtime.internal.values.ReadOnlyUtils; import io.ballerina.runtime.internal.values.TupleValueImpl; @@ -40,36 +31,25 @@ import java.util.List; import java.util.Objects; import java.util.Optional; -import java.util.Set; -import java.util.function.Function; import java.util.stream.Collectors; -import static io.ballerina.runtime.api.types.semtype.Builder.getNeverType; -import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_NONE; -import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_UNLIMITED; - /** * {@code {@link BTupleType}} represents a tuple type in Ballerina. * * @since 0.995.0 */ -public class BTupleType extends BAnnotatableType implements TupleType, TypeWithShape { +public class BTupleType extends BAnnotatableType implements TupleType { private List tupleTypes; private Type restType; private int typeFlags; private final boolean readonly; - // This is used avoid unnecessary flag updates when we change the members. If this - // is set before accessing flags you must call {@code checkAllMembers}. - private volatile boolean flagsPoisoned = false; private IntersectionType immutableType; private IntersectionType intersectionType = null; public boolean isCyclic = false; private boolean resolving; private boolean resolvingReadonly; private String cachedToString; - private final DefinitionContainer defn = new DefinitionContainer<>(); - private final DefinitionContainer acceptedTypeDefn = new DefinitionContainer<>(); /** * Create a {@code BTupleType} which represents the tuple type. @@ -80,7 +60,7 @@ public BTupleType(List typeList) { super(null, null, Object.class); this.tupleTypes = typeList; this.restType = null; - this.flagsPoisoned = true; + checkAllMembers(); this.readonly = false; } @@ -174,7 +154,6 @@ public void setCyclic(boolean isCyclic) { } public void setMemberTypes(List members, Type restType) { - resetSemType(); if (members == null) { return; } @@ -187,8 +166,7 @@ public void setMemberTypes(List members, Type restType) { this.tupleTypes = members; this.restType = restType; } - flagsPoisoned = true; - defn.clear(); + checkAllMembers(); } @Override @@ -276,24 +254,16 @@ public boolean equals(Object o) { @Override public boolean isAnydata() { - return TypeFlags.isFlagOn(getTypeFlags(), TypeFlags.ANYDATA); + return TypeFlags.isFlagOn(this.typeFlags, TypeFlags.ANYDATA); } @Override public boolean isPureType() { - return TypeFlags.isFlagOn(getTypeFlags(), TypeFlags.PURETYPE); + return TypeFlags.isFlagOn(this.typeFlags, TypeFlags.PURETYPE); } @Override public int getTypeFlags() { - if (flagsPoisoned) { - synchronized (this) { - if (flagsPoisoned) { - checkAllMembers(); - flagsPoisoned = false; - } - } - } return this.typeFlags; } @@ -329,108 +299,4 @@ public void setIntersectionType(IntersectionType intersectionType) { public String getAnnotationKey() { return Utils.decodeIdentifier(this.typeName); } - - @Override - public SemType createSemType() { - Env env = Env.getInstance(); - if (defn.isDefinitionReady()) { - return defn.getSemType(env); - } - var result = defn.trySetDefinition(ListDefinition::new); - if (!result.updated()) { - return defn.getSemType(env); - } - ListDefinition ld = result.definition(); - return createSemTypeInner(env, ld, SemType::tryInto, mut()); - } - - private CellAtomicType.CellMutability mut() { - return isReadOnly() ? CELL_MUT_NONE : CellAtomicType.CellMutability.CELL_MUT_LIMITED; - } - - private SemType createSemTypeInner(Env env, ListDefinition ld, Function semTypeFunction, - CellAtomicType.CellMutability mut) { - SemType[] memberTypes = new SemType[tupleTypes.size()]; - for (int i = 0; i < tupleTypes.size(); i++) { - SemType memberType = semTypeFunction.apply(tupleTypes.get(i)); - if (Core.isNever(memberType)) { - return getNeverType(); - } - memberTypes[i] = memberType; - } - SemType rest = restType != null ? semTypeFunction.apply(restType) : getNeverType(); - return ld.defineListTypeWrapped(env, memberTypes, memberTypes.length, rest, mut); - } - - @Override - public void resetSemType() { - defn.clear(); - super.resetSemType(); - } - - @Override - protected boolean isDependentlyTypedInner(Set visited) { - return tupleTypes.stream().filter(each -> each instanceof MayBeDependentType) - .anyMatch(each -> ((MayBeDependentType) each).isDependentlyTyped(visited)); - } - - @Override - public Optional inherentTypeOf(Context cx, ShapeSupplier shapeSupplier, Object object) { - if (!couldInherentTypeBeDifferent()) { - return Optional.of(getSemType()); - } - AbstractArrayValue value = (AbstractArrayValue) object; - SemType cachedShape = value.shapeOf(); - if (cachedShape != null) { - return Optional.of(cachedShape); - } - SemType semType = shapeOfInner(cx, shapeSupplier, value); - value.cacheShape(semType); - return Optional.of(semType); - } - - @Override - public boolean couldInherentTypeBeDifferent() { - return isReadOnly(); - } - - @Override - public Optional shapeOf(Context cx, ShapeSupplier shapeSupplier, Object object) { - return Optional.of(shapeOfInner(cx, shapeSupplier, (AbstractArrayValue) object)); - } - - @Override - public Optional acceptedTypeOf(Context cx) { - Env env = cx.env; - if (acceptedTypeDefn.isDefinitionReady()) { - return Optional.of(acceptedTypeDefn.getSemType(env)); - } - var result = acceptedTypeDefn.trySetDefinition(ListDefinition::new); - if (!result.updated()) { - return Optional.of(acceptedTypeDefn.getSemType(env)); - } - ListDefinition ld = result.definition(); - return Optional.of(createSemTypeInner(env, ld, (type) -> ShapeAnalyzer.acceptedTypeOf(cx, type).orElseThrow(), - CELL_MUT_UNLIMITED)); - } - - private SemType shapeOfInner(Context cx, ShapeSupplier shapeSupplier, AbstractArrayValue value) { - Env env = cx.env; - ListDefinition defn = value.getReadonlyShapeDefinition(); - if (defn != null) { - return defn.getSemType(env); - } - int size = value.size(); - SemType[] memberTypes = new SemType[size]; - ListDefinition ld = new ListDefinition(); - value.setReadonlyShapeDefinition(ld); - for (int i = 0; i < size; i++) { - Optional memberType = shapeSupplier.get(cx, value.get(i)); - assert memberType.isPresent(); - memberTypes[i] = memberType.get(); - } - SemType semType = ld.defineListTypeWrapped(env, memberTypes, memberTypes.length, getNeverType(), mut()); - value.resetReadonlyShapeDefinition(); - return semType; - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BType.java index 1fdd10c91847..d6cd9c996ba3 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BType.java @@ -22,20 +22,10 @@ import io.ballerina.runtime.api.types.IntersectionType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.CacheableTypeDescriptor; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.TypeCheckCache; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.internal.TypeChecker; -import io.ballerina.runtime.internal.types.semtype.MutableSemType; -import java.util.HashSet; import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; /** * {@code BType} represents a type in Ballerina. @@ -47,18 +37,13 @@ * * @since 0.995.0 */ -public abstract non-sealed class BType extends SemType - implements Type, MutableSemType, Cloneable, CacheableTypeDescriptor, MayBeDependentType { - +public abstract class BType implements Type { protected String typeName; protected Module pkg; protected Class valueClass; private int hashCode; private Type cachedReferredType = null; private Type cachedImpliedType = null; - private volatile SemType cachedSemType = null; - private volatile TypeCheckCache typeCheckCache; - private final ReadWriteLock typeCacheLock = new ReentrantReadWriteLock(); protected BType(String typeName, Module pkg, Class valueClass) { this.typeName = typeName; @@ -246,99 +231,4 @@ public void setCachedImpliedType(Type type) { public Type getCachedImpliedType() { return this.cachedImpliedType; } - - @Override - public SemType createSemType() { - throw new IllegalStateException("Child that are used for type checking must implement this method"); - } - - @Override - public void updateInnerSemTypeIfNeeded() { - synchronized (this) { - if (cachedSemType == null) { - cachedSemType = createSemType(); - setAll(cachedSemType.all()); - setSome(cachedSemType.some(), cachedSemType.subTypeData()); - } - } - } - - protected SemType getSemType() { - updateInnerSemTypeIfNeeded(); - return cachedSemType; - } - - @Override - public void resetSemType() { - cachedSemType = null; - } - - @Override - public BType clone() { - try { - BType clone = (BType) super.clone(); - clone.cachedSemType = null; - clone.setCachedImpliedType(null); - clone.setCachedReferredType(null); - return clone; - } catch (CloneNotSupportedException e) { - throw new AssertionError(); - } - } - - @Override - public boolean shouldCache() { - return this.pkg != null && this.typeName != null && !this.typeName.contains("$anon"); - } - - @Override - public final Optional cachedTypeCheckResult(Context cx, CacheableTypeDescriptor other) { - initializeCacheIfNeeded(cx); - typeCacheLock.readLock().lock(); - try { - return typeCheckCache.cachedTypeCheckResult(other); - } finally { - typeCacheLock.readLock().unlock(); - } - } - - private synchronized void initializeCacheIfNeeded(Context cx) { - typeCacheLock.readLock().lock(); - boolean shouldInitialize = typeCheckCache == null; - typeCacheLock.readLock().unlock(); - if (!shouldInitialize) { - return; - } - try { - typeCacheLock.writeLock().lock(); - if (typeCheckCache == null) { - typeCheckCache = cx.getTypeCheckCache(this); - } - } finally { - typeCacheLock.writeLock().unlock(); - } - } - - @Override - public final void cacheTypeCheckResult(CacheableTypeDescriptor other, boolean result) { - // This happening after checking the cache so it must be initialized by now - typeCheckCache.cacheTypeCheckResult(other, result); - } - - @Override - public final boolean isDependentlyTyped() { - return isDependentlyTyped(new HashSet<>()); - } - - @Override - public final boolean isDependentlyTyped(Set visited) { - if (!visited.add(this)) { - return false; - } - return isDependentlyTypedInner(visited); - } - - protected boolean isDependentlyTypedInner(Set visited) { - return false; - } } 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 2e6384699111..cc2e78d6a319 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 @@ -25,20 +25,16 @@ import io.ballerina.runtime.api.types.IntersectionType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.ShapeAnalyzer; import java.util.Objects; import java.util.Optional; -import java.util.Set; /** * {@code TypeReferencedType} represents a type description which refers to another type. * * @since 2201.2.0 */ -public class BTypeReferenceType extends BAnnotatableType implements IntersectableReferenceType, TypeWithShape { +public class BTypeReferenceType extends BAnnotatableType implements IntersectableReferenceType { private final int typeFlags; private final boolean readOnly; @@ -130,50 +126,4 @@ public Optional getIntersectionType() { public void setIntersectionType(IntersectionType intersectionType) { this.intersectionType = intersectionType; } - - @Override - public SemType createSemType() { - Type referredType = getReferredType(); - return tryInto(referredType); - } - - @Override - protected boolean isDependentlyTypedInner(Set visited) { - return getReferredType() instanceof MayBeDependentType refType && refType.isDependentlyTyped(visited); - } - - @Override - public Optional inherentTypeOf(Context cx, ShapeSupplier shapeSupplier, Object object) { - if (!couldInherentTypeBeDifferent()) { - return Optional.of(getSemType()); - } - Type referredType = getReferredType(); - if (referredType instanceof TypeWithShape typeWithShape) { - return typeWithShape.inherentTypeOf(cx, shapeSupplier, object); - } - return Optional.empty(); - } - - @Override - public boolean couldInherentTypeBeDifferent() { - return referredType instanceof TypeWithShape typeWithShape && typeWithShape.couldInherentTypeBeDifferent(); - } - - @Override - public Optional shapeOf(Context cx, ShapeSupplier shapeSupplierFn, Object object) { - Type referredType = getReferredType(); - if (referredType instanceof TypeWithShape typeWithShape) { - return typeWithShape.shapeOf(cx, shapeSupplierFn, object); - } - return ShapeAnalyzer.shapeOf(cx, referredType); - } - - @Override - public Optional acceptedTypeOf(Context cx) { - Type referredType = getReferredType(); - if (referredType instanceof TypeWithShape typeWithShape) { - return typeWithShape.acceptedTypeOf(cx); - } - return ShapeAnalyzer.acceptedTypeOf(cx, referredType); - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BTypedescType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BTypedescType.java index da696b1bf335..411d75cf9662 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BTypedescType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BTypedescType.java @@ -24,28 +24,19 @@ import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; import io.ballerina.runtime.api.types.TypedescType; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.internal.TypeChecker; -import io.ballerina.runtime.internal.types.semtype.TypedescUtils; import io.ballerina.runtime.internal.values.TypedescValue; import io.ballerina.runtime.internal.values.TypedescValueImpl; -import java.util.Set; - /** * {@code BTypedescType} represents a type of a type in the Ballerina type system. * * @since 0.995.0 */ public class BTypedescType extends BType implements TypedescType { - - private final Type constraint; + private Type constraint; public BTypedescType(String typeName, Module pkg) { super(typeName, pkg, Object.class); - constraint = null; } public BTypedescType(Type constraint) { @@ -93,20 +84,4 @@ public boolean isReadOnly() { public String toString() { return "typedesc" + "<" + constraint.toString() + ">"; } - - @Override - public SemType createSemType() { - if (constraint == null) { - return Builder.getTypeDescType(); - } - SemType constraint = tryInto(getConstraint()); - Context cx = TypeChecker.context(); - return TypedescUtils.typedescContaining(cx.env, constraint); - } - - @Override - protected boolean isDependentlyTypedInner(Set visited) { - return constraint instanceof MayBeDependentType constraintType && - constraintType.isDependentlyTyped(visited); - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BUnionType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BUnionType.java index bdd97fe67536..4fe1f164c653 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BUnionType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BUnionType.java @@ -21,16 +21,10 @@ import io.ballerina.runtime.api.flags.SymbolFlags; import io.ballerina.runtime.api.flags.TypeFlags; import io.ballerina.runtime.api.types.IntersectionType; -import io.ballerina.runtime.api.types.MapType; import io.ballerina.runtime.api.types.SelectivelyImmutableReferenceType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; import io.ballerina.runtime.api.types.UnionType; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.ShapeAnalyzer; import io.ballerina.runtime.api.utils.TypeUtils; import io.ballerina.runtime.internal.TypeChecker; import io.ballerina.runtime.internal.values.ReadOnlyUtils; @@ -50,7 +44,7 @@ * * @since 0.995.0 */ -public class BUnionType extends BType implements UnionType, SelectivelyImmutableReferenceType, TypeWithAcceptedType { +public class BUnionType extends BType implements UnionType, SelectivelyImmutableReferenceType { public boolean isCyclic = false; public static final String PIPE = "|"; @@ -173,7 +167,6 @@ public void setMemberTypes(Type[] members) { } this.memberTypes = readonly ? getReadOnlyTypes(members) : Arrays.asList(members); setFlagsBasedOnMembers(); - resetSemType(); } public void setOriginalMemberTypes(Type[] originalMemberTypes) { @@ -189,9 +182,6 @@ private void setMemberTypes(List members) { } private void setMemberTypes(List members, List originalMembers) { - if (memberTypes != null) { - resetSemType(); - } if (members == null) { return; } @@ -203,6 +193,7 @@ private void setMemberTypes(List members, List originalMembers) { this.memberTypes = readonly ? getReadOnlyTypes(members, new HashSet<>(members.size())) : members; this.resolvingReadonly = false; setFlagsBasedOnMembers(); + setOriginalMemberTypes(originalMembers); } @@ -240,14 +231,12 @@ private boolean checkNillable(List memberTypes) { } private void addMember(Type type) { - resetSemType(); this.memberTypes.add(type); setFlagsBasedOnMembers(); this.originalMemberTypes.add(type); } public void addMembers(Type... types) { - resetSemType(); this.memberTypes.addAll(Arrays.asList(types)); setFlagsBasedOnMembers(); this.originalMemberTypes.addAll(Arrays.asList(types)); @@ -457,7 +446,7 @@ public void mergeUnionType(BUnionType unionType) { this.addMember(newArrayType); continue; } - } else if (member instanceof MapType mapType) { + } else if (member instanceof BMapType mapType) { if (mapType.getConstrainedType() == unionType) { BMapType newMapType = new BMapType(this, this.readonly); this.addMember(newMapType); @@ -468,7 +457,7 @@ public void mergeUnionType(BUnionType unionType) { BTableType newTableType = new BTableType(this, tableType.isReadOnly()); this.addMember(newTableType); continue; - } else if (tableType.getConstrainedType() instanceof MapType mapType) { + } else if (tableType.getConstrainedType() instanceof BMapType mapType) { if (mapType.getConstrainedType() == unionType) { BMapType newMapType = new BMapType(this); BTableType newTableType = new BTableType(newMapType, @@ -551,22 +540,4 @@ public Optional getIntersectionType() { public void setIntersectionType(IntersectionType intersectionType) { this.intersectionType = intersectionType; } - - @Override - public SemType createSemType() { - return memberTypes.stream().map(SemType::tryInto).reduce(Builder.getNeverType(), Core::union); - } - - @Override - protected boolean isDependentlyTypedInner(Set visited) { - return memberTypes.stream() - .filter(each -> each instanceof MayBeDependentType) - .anyMatch(type -> ((MayBeDependentType) type).isDependentlyTyped(visited)); - } - - @Override - public Optional acceptedTypeOf(Context cx) { - return Optional.of(memberTypes.stream().map(each -> ShapeAnalyzer.acceptedTypeOf(cx, each).orElseThrow()) - .reduce(Builder.getNeverType(), Core::union)); - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BXmlType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BXmlType.java index 45dd60c0ad10..05e1cde6985c 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BXmlType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BXmlType.java @@ -20,21 +20,11 @@ import io.ballerina.runtime.api.Module; import io.ballerina.runtime.api.constants.TypeConstants; import io.ballerina.runtime.api.types.IntersectionType; -import io.ballerina.runtime.api.types.ParameterizedType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; import io.ballerina.runtime.api.types.XmlType; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.internal.types.semtype.XmlUtils; import io.ballerina.runtime.internal.values.ReadOnlyUtils; -import io.ballerina.runtime.internal.values.XmlComment; -import io.ballerina.runtime.internal.values.XmlItem; -import io.ballerina.runtime.internal.values.XmlPi; import io.ballerina.runtime.internal.values.XmlSequence; -import io.ballerina.runtime.internal.values.XmlText; import io.ballerina.runtime.internal.values.XmlValue; import java.util.Optional; @@ -45,10 +35,10 @@ * @since 0.995.0 */ @SuppressWarnings("unchecked") -public class BXmlType extends BType implements XmlType, TypeWithShape { +public class BXmlType extends BType implements XmlType { private final int tag; - public final Type constraint; + public Type constraint; private final boolean readonly; private IntersectionType immutableType; private IntersectionType intersectionType = null; @@ -73,13 +63,6 @@ public BXmlType(String typeName, Module pkg, int tag, boolean readonly) { this.constraint = null; } - public BXmlType(String typeName, Type constraint, Module pkg, int tag, boolean readonly) { - super(typeName, pkg, XmlValue.class); - this.tag = tag; - this.readonly = readonly; - this.constraint = constraint; - } - public BXmlType(String typeName, Type constraint, Module pkg, boolean readonly) { super(typeName, pkg, XmlValue.class); this.tag = TypeTags.XML_TAG; @@ -155,103 +138,8 @@ public Optional getIntersectionType() { return this.intersectionType == null ? Optional.empty() : Optional.of(this.intersectionType); } - @Override - public SemType createSemType() { - SemType semType; - if (constraint == null) { - semType = pickTopType(); - } else { - SemType contraintSemtype; - if (constraint instanceof ParameterizedType parameterizedType) { - contraintSemtype = tryInto(parameterizedType.getParamValueType()); - } else { - contraintSemtype = tryInto(constraint); - } - semType = XmlUtils.xmlSequence(contraintSemtype); - } - return isReadOnly() ? Core.intersect(Builder.getReadonlyType(), semType) : semType; - } - - private SemType pickTopType() { - return switch (tag) { - case TypeTags.XML_TAG -> Builder.getXmlType(); - case TypeTags.XML_ELEMENT_TAG -> Builder.getXmlElementType(); - case TypeTags.XML_COMMENT_TAG -> Builder.getXmlCommentType(); - case TypeTags.XML_PI_TAG -> Builder.getXmlPIType(); - case TypeTags.XML_TEXT_TAG -> Builder.getXmlTextType(); - default -> throw new IllegalStateException("Unexpected value: " + tag); - }; - } - @Override public void setIntersectionType(IntersectionType intersectionType) { this.intersectionType = intersectionType; } - - @Override - public Optional inherentTypeOf(Context cx, ShapeSupplier shapeSupplier, Object object) { - XmlValue xmlValue = (XmlValue) object; - if (!isReadOnly(xmlValue)) { - return Optional.of(getSemType()); - } - return readonlyShapeOf(object); - } - - @Override - public boolean couldInherentTypeBeDifferent() { - return true; - } - - @Override - public Optional shapeOf(Context cx, ShapeSupplier shapeSupplierFn, Object object) { - return readonlyShapeOf(object).map(semType -> Core.intersect(semType, Builder.getReadonlyType())); - } - - @Override - public Optional acceptedTypeOf(Context cx) { - return Optional.of(getSemType()); - } - - private Optional readonlyShapeOf(Object object) { - if (object instanceof XmlSequence xmlSequence) { - // We represent xml as an empty sequence - var children = xmlSequence.getChildrenList(); - if (children.isEmpty()) { - return Optional.of(XmlUtils.xmlSingleton(XmlUtils.XML_PRIMITIVE_NEVER)); - } else if (children.size() == 1) { - // Not entirely sure if this is correct, but needed for passing tests - return readonlyShapeOf(children.get(0)); - } - return children.stream() - .map(this::readonlyShapeOf) - .filter(Optional::isPresent) - .map(Optional::get) - .reduce(Core::union) - .map(XmlUtils::xmlSequence); - } else if (object instanceof XmlText) { - // Text is inherently readonly - return Optional.of(Builder.getXmlTextType()); - } else if (object instanceof XmlItem xml) { - return getSemType(xml, Builder.getXmlElementType()); - } else if (object instanceof XmlComment xml) { - return getSemType(xml, Builder.getXmlCommentType()); - } else if (object instanceof XmlPi xml) { - return getSemType(xml, Builder.getXmlPIType()); - } - throw new IllegalArgumentException("Unexpected xml value: " + object); - } - - private static Optional getSemType(XmlValue xml, SemType baseType) { - if (isReadOnly(xml)) { - return Optional.of(Core.intersect(baseType, Builder.getReadonlyType())); - } - return Optional.of(baseType); - } - - private static boolean isReadOnly(XmlValue xmlValue) { - if (xmlValue instanceof XmlSequence || xmlValue instanceof XmlText) { - return true; - } - return xmlValue.getType().isReadOnly(); - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/DistinctIdSupplier.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/DistinctIdSupplier.java deleted file mode 100644 index 771ea177cfa5..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/DistinctIdSupplier.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package io.ballerina.runtime.internal.types; - -import io.ballerina.runtime.api.types.TypeId; -import io.ballerina.runtime.api.types.TypeIdSet; -import io.ballerina.runtime.api.types.semtype.Env; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Supplier; - -/** - * A supplier that provides a list of distinct ids for a given type id set. - * - * @since 2201.11.0 - */ -final class DistinctIdSupplier implements Supplier> { - - private List ids = null; - private static final Map allocatedIds = new ConcurrentHashMap<>(); - private final Env env; - private final TypeIdSet typeIdSet; - - DistinctIdSupplier(Env env, TypeIdSet typeIdSet) { - this.env = env; - this.typeIdSet = typeIdSet; - } - - public synchronized Collection get() { - if (ids != null) { - return ids; - } - if (typeIdSet == null) { - return List.of(); - } - ids = typeIdSet.getIds().stream().map(TypeIdWrapper::new).map(typeId -> allocatedIds.computeIfAbsent(typeId, - ignored -> env.distinctAtomCountGetAndIncrement())) - .toList(); - return ids; - } - - // This is to avoid whether id is primary or not affecting the hashcode. - private record TypeIdWrapper(TypeId typeId) { - - @Override - public boolean equals(Object obj) { - if (obj instanceof TypeIdWrapper other) { - return typeId.getName().equals(other.typeId().getName()) && - typeId.getPkg().equals(other.typeId().getPkg()); - } - return false; - } - - @Override - public int hashCode() { - return Objects.hash(typeId.getPkg(), typeId.getName()); - } - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/TypeWithAcceptedType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/TypeWithAcceptedType.java deleted file mode 100644 index 6dda26b4a8d6..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/TypeWithAcceptedType.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package io.ballerina.runtime.internal.types; - -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SemType; - -import java.util.Optional; - -/** - * Any {@code Type} that contains selectively immutable types must implement this interface. It represents the type - * against which {@code isLikeType} operation is performed. - * - * @since 2201.11.0 - */ -public interface TypeWithAcceptedType { - - Optional acceptedTypeOf(Context cx); -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/TypeWithShape.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/TypeWithShape.java deleted file mode 100644 index 259062fc6896..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/TypeWithShape.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package io.ballerina.runtime.internal.types; - -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SemType; - -import java.util.Optional; - -/** - * Types that are not basic types and have values whose shape could be different form the actual type (i.e. not handles) - * must implement this interface. Note that multiple values could share the same instance of TypeWithShape. Ideally - * different objects should be able to do their shape calculations in a non-blocking manner, even when they share the - * same instance of {@code TypeWithShape}. - * - * @since 2201.11.0 - */ -public interface TypeWithShape extends TypeWithAcceptedType { - - Optional inherentTypeOf(Context cx, ShapeSupplier shapeSupplierFn, Object object); - - Optional shapeOf(Context cx, ShapeSupplier shapeSupplierFn, Object object); - - boolean couldInherentTypeBeDifferent(); -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/AllOrNothing.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/AllOrNothing.java deleted file mode 100644 index 104ed50d84ba..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/AllOrNothing.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package io.ballerina.runtime.internal.types.semtype; - -/** - * Represent cases where a subtype is either all or nothing of the basic type. - * For example if StringSubType has All as it's subtype data that means subtype - * is actually String basic type and nothing means it doesn't have any string - * subtype - * - * @since 2201.11.0 - */ -public enum AllOrNothing implements SubTypeData { - ALL, - NOTHING -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BBooleanSubType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BBooleanSubType.java deleted file mode 100644 index a93adceb286b..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BBooleanSubType.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SubType; - -/** - * Runtime representation of Boolean Sub Type. - * - * @since 2201.11.0 - */ -public final class BBooleanSubType extends SubType { - - private final BBooleanSubTypeData data; - private static final BBooleanSubType ALL = new BBooleanSubType(BBooleanSubTypeData.ALL); - private static final BBooleanSubType NOTHING = new BBooleanSubType(BBooleanSubTypeData.NOTHING); - private static final BBooleanSubType TRUE = new BBooleanSubType(BBooleanSubTypeData.TRUE); - private static final BBooleanSubType FALSE = new BBooleanSubType(BBooleanSubTypeData.FALSE); - - private BBooleanSubType(BBooleanSubTypeData data) { - super(data.isAll(), data.isNothing()); - this.data = data; - } - - public static BBooleanSubType from(boolean value) { - return value ? TRUE : FALSE; - } - - @Override - public SubType union(SubType otherSubtype) { - if (!(otherSubtype instanceof BBooleanSubType other)) { - throw new IllegalArgumentException("union of different subtypes"); - } - if (this.isAll() || other.isAll()) { - return ALL; - } - if (this.isNothing()) { - return other; - } - if (other.isNothing()) { - return this; - } - if (this.data.value == other.data.value) { - return this; - } - return ALL; - } - - @Override - public SubType intersect(SubType otherSubtype) { - if (!(otherSubtype instanceof BBooleanSubType other)) { - throw new IllegalArgumentException("intersection of different subtypes"); - } - if (this.isAll()) { - return other; - } - if (other.isAll()) { - return this; - } - if (this.isNothing() || other.isNothing()) { - return NOTHING; - } - if (this.data.value == other.data.value) { - return this; - } - return NOTHING; - } - - @Override - public SubType diff(SubType otherSubtype) { - if (!(otherSubtype instanceof BBooleanSubType other)) { - throw new IllegalArgumentException("diff of different subtypes"); - } - if (this.isAll() && other.isAll()) { - return NOTHING; - } - if (this.isNothing() || other.isAll()) { - return NOTHING; - } - if (other.isNothing()) { - return this; - } - if (this.isAll()) { - return from(!other.data.value); - } - return this.data.value == other.data.value ? NOTHING : this; - } - - @Override - public SubType complement() { - if (isAll()) { - return NOTHING; - } - if (isNothing()) { - return ALL; - } - return from(!data.value); - } - - @Override - public boolean isEmpty(Context cx) { - return data.isNothing(); - } - - @Override - public SubTypeData data() { - return data.toData(); - } - - // This is instance controlled so only 4 possible instances exists. Default equals is therefore correct - @Override - public int hashCode() { - if (this == ALL) { - return 0; - } - if (this == NOTHING) { - return 1; - } - if (this == TRUE) { - return 2; - } - if (this == FALSE) { - return 3; - } - assert false : "unexpected BBooleanSubType instance"; - return -1; - } - - private record BBooleanSubTypeData(boolean isAll, boolean isNothing, boolean value) { - - private static final BBooleanSubTypeData ALL = new BBooleanSubTypeData(true, false, false); - private static final BBooleanSubTypeData NOTHING = new BBooleanSubTypeData(false, true, false); - private static final BBooleanSubTypeData TRUE = new BBooleanSubTypeData(false, false, true); - private static final BBooleanSubTypeData FALSE = new BBooleanSubTypeData(false, false, false); - - SubTypeData toData() { - if (isAll()) { - return AllOrNothing.ALL; - } else if (isNothing()) { - return AllOrNothing.NOTHING; - } - return new BooleanSubTypeData(value()); - } - } - - private record BooleanSubTypeData(boolean value) implements SubTypeData { - - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BCellSubType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BCellSubType.java deleted file mode 100644 index 2192eec3e530..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BCellSubType.java +++ /dev/null @@ -1,52 +0,0 @@ -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Atom; -import io.ballerina.runtime.api.types.semtype.Bdd; -import io.ballerina.runtime.api.types.semtype.BddNode; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.SubType; -import io.ballerina.runtime.api.types.semtype.TypeAtom; - -/** - * Represents a subtype of a Cell. - * - * @since 2201.11.0 - */ -public abstract sealed class BCellSubType extends SubType implements DelegatedSubType - permits BCellSubTypeImpl, BCellSubTypeSimple { - - public BCellSubType(boolean all, boolean nothing) { - super(all, nothing); - } - - public static BCellSubType createDelegate(SubType inner) { - Bdd bdd; - if (inner instanceof Bdd b) { - bdd = b; - } else if (inner instanceof BCellSubTypeImpl bCellImpl) { - bdd = bCellImpl.inner(); - } else if (inner instanceof BCellSubTypeSimple simple) { - return simple; - } else { - throw new IllegalArgumentException("Unexpected inner type"); - } - if (!(bdd instanceof BddNode bddNode && bddNode.isSimple())) { - return new BCellSubTypeImpl(bdd); - } - Atom atom = bddNode.atom(); - if (!(atom instanceof TypeAtom typeAtom)) { - return new BCellSubTypeImpl(bdd); - } - CellAtomicType atomicType = (CellAtomicType) typeAtom.atomicType(); - SemType ty = atomicType.ty(); - // We have special logic when it comes to handling undef that needs to be updated to deal with simple cell - // TODO: probably we can also handle immutable cells as well - if (Core.containsBasicType(ty, Builder.getUndefType()) || ty.some() != 0 || - atomicType.mut() != CellAtomicType.CellMutability.CELL_MUT_LIMITED) { - return new BCellSubTypeImpl(bdd); - } - return new BCellSubTypeSimple(ty, bddNode); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BCellSubTypeImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BCellSubTypeImpl.java deleted file mode 100644 index 0335d6513051..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BCellSubTypeImpl.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Bdd; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Conjunction; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.SubType; - -import java.util.Objects; -import java.util.function.Predicate; - -/** - * Runtime representation of CellSubType. - * - * @since 2201.11.0 - */ -final class BCellSubTypeImpl extends BCellSubType implements DelegatedSubType { - - private final Bdd inner; - - BCellSubTypeImpl(Bdd inner) { - super(inner.isAll(), inner.isNothing()); - this.inner = inner; - } - - @Override - public SubType union(SubType other) { - if (other instanceof BCellSubType otherCell) { - return createDelegate(inner.union(otherCell.inner())); - } - throw new IllegalArgumentException("union of different subtypes"); - } - - @Override - public SubType intersect(SubType other) { - if (other instanceof BCellSubType otherCell) { - return createDelegate(inner.intersect(otherCell.inner())); - } - throw new IllegalArgumentException("intersect of different subtypes"); - } - - @Override - public SubType complement() { - return createDelegate(inner.complement()); - } - - @Override - public boolean isEmpty(Context cx) { - return Bdd.bddEvery(cx, inner, BCellSubTypeImpl::cellFormulaIsEmpty); - } - - @Override - public SubType diff(SubType other) { - if (other instanceof BCellSubType otherCell) { - return createDelegate(inner.diff(otherCell.inner())); - } - throw new IllegalArgumentException("diff of different subtypes"); - - } - - @Override - public SubTypeData data() { - throw new IllegalStateException("unimplemented"); - } - - private static boolean cellFormulaIsEmpty(Context cx, Conjunction posList, Conjunction negList) { - CellAtomicType combined; - if (posList == null) { - combined = CellAtomicType.from(Builder.getValType(), CellAtomicType.CellMutability.CELL_MUT_UNLIMITED); - } else { - combined = CellAtomicType.cellAtomType(posList.atom()); - Conjunction p = posList.next(); - while (p != null) { - combined = CellAtomicType.intersectCellAtomicType(combined, CellAtomicType.cellAtomType(p.atom())); - p = p.next(); - } - } - return !cellInhabited(cx, combined, negList); - } - - private static boolean cellInhabited(Context cx, CellAtomicType posCell, Conjunction negList) { - SemType pos = posCell.ty(); - if (Core.isEmpty(cx, pos)) { - return false; - } - return switch (posCell.mut()) { - case CELL_MUT_NONE -> cellMutNoneInhabited(cx, pos, negList); - case CELL_MUT_LIMITED -> cellMutLimitedInhabited(cx, pos, negList); - default -> cellMutUnlimitedInhabited(cx, pos, negList); - }; - } - - private static boolean cellMutUnlimitedInhabited(Context cx, SemType pos, Conjunction negList) { - Conjunction neg = negList; - while (neg != null) { - if (CellAtomicType.cellAtomType(neg.atom()).mut() == CellAtomicType.CellMutability.CELL_MUT_LIMITED && - Core.isSameType(cx, Builder.getValType(), CellAtomicType.cellAtomType(neg.atom()).ty())) { - return false; - } - neg = neg.next(); - } - SemType negListUnionResult = filteredCellListUnion(negList, - conjunction -> CellAtomicType.cellAtomType(conjunction.atom()).mut() == - CellAtomicType.CellMutability.CELL_MUT_UNLIMITED); - // We expect `isNever` condition to be `true` when there are no negative atoms with unlimited mutability. - // Otherwise, we do `isEmpty` to conclude on the inhabitance. - return Core.isNever(negListUnionResult) || !Core.isEmpty(cx, Core.diff(pos, negListUnionResult)); - } - - private static boolean cellMutLimitedInhabited(Context cx, SemType pos, Conjunction negList) { - if (negList == null) { - return true; - } - CellAtomicType negAtomicCell = CellAtomicType.cellAtomType(negList.atom()); - if ((negAtomicCell.mut().compareTo(CellAtomicType.CellMutability.CELL_MUT_LIMITED) >= 0) && - Core.isEmpty(cx, Core.diff(pos, negAtomicCell.ty()))) { - return false; - } - return cellMutLimitedInhabited(cx, pos, negList.next()); - } - - private static boolean cellMutNoneInhabited(Context cx, SemType pos, Conjunction negList) { - SemType negListUnionResult = cellListUnion(negList); - // We expect `isNever` condition to be `true` when there are no negative atoms. - // Otherwise, we do `isEmpty` to conclude on the inhabitance. - return Core.isNever(negListUnionResult) || !Core.isEmpty(cx, Core.diff(pos, negListUnionResult)); - } - - private static SemType cellListUnion(Conjunction negList) { - return filteredCellListUnion(negList, neg -> true); - } - - private static SemType filteredCellListUnion(Conjunction negList, Predicate predicate) { - SemType negUnion = Builder.getNeverType(); - Conjunction neg = negList; - while (neg != null) { - if (predicate.test(neg)) { - negUnion = Core.union(negUnion, CellAtomicType.cellAtomType(neg.atom()).ty()); - } - neg = neg.next(); - } - return negUnion; - } - - @Override - public Bdd inner() { - return inner; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof BCellSubTypeImpl other)) { - return false; - } - return Objects.equals(inner, other.inner); - } - - @Override - public int hashCode() { - return Objects.hashCode(inner); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BCellSubTypeSimple.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BCellSubTypeSimple.java deleted file mode 100644 index 8166bf862624..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BCellSubTypeSimple.java +++ /dev/null @@ -1,137 +0,0 @@ -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.BasicTypeCode; -import io.ballerina.runtime.api.types.semtype.Bdd; -import io.ballerina.runtime.api.types.semtype.BddAllOrNothing; -import io.ballerina.runtime.api.types.semtype.BddNode; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.SubType; -import io.ballerina.runtime.api.types.semtype.TypeAtom; -import io.ballerina.runtime.internal.TypeChecker; - -import java.util.List; -import java.util.Optional; -import java.util.stream.Stream; - -import static io.ballerina.runtime.api.types.semtype.BddNode.bddAtom; - -/** - * Simplified representation of cell if the type is only basic type union and mutability is limited. - * - * @since 2201.11.0 - */ -final class BCellSubTypeSimple extends BCellSubType implements DelegatedSubType { - - private final List pos; - private final List neg; - private BddNode inner; - - BCellSubTypeSimple(SemType type) { - super(type.all() == BasicTypeCode.VT_MASK, type.all() == 0); - assert type.some() == 0; - this.pos = List.of(type); - this.neg = List.of(); - } - - BCellSubTypeSimple(SemType type, BddNode bddNode) { - this(type); - inner = bddNode; - } - - private BCellSubTypeSimple(List pos, List neg) { - super(false, false); - this.pos = pos; - this.neg = neg; - } - - @Override - public SubType union(SubType other) { - if (other instanceof BCellSubTypeSimple simple) { - // P1\N1 U P2\N2 = (P1 U P2)\(N1 U N2) - List combinedPos = Stream.concat(pos.stream(), simple.pos.stream()).toList(); - List combinedNeg = Stream.concat(neg.stream(), simple.neg.stream()).toList(); - return new BCellSubTypeSimple(combinedPos, combinedNeg); - } else if (other instanceof BCellSubTypeImpl complex) { - return createDelegate(inner().union(complex.inner())); - } - throw new IllegalArgumentException("union of different subtypes"); - } - - @Override - public SubType intersect(SubType other) { - if (other instanceof BCellSubTypeSimple simple) { - // P1\N1 ∩ P2\N2 = (P1 ∩ P2)\(N1 U N2) - SemType pos = - Stream.concat(this.pos.stream(), simple.pos.stream()).reduce(Builder.getValType(), Core::intersect); - List neg = Stream.concat(this.neg.stream(), simple.neg.stream()).toList(); - return new BCellSubTypeSimple(List.of(pos), neg); - } else if (other instanceof BCellSubTypeImpl complex) { - return createDelegate(inner().intersect(complex.inner())); - } - throw new IllegalArgumentException("intersection of different subtypes"); - } - - @Override - public SubType complement() { - return new BCellSubTypeSimple(neg, pos); - } - - @Override - public boolean isEmpty(Context cx) { - if (pos.isEmpty()) { - return true; - } - SemType posUnion = pos.stream().reduce(Builder.getNeverType(), Core::union); - if (neg.isEmpty()) { - return Core.isEmpty(cx, posUnion); - } - return neg.stream().anyMatch(neg -> Core.isEmpty(cx, Core.diff(posUnion, neg))); - } - - @Override - public SubTypeData data() { - throw new IllegalStateException("unimplemented"); - } - - @Override - public SubType inner() { - if (inner != null) { - return inner; - } - Env env = TypeChecker.getEnv(); - Optional posBdd = - pos.stream().map(semType -> fromSemType(env, semType)).reduce((acum, bdd) -> (Bdd) acum.union(bdd)); - if (posBdd.isEmpty()) { - return BddAllOrNothing.NOTHING; - } - Optional negBdd = - neg.stream().map(semType -> fromSemType(env, semType)).reduce((acum, bdd) -> (Bdd) acum.union(bdd)); - if (negBdd.isEmpty()) { - return posBdd.get(); - } - return posBdd.get().diff(negBdd.get()); - } - - private static Bdd fromSemType(Env env, SemType type) { - CellAtomicType atomicCell = CellAtomicType.from(type, CellAtomicType.CellMutability.CELL_MUT_LIMITED); - TypeAtom atom = env.cellAtom(atomicCell); - return bddAtom(atom); - } - - @Override - public int hashCode() { - return Stream.concat(pos.stream(), neg.stream()).map(SemType::hashCode).reduce(0, Integer::sum); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof BCellSubTypeSimple other)) { - return false; - } - return pos.equals(other.pos) && neg.equals(other.neg); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BDecimalSubType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BDecimalSubType.java deleted file mode 100644 index 03d2902e17db..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BDecimalSubType.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SubType; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * Runtime representation of DecimalSubType. - * - * @since 2201.11.0 - */ -public final class BDecimalSubType extends SubType { - - final SubTypeData data; - - private BDecimalSubType(SubTypeData data) { - super(data == AllOrNothing.ALL, data == AllOrNothing.NOTHING); - this.data = data; - } - - private static final BDecimalSubType ALL = new BDecimalSubType(AllOrNothing.ALL); - private static final BDecimalSubType NOTHING = new BDecimalSubType(AllOrNothing.NOTHING); - - public static BDecimalSubType createDecimalSubType(boolean allowed, BigDecimal[] values) { - if (values.length == 0) { - if (!allowed) { - return ALL; - } else { - return NOTHING; - } - } - Arrays.sort(values); - return new BDecimalSubType(new DecimalSubTypeData(allowed, values)); - } - - @Override - public SubType union(SubType otherSubtype) { - BDecimalSubType other = (BDecimalSubType) otherSubtype; - if (data instanceof AllOrNothing) { - if (data == AllOrNothing.ALL) { - return this; - } else { - return other; - } - } else if (other.data instanceof AllOrNothing) { - if (other.data == AllOrNothing.ALL) { - return other; - } else { - return this; - } - } - List values = new ArrayList<>(); - DecimalSubTypeData data = (DecimalSubTypeData) this.data; - DecimalSubTypeData otherData = (DecimalSubTypeData) other.data; - boolean allowed = data.union(otherData, values); - return createDecimalSubType(allowed, values.toArray(BigDecimal[]::new)); - } - - @Override - public SubType intersect(SubType otherSubtype) { - BDecimalSubType other = (BDecimalSubType) otherSubtype; - if (data instanceof AllOrNothing) { - if (data == AllOrNothing.ALL) { - return other; - } else { - return NOTHING; - } - } else if (other.data instanceof AllOrNothing) { - if (other.data == AllOrNothing.ALL) { - return this; - } else { - return NOTHING; - } - } - List values = new ArrayList<>(); - DecimalSubTypeData data = (DecimalSubTypeData) this.data; - DecimalSubTypeData otherData = (DecimalSubTypeData) other.data; - boolean allowed = data.intersect(otherData, values); - return createDecimalSubType(allowed, values.toArray(BigDecimal[]::new)); - } - - @Override - public SubType complement() { - if (data == AllOrNothing.ALL) { - return NOTHING; - } else if (data == AllOrNothing.NOTHING) { - return ALL; - } - DecimalSubTypeData data = (DecimalSubTypeData) this.data; - return createDecimalSubType(!data.allowed, data.values); - } - - @Override - public boolean isEmpty(Context cx) { - return data == AllOrNothing.NOTHING; - } - - @Override - public SubTypeData data() { - return data; - } - - public BigDecimal defaultValue() { - if (data instanceof DecimalSubTypeData subTypeData && subTypeData.allowed && subTypeData.values.length == 1) { - return subTypeData.values[0]; - } - return null; - } - - @Override - public String toString() { - if (data instanceof DecimalSubTypeData subTypeData && subTypeData.allowed) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < subTypeData.values.length; i++) { - if (i > 0) { - sb.append(", "); - } - sb.append(subTypeData.values[i]); - } - return sb.toString(); - } - return "decimal"; - } - - private static final class DecimalSubTypeData extends EnumerableSubtypeData implements SubTypeData { - - private final boolean allowed; - private final BigDecimal[] values; - - private DecimalSubTypeData(boolean allowed, BigDecimal[] values) { - this.allowed = allowed; - this.values = values; - } - - @Override - public boolean allowed() { - return allowed; - } - - @Override - public BigDecimal[] values() { - return values; - } - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BErrorSubType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BErrorSubType.java deleted file mode 100644 index 5045122f9a2a..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BErrorSubType.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Bdd; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SubType; - -import java.util.Objects; - -import static io.ballerina.runtime.api.types.semtype.Bdd.bddEveryPositive; - -/** - * Runtime representation of a subtype of error type. - * - * @since 2201.11.0 - */ -public class BErrorSubType extends SubType implements DelegatedSubType { - - public final Bdd inner; - - private BErrorSubType(Bdd inner) { - super(inner.isAll(), inner.isNothing()); - this.inner = inner; - } - - public static BErrorSubType createDelegate(SubType inner) { - if (inner instanceof Bdd bdd) { - return new BErrorSubType(bdd); - } else if (inner.isAll() || inner.isNothing()) { - throw new IllegalStateException("unimplemented"); - } else if (inner instanceof BErrorSubType bError) { - return new BErrorSubType(bError.inner); - } - throw new IllegalArgumentException("Unexpected inner type"); - } - - @Override - public SubType union(SubType other) { - if (!(other instanceof BErrorSubType otherError)) { - throw new IllegalArgumentException("union of different subtypes"); - } - return createDelegate(inner.union(otherError.inner)); - } - - @Override - public SubType intersect(SubType other) { - if (!(other instanceof BErrorSubType otherError)) { - throw new IllegalArgumentException("intersect of different subtypes"); - } - return createDelegate(inner.intersect(otherError.inner)); - } - - @Override - public SubType complement() { - return createDelegate(Builder.getBddSubtypeRo().diff(inner)); - } - - @Override - public boolean isEmpty(Context cx) { - Bdd b = inner; - // The goal of this is to ensure that mappingFormulaIsEmpty call in errorBddIsEmpty beneath - // does not get an empty posList, because it will interpret that - // as `map` rather than `readonly & map`. - b = b.posMaybeEmpty() ? (Bdd) b.intersect(Builder.getBddSubtypeRo()) : b; - return cx.memoSubtypeIsEmpty(cx.mappingMemo, BErrorSubType::errorBddIsEmpty, b); - } - - private static boolean errorBddIsEmpty(Context cx, Bdd b) { - return bddEveryPositive(cx, b, null, null, BMappingSubType::mappingFormulaIsEmpty); - } - - @Override - public SubTypeData data() { - return inner(); - } - - @Override - public Bdd inner() { - return inner; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof BErrorSubType that)) { - return false; - } - return Objects.equals(inner, that.inner); - } - - @Override - public int hashCode() { - return Objects.hashCode(inner); - } - -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BFloatSubType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BFloatSubType.java deleted file mode 100644 index 333e986ae9be..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BFloatSubType.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SubType; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * Runtime representation of FloatSubType. - * - * @since 2201.11.0 - */ -public final class BFloatSubType extends SubType { - - final SubTypeData data; - - private BFloatSubType(SubTypeData data) { - super(data == AllOrNothing.ALL, data == AllOrNothing.NOTHING); - this.data = data; - } - - private static final BFloatSubType ALL = new BFloatSubType(AllOrNothing.ALL); - private static final BFloatSubType NOTHING = new BFloatSubType(AllOrNothing.NOTHING); - - public static BFloatSubType createFloatSubType(boolean allowed, Double[] values) { - if (values.length == 0) { - if (!allowed) { - return ALL; - } else { - return NOTHING; - } - } - return new BFloatSubType(new FloatSubTypeData(allowed, values)); - } - - @Override - public SubType union(SubType otherSubtype) { - BFloatSubType other = (BFloatSubType) otherSubtype; - if (data instanceof AllOrNothing) { - if (data == AllOrNothing.ALL) { - return this; - } else { - return other; - } - } else if (other.data instanceof AllOrNothing) { - if (other.data == AllOrNothing.ALL) { - return other; - } else { - return this; - } - } - List values = new ArrayList<>(); - FloatSubTypeData data = (FloatSubTypeData) this.data; - FloatSubTypeData otherData = (FloatSubTypeData) other.data; - boolean allowed = data.union(otherData, values); - return createFloatSubType(allowed, values.toArray(Double[]::new)); - } - - @Override - public SubType intersect(SubType otherSubtype) { - BFloatSubType other = (BFloatSubType) otherSubtype; - if (data instanceof AllOrNothing) { - if (data == AllOrNothing.ALL) { - return other; - } else { - return NOTHING; - } - } else if (other.data instanceof AllOrNothing) { - if (other.data == AllOrNothing.ALL) { - return this; - } else { - return NOTHING; - } - } - List values = new ArrayList<>(); - FloatSubTypeData data = (FloatSubTypeData) this.data; - FloatSubTypeData otherData = (FloatSubTypeData) other.data; - boolean allowed = data.intersect(otherData, values); - return createFloatSubType(allowed, values.toArray(Double[]::new)); - } - - @Override - public SubType complement() { - if (data == AllOrNothing.ALL) { - return NOTHING; - } else if (data == AllOrNothing.NOTHING) { - return ALL; - } - FloatSubTypeData data = (FloatSubTypeData) this.data; - return createFloatSubType(!data.allowed, data.values); - } - - @Override - public boolean isEmpty(Context cx) { - return data == AllOrNothing.NOTHING; - } - - @Override - public SubTypeData data() { - return data; - } - - static final class FloatSubTypeData extends EnumerableSubtypeData implements SubTypeData { - - private final boolean allowed; - private final Double[] values; - - private FloatSubTypeData(boolean allowed, Double[] values) { - this.allowed = allowed; - this.values = filteredValues(values); - } - - private static Double[] filteredValues(Double[] values) { - for (int i = 0; i < values.length; i++) { - values[i] = canon(values[i]); - } - if (values.length < 2) { - return values; - } - Arrays.sort(values); - Double[] buffer = new Double[values.length]; - buffer[0] = values[0]; - int bufferLen = 1; - for (int i = 1; i < values.length; i++) { - Double value = values[i]; - Double prevValue = values[i - 1]; - if (isSame(value, prevValue)) { - continue; - } - buffer[bufferLen++] = value; - } - return Arrays.copyOf(buffer, bufferLen); - } - - private static Double canon(Double d) { - if (d.equals(0.0) || d.equals(-0.0)) { - return 0.0; - } - return d; - } - - private static boolean isSame(double f1, double f2) { - if (Double.isNaN(f1)) { - return Double.isNaN(f2); - } - return f1 == f2; - } - - @Override - public boolean allowed() { - return allowed; - } - - @Override - public Double[] values() { - return values; - } - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BFunctionSubType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BFunctionSubType.java deleted file mode 100644 index cad6312b7744..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BFunctionSubType.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Bdd; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Conjunction; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.SubType; - -import java.util.Objects; - -import static io.ballerina.runtime.api.types.semtype.Bdd.bddEvery; - -/** - * Runtime representation of a subtype of function type. - * - * @since 2201.11.0 - */ -public class BFunctionSubType extends SubType implements DelegatedSubType { - - public final Bdd inner; - - private BFunctionSubType(Bdd inner) { - super(inner.isAll(), inner.isNothing()); - this.inner = inner; - } - - public static BFunctionSubType createDelegate(SubType inner) { - if (inner instanceof Bdd bdd) { - return new BFunctionSubType(bdd); - } else if (inner.isAll() || inner.isNothing()) { - throw new IllegalStateException("unimplemented"); - } else if (inner instanceof BFunctionSubType bFunction) { - return new BFunctionSubType(bFunction.inner); - } - throw new IllegalArgumentException("Unexpected inner type"); - } - - @Override - public SubType union(SubType other) { - if (!(other instanceof BFunctionSubType otherFn)) { - throw new IllegalArgumentException("union of different subtypes"); - } - return createDelegate(inner.union(otherFn.inner)); - } - - @Override - public SubType intersect(SubType other) { - if (!(other instanceof BFunctionSubType otherList)) { - throw new IllegalArgumentException("intersect of different subtypes"); - } - return createDelegate(inner.intersect(otherList.inner)); - } - - @Override - public SubType complement() { - return createDelegate(inner.complement()); - } - - @Override - public boolean isEmpty(Context cx) { - return cx.memoSubtypeIsEmpty(cx.functionMemo, - (context, bdd) -> bddEvery(context, bdd, BFunctionSubType::functionFormulaIsEmpty), inner); - } - - private static boolean functionFormulaIsEmpty(Context cx, Conjunction pos, Conjunction neg) { - return functionPathIsEmpty(cx, functionUnionParams(cx, pos), functionUnionQualifiers(cx, pos), pos, neg); - } - - private static boolean functionPathIsEmpty(Context cx, SemType params, SemType qualifier, Conjunction pos, - Conjunction neg) { - if (neg == null) { - return false; - } - FunctionAtomicType t = cx.functionAtomicType(neg.atom()); - SemType t0 = t.paramType(); - SemType t1 = t.retType(); - SemType t2 = t.qualifiers(); - return (Core.isSubType(cx, qualifier, t2) && Core.isSubType(cx, t0, params) && - functionPhi(cx, t0, Core.complement(t1), pos)) - || functionPathIsEmpty(cx, params, qualifier, pos, neg.next()); - } - - private static boolean functionPhi(Context cx, SemType t0, SemType t1, Conjunction pos) { - if (pos == null) { - // t0 is NEVER only for function top types with qualifiers - return !Core.isNever(t0) && (Core.isEmpty(cx, t0) || Core.isEmpty(cx, t1)); - } - return functionPhiInner(cx, t0, t1, pos); - } - - private static boolean functionPhiInner(Context cx, SemType t0, SemType t1, Conjunction pos) { - if (pos == null) { - return Core.isEmpty(cx, t0) || Core.isEmpty(cx, t1); - } else { - FunctionAtomicType s = cx.functionAtomicType(pos.atom()); - SemType s0 = s.paramType(); - SemType s1 = s.retType(); - return (Core.isSubType(cx, t0, s0) - || Core.isSubType(cx, functionIntersectRet(cx, pos.next()), Core.complement(t1))) - && functionPhiInner(cx, t0, Core.intersect(t1, s1), pos.next()) - && functionPhiInner(cx, Core.diff(t0, s0), t1, pos.next()); - } - } - - private static SemType functionIntersectRet(Context cx, Conjunction pos) { - if (pos == null) { - return Builder.getValType(); - } - return Core.intersect(cx.functionAtomicType(pos.atom()).retType(), functionIntersectRet(cx, pos.next())); - } - - private static SemType functionUnionParams(Context cx, Conjunction pos) { - if (pos == null) { - return Builder.getNeverType(); - } - return Core.union(cx.functionAtomicType(pos.atom()).paramType(), functionUnionParams(cx, pos.next())); - } - - private static SemType functionUnionQualifiers(Context cx, Conjunction pos) { - if (pos == null) { - return Builder.getNeverType(); - } - return Core.union(cx.functionAtomicType(pos.atom()).qualifiers(), functionUnionQualifiers(cx, pos.next())); - } - - @Override - public SubTypeData data() { - throw new IllegalStateException("unimplemented"); - } - - @Override - public Bdd inner() { - return inner; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof BMappingSubType that)) { - return false; - } - return Objects.equals(inner, that.inner); - } - - @Override - public int hashCode() { - return Objects.hashCode(inner); - } - -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BFutureSubType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BFutureSubType.java deleted file mode 100644 index c9389cff9671..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BFutureSubType.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Bdd; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SubType; - -import java.util.Objects; - -import static io.ballerina.runtime.api.types.semtype.Bdd.bddEvery; - -/** - * Runtime representation of a subtype of future type. - * - * @since 2201.11.0 - */ -public final class BFutureSubType extends SubType implements DelegatedSubType { - - private final Bdd inner; - - private BFutureSubType(Bdd inner) { - super(inner.isAll(), inner.isNothing()); - this.inner = inner; - } - - public static BFutureSubType createDelegate(SubType inner) { - if (inner instanceof Bdd bdd) { - return new BFutureSubType(bdd); - } else if (inner.isAll() || inner.isNothing()) { - throw new IllegalStateException("unimplemented"); - } else if (inner instanceof BFutureSubType other) { - return new BFutureSubType(other.inner); - } - throw new IllegalArgumentException("Unexpected inner type"); - } - - @Override - public SubType union(SubType other) { - if (!(other instanceof BFutureSubType otherFuture)) { - throw new IllegalArgumentException("union of different subtypes"); - } - return createDelegate(inner.union(otherFuture.inner)); - } - - @Override - public SubType intersect(SubType other) { - if (!(other instanceof BFutureSubType otherFuture)) { - throw new IllegalArgumentException("union of different subtypes"); - } - return createDelegate(inner.intersect(otherFuture.inner)); - } - - @Override - public SubType complement() { - return createDelegate(inner.complement()); - } - - @Override - public boolean isEmpty(Context cx) { - return cx.memoSubtypeIsEmpty(cx.mappingMemo, - (context, bdd) -> bddEvery(context, bdd, BMappingSubType::mappingFormulaIsEmpty), inner); - } - - @Override - public SubTypeData data() { - throw new UnsupportedOperationException("Method not implemented"); - } - - @Override - public SubType inner() { - throw new UnsupportedOperationException("Method not implemented"); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof BFutureSubType other)) { - return false; - } - return Objects.equals(inner, other.inner); - } - - @Override - public int hashCode() { - return Objects.hash(inner); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BIntSubType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BIntSubType.java deleted file mode 100644 index 30e123d338fe..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BIntSubType.java +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SubType; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import static io.ballerina.runtime.api.constants.RuntimeConstants.INT_MAX_VALUE; -import static io.ballerina.runtime.api.constants.RuntimeConstants.INT_MIN_VALUE; - -/** - * Runtime representation of a int subtype. - * - * @since 2201.11.0 - */ -public final class BIntSubType extends SubType { - - final SubTypeData data; - - private BIntSubType(SubTypeData data) { - super(data == AllOrNothing.ALL, data == AllOrNothing.NOTHING); - this.data = data; - } - - private static final BIntSubType ALL = new BIntSubType(AllOrNothing.ALL); - private static final BIntSubType NOTHING = new BIntSubType(AllOrNothing.NOTHING); - - public static BIntSubType createIntSubType(List values) { - Collections.sort(values); - List ranges = new ArrayList<>(); - long start = values.get(0); - long end = start; - for (int i = 1; i < values.size(); i++) { - long value = values.get(i); - if (value == end + 1) { - end = value; - } else { - ranges.add(new Range(start, end)); - start = value; - end = value; - } - } - ranges.add(new Range(start, end)); - return new BIntSubType(new IntSubTypeData(ranges.toArray(Range[]::new))); - } - - public static BIntSubType createIntSubType(long min, long max) { - assert min < max : "Invalid range"; - Range range = new Range(min, max); - Range[] ranges = {range}; - return new BIntSubType(new IntSubTypeData(ranges)); - } - - @Override - public SubType union(SubType otherSubType) { - BIntSubType other = (BIntSubType) otherSubType; - if (data instanceof AllOrNothing) { - if (data == AllOrNothing.ALL) { - return this; - } else { - return other; - } - } else if (other.data instanceof AllOrNothing) { - if (other.data == AllOrNothing.ALL) { - return other; - } else { - return this; - } - } - IntSubTypeData thisData = (IntSubTypeData) data; - IntSubTypeData otherData = (IntSubTypeData) other.data; - IntSubTypeData v = thisData.union(otherData); - Range[] resultRanges = v.ranges; - if (resultRanges.length == 1 && resultRanges[0].min == INT_MAX_VALUE && resultRanges[0].max == INT_MAX_VALUE) { - return ALL; - } - return new BIntSubType(v); - } - - @Override - public SubType intersect(SubType otherSubType) { - BIntSubType other = (BIntSubType) otherSubType; - if (data instanceof AllOrNothing) { - if (data == AllOrNothing.ALL) { - return other; - } else { - return NOTHING; - } - } else if (other.data instanceof AllOrNothing) { - if (other.data == AllOrNothing.ALL) { - return this; - } else { - return NOTHING; - } - } - IntSubTypeData thisData = (IntSubTypeData) data; - IntSubTypeData otherData = (IntSubTypeData) other.data; - IntSubTypeData v = thisData.intersect(otherData); - Range[] resultRanges = v.ranges; - if (resultRanges.length == 0) { - return NOTHING; - } - return new BIntSubType(v); - } - - @Override - public SubType complement() { - if (this.data == AllOrNothing.ALL) { - return NOTHING; - } else if (this.data == AllOrNothing.NOTHING) { - return ALL; - } - IntSubTypeData intData = (IntSubTypeData) data; - return new BIntSubType(intData.complement()); - } - - @Override - public boolean isEmpty(Context cx) { - return data == AllOrNothing.NOTHING; - } - - @Override - public SubTypeData data() { - return data; - } - - public record Range(long min, long max) { - - } - - public static boolean intSubtypeContains(SubTypeData d, long n) { - if (!(d instanceof IntSubTypeData intSubTypeData)) { - return d == AllOrNothing.ALL; - } - return intSubTypeData.contains(n); - } - - public static final class IntSubTypeData implements SubTypeData { - - final Range[] ranges; - - private IntSubTypeData(Range range) { - this.ranges = new Range[]{range}; - } - - private IntSubTypeData(Range[] ranges) { - this.ranges = ranges; - } - - public List values() { - List values = new ArrayList<>(); - for (Range range : ranges) { - for (long i = range.min; i <= range.max; i++) { - values.add(i); - } - } - return values; - } - - public long max() { - return ranges[ranges.length - 1].max; - } - - boolean isRangeOverlap(Range range) { - IntSubTypeData subTypeData = intersect(new IntSubTypeData(range)); - return subTypeData.ranges.length != 0; - } - - private boolean contains(long n) { - for (Range r : ranges) { - if (r.min <= n && n <= r.max) { - return true; - } - } - return false; - } - - private IntSubTypeData union(IntSubTypeData other) { - List result = new ArrayList<>(); - int i1 = 0; - int i2 = 0; - Range[] v1 = this.ranges; - Range[] v2 = other.ranges; - int len1 = ranges.length; - int len2 = other.ranges.length; - while (true) { - if (i1 >= len1) { - if (i2 >= len2) { - break; - } - rangeUnionPush(result, v2[i2]); - i2++; - } else if (i2 >= len2) { - rangeUnionPush(result, v1[i1]); - i1++; - } else { - Range r1 = v1[i1]; - Range r2 = v2[i2]; - RangeOpResult combined = rangeUnion(r1, r2); - switch (combined.tag) { - case OVERLAP -> { - rangeUnionPush(result, combined.range); - i1++; - i2++; - } - case BEFORE -> { - rangeUnionPush(result, r1); - i1++; - } - case AFTER -> { - rangeUnionPush(result, r2); - i2++; - } - } - } - } - return new IntSubTypeData(result.toArray(Range[]::new)); - } - - IntSubTypeData intersect(IntSubTypeData other) { - List result = new ArrayList<>(); - int i1 = 0; - int i2 = 0; - Range[] v1 = this.ranges; - Range[] v2 = other.ranges; - int len1 = ranges.length; - int len2 = other.ranges.length; - while (true) { - if (i1 >= len1 || i2 >= len2) { - break; - } - Range r1 = v1[i1]; - Range r2 = v2[i2]; - RangeOpResult combined = rangeIntersect(r1, r2); - switch (combined.tag) { - case OVERLAP -> { - rangeUnionPush(result, combined.range); - i1++; - i2++; - } - case BEFORE -> i1++; - case AFTER -> i2++; - } - } - return new IntSubTypeData(result.toArray(Range[]::new)); - } - - IntSubTypeData complement() { - List result = new ArrayList<>(); - Range[] v = this.ranges; - int len = v.length; - long min = v[0].min; - if (min > INT_MIN_VALUE) { - result.add(new Range(INT_MIN_VALUE, min - 1)); - } - for (int i = 1; i < len; i++) { - result.add(new Range(v[i - 1].max + 1, v[i].min - 1)); - } - long max = v[v.length - 1].max; - if (max < INT_MAX_VALUE) { - result.add(new Range(max + 1, INT_MAX_VALUE)); - } - return new IntSubTypeData(result.toArray(Range[]::new)); - } - - private static void rangeUnionPush(List ranges, Range next) { - int lastIndex = ranges.size() - 1; - if (lastIndex < 0) { - ranges.add(next); - return; - } - RangeOpResult result = rangeUnion(ranges.get(lastIndex), next); - if (result.tag == RangeOpResultTag.OVERLAP) { - ranges.set(lastIndex, result.range); - } else { - ranges.add(next); - } - } - - private static RangeOpResult rangeIntersect(Range r1, Range r2) { - if (r1.max < r2.min) { - return new RangeOpResult(RangeOpResultTag.BEFORE, null); - } - if (r2.max < r1.min) { - return new RangeOpResult(RangeOpResultTag.AFTER, null); - } - return new RangeOpResult(RangeOpResultTag.OVERLAP, - new Range(Math.max(r1.min, r2.min), Math.min(r1.max, r2.max))); - } - - enum RangeOpResultTag { - BEFORE, - OVERLAP, - AFTER, - } - - record RangeOpResult(RangeOpResultTag tag, Range range) { - - } - - private static RangeOpResult rangeUnion(Range r1, Range r2) { - if (r1.max < r2.min) { - if (r1.max + 1 != r2.min) { - return new RangeOpResult(RangeOpResultTag.BEFORE, null); - } - } - if (r2.max < r1.min) { - if (r1.max + 1 != r2.min) { - return new RangeOpResult(RangeOpResultTag.AFTER, null); - } - } - return new RangeOpResult(RangeOpResultTag.OVERLAP, - new Range(Math.min(r1.min, r2.min), Math.max(r1.max, r2.max))); - } - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BListProj.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BListProj.java deleted file mode 100644 index adcd59d67c89..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BListProj.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Atom; -import io.ballerina.runtime.api.types.semtype.BasicTypeCode; -import io.ballerina.runtime.api.types.semtype.Bdd; -import io.ballerina.runtime.api.types.semtype.BddAllOrNothing; -import io.ballerina.runtime.api.types.semtype.BddNode; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Conjunction; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.Pair; -import io.ballerina.runtime.api.types.semtype.SemType; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; -import java.util.Objects; - -import static io.ballerina.runtime.api.types.semtype.Builder.getRoCellContaining; -import static io.ballerina.runtime.api.types.semtype.Conjunction.and; -import static io.ballerina.runtime.api.types.semtype.Core.cellInnerVal; -import static io.ballerina.runtime.api.types.semtype.Core.diff; -import static io.ballerina.runtime.api.types.semtype.Core.getComplexSubtypeData; -import static io.ballerina.runtime.api.types.semtype.Core.isEmpty; -import static io.ballerina.runtime.api.types.semtype.Core.isNever; -import static io.ballerina.runtime.api.types.semtype.Core.isNothingSubtype; -import static io.ballerina.runtime.api.types.semtype.Core.union; -import static io.ballerina.runtime.internal.types.semtype.BIntSubType.intSubtypeContains; -import static io.ballerina.runtime.internal.types.semtype.BListSubType.fixedArrayAnyEmpty; -import static io.ballerina.runtime.internal.types.semtype.BListSubType.listIntersectWith; -import static io.ballerina.runtime.internal.types.semtype.BListSubType.listMemberAtInnerVal; -import static io.ballerina.runtime.internal.types.semtype.BListSubType.listSampleTypes; -import static io.ballerina.runtime.internal.types.semtype.BListSubType.listSamples; - -/** - * utility class for list type projection. - * - * @since 2201.11.0 - */ -public final class BListProj { - - private BListProj() { - } - - public static SemType listProjInnerVal(Context cx, SemType t, SemType k) { - if (t.some() == 0) { - return t == Builder.getListType() ? Builder.getValType() : Builder.getNeverType(); - } else { - SubTypeData keyData = Core.intSubtype(k); - if (isNothingSubtype(keyData)) { - return Builder.getNeverType(); - } - return listProjBddInnerVal(cx, keyData, (Bdd) getComplexSubtypeData(t, BasicTypeCode.BT_LIST), null, - null); - } - } - - private static SemType listProjBddInnerVal(Context cx, SubTypeData k, Bdd b, Conjunction pos, Conjunction neg) { - if (b instanceof BddAllOrNothing allOrNothing) { - return allOrNothing.isAll() ? listProjPathInnerVal(cx, k, pos, neg) : Builder.getNeverType(); - } else { - BddNode bddNode = (BddNode) b; - return union(listProjBddInnerVal(cx, k, bddNode.left(), and(bddNode.atom(), pos), neg), - union(listProjBddInnerVal(cx, k, bddNode.middle(), pos, neg), - listProjBddInnerVal(cx, k, bddNode.right(), pos, and(bddNode.atom(), neg)))); - } - } - - private static SemType listProjPathInnerVal(Context cx, SubTypeData k, Conjunction pos, Conjunction neg) { - FixedLengthArray members; - SemType rest; - if (pos == null) { - members = FixedLengthArray.empty(); - rest = Builder.getRwCellContaining(cx.env, union(Builder.getValType(), Builder.getUndefType())); - } else { - // combine all the positive tuples using intersection - ListAtomicType lt = cx.listAtomType(pos.atom()); - members = lt.members(); - rest = lt.rest(); - Conjunction p = pos.next(); - // the neg case is in case we grow the array in listInhabited - if (p != null || neg != null) { - members = members.shallowCopy(); - } - - while (true) { - if (p == null) { - break; - } else { - Atom d = p.atom(); - p = p.next(); - lt = cx.listAtomType(d); - Pair - intersected = listIntersectWith(cx.env, members, rest, lt.members(), lt.rest()); - if (intersected == null) { - return Builder.getNeverType(); - } - members = intersected.first(); - rest = intersected.second(); - } - } - if (fixedArrayAnyEmpty(cx, members)) { - return Builder.getNeverType(); - } - // Ensure that we can use isNever on rest in listInhabited - if (!isNever(cellInnerVal(rest)) && isEmpty(cx, rest)) { - rest = getRoCellContaining(cx.env, Builder.getNeverType()); - } - } - Integer[] indices = listSamples(cx, members, rest, neg); - Pair projSamples = listProjSamples(indices, k); - indices = projSamples.first(); - Pair sampleTypes = listSampleTypes(cx, members, rest, indices); - return listProjExcludeInnerVal(cx, projSamples.first(), - projSamples.second(), - sampleTypes.first(), - sampleTypes.second(), neg); - } - - private static SemType listProjExcludeInnerVal(Context cx, Integer[] indices, Integer[] keyIndices, - SemType[] memberTypes, int nRequired, Conjunction neg) { - SemType p = Builder.getNeverType(); - if (neg == null) { - int len = memberTypes.length; - for (int k : keyIndices) { - if (k < len) { - p = union(p, cellInnerVal(memberTypes[k])); - } - } - } else { - final ListAtomicType nt = cx.listAtomType(neg.atom()); - if (nRequired > 0 && isNever(listMemberAtInnerVal(nt.members(), nt.rest(), indices[nRequired - 1]))) { - return listProjExcludeInnerVal(cx, indices, keyIndices, memberTypes, nRequired, neg.next()); - } - int negLen = nt.members().fixedLength(); - if (negLen > 0) { - int len = memberTypes.length; - if (len < indices.length && indices[len] < negLen) { - return listProjExcludeInnerVal(cx, indices, keyIndices, memberTypes, nRequired, neg.next()); - } - for (int i = nRequired; i < memberTypes.length; i++) { - if (indices[i] >= negLen) { - break; - } - SemType[] t = Arrays.copyOfRange(memberTypes, 0, i); - p = union(p, listProjExcludeInnerVal(cx, indices, keyIndices, t, nRequired, neg.next())); - } - } - for (int i = 0; i < memberTypes.length; i++) { - SemType d = - diff(cellInnerVal(memberTypes[i]), listMemberAtInnerVal(nt.members(), nt.rest(), indices[i])); - if (!Core.isEmpty(cx, d)) { - SemType[] t = memberTypes.clone(); - t[i] = Builder.getRwCellContaining(cx.env, d); - // We need to make index i be required - p = union(p, listProjExcludeInnerVal(cx, indices, keyIndices, t, Integer.max(nRequired, i + 1), - neg.next())); - } - } - } - return p; - } - - private static Pair listProjSamples(Integer[] indices, SubTypeData k) { - List> v = new ArrayList<>(); - for (int i : indices) { - v.add(Pair.from(i, intSubtypeContains(k, i))); - } - if (k instanceof BIntSubType.IntSubTypeData intSubtype) { - for (BIntSubType.Range range : intSubtype.ranges) { - long max = range.max(); - if (range.max() >= 0) { - v.add(Pair.from((int) max, true)); - int min = Integer.max(0, (int) range.min()); - if (min < max) { - v.add(Pair.from(min, true)); - } - } - } - } - v.sort(Comparator.comparingInt(Pair::first)); - List indices1 = new ArrayList<>(); - List keyIndices = new ArrayList<>(); - for (var ib : v) { - if (indices1.isEmpty() || !Objects.equals(ib.first(), indices1.get(indices1.size() - 1))) { - if (ib.second()) { - keyIndices.add(indices1.size()); - } - indices1.add(ib.first()); - } - } - return Pair.from(indices1.toArray(Integer[]::new), keyIndices.toArray(Integer[]::new)); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BListSubType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BListSubType.java deleted file mode 100644 index bb3bbec3769a..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BListSubType.java +++ /dev/null @@ -1,462 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Atom; -import io.ballerina.runtime.api.types.semtype.Bdd; -import io.ballerina.runtime.api.types.semtype.BddAllOrNothing; -import io.ballerina.runtime.api.types.semtype.BddNode; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Conjunction; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.Pair; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.SubType; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -import static io.ballerina.runtime.api.types.semtype.Bdd.bddEvery; -import static io.ballerina.runtime.api.types.semtype.Core.cellInner; -import static io.ballerina.runtime.api.types.semtype.Core.cellInnerVal; -import static io.ballerina.runtime.api.types.semtype.Core.getCellContainingInnerVal; -import static io.ballerina.runtime.api.types.semtype.Core.intersectCellMemberSemTypes; -import static io.ballerina.runtime.internal.types.semtype.BIntSubType.intSubtypeContains; - -/** - * Runtime representation of a subtype of list type. - * - * @since 2201.11.0 - */ -public class BListSubType extends SubType implements DelegatedSubType { - - public final Bdd inner; - - private BListSubType(Bdd inner) { - super(inner.isAll(), inner.isNothing()); - this.inner = inner; - } - - public static BListSubType createDelegate(SubType inner) { - if (inner instanceof Bdd bdd) { - return new BListSubType(bdd); - } else if (inner.isAll() || inner.isNothing()) { - throw new IllegalStateException("unimplemented"); - } else if (inner instanceof BListSubType bList) { - return new BListSubType(bList.inner); - } - throw new IllegalArgumentException("Unexpected inner type"); - } - - @Override - public SubType union(SubType other) { - if (!(other instanceof BListSubType otherList)) { - throw new IllegalArgumentException("union of different subtypes"); - } - return createDelegate(inner.union(otherList.inner)); - } - - @Override - public SubType intersect(SubType other) { - if (!(other instanceof BListSubType otherList)) { - throw new IllegalArgumentException("intersect of different subtypes"); - } - return createDelegate(inner.intersect(otherList.inner)); - } - - @Override - public SubType complement() { - return createDelegate(inner.complement()); - } - - @Override - public SubType diff(SubType other) { - if (!(other instanceof BListSubType otherList)) { - throw new IllegalArgumentException("diff of different subtypes"); - } - return createDelegate(inner.diff(otherList.inner)); - } - - @Override - public boolean isEmpty(Context cx) { - return cx.memoSubtypeIsEmpty(cx.listMemo, - (context, bdd) -> bddEvery(context, bdd, BListSubType::listFormulaIsEmpty), inner); - } - - static boolean listFormulaIsEmpty(Context cx, Conjunction pos, Conjunction neg) { - FixedLengthArray members; - SemType rest; - if (pos == null) { - ListAtomicType atom = Builder.getListAtomicInner(); - members = atom.members(); - rest = atom.rest(); - } else { - // combine all the positive tuples using intersection - ListAtomicType lt = cx.listAtomType(pos.atom()); - members = lt.members(); - rest = lt.rest(); - Conjunction p = pos.next(); - // the neg case is in case we grow the array in listInhabited - if (p != null || neg != null) { - members = members.shallowCopy(); - } - while (true) { - if (p == null) { - break; - } else { - Atom d = p.atom(); - p = p.next(); - lt = cx.listAtomType(d); - Pair - intersected = listIntersectWith(cx.env, members, rest, lt.members(), lt.rest()); - if (intersected == null) { - return true; - } - members = intersected.first(); - rest = intersected.second(); - } - } - if (fixedArrayAnyEmpty(cx, members)) { - return true; - } - } - Integer[] indices = listSamples(cx, members, rest, neg); - Pair sampleTypes = listSampleTypes(cx, members, rest, indices); - return !listInhabited(cx, indices, sampleTypes.first(), sampleTypes.second(), neg); - } - - // This function determines whether a list type P & N is inhabited. - // where P is a positive list type and N is a list of negative list types. - // With just straightforward fixed-length tuples we can consider every index of the tuple. - // But we cannot do this in general because of rest types and fixed length array types e.g. `byte[10000000]`. - // So we consider instead a collection of indices that is sufficient for us to determine inhabitation, - // given the types of P and N. - // `indices` is this list of sample indices: these are indicies into members of the list type. - // We don't represent P directly. Instead P is represented by `memberTypes` and `nRequired`: - // `memberTypes[i]` is the type that P gives to `indices[i]`; - // `nRequired` is the number of members of `memberTypes` that are required by P. - // `neg` represents N. - private static boolean listInhabited(Context cx, Integer[] indices, SemType[] memberTypes, int nRequired, - Conjunction neg) { - if (neg == null) { - return true; - } else { - final ListAtomicType nt = cx.listAtomType(neg.atom()); - if (nRequired > 0 && Core.isNever(listMemberAtInnerVal(nt.members(), nt.rest(), indices[nRequired - 1]))) { - // Skip this negative if it is always shorter than the minimum required by the positive - return listInhabited(cx, indices, memberTypes, nRequired, neg.next()); - } - // Consider cases we can avoid this negative by having a sufficiently short list - int negLen = nt.members().fixedLength(); - if (negLen > 0) { - int len = memberTypes.length; - // If we have isEmpty(T1 & S1) or isEmpty(T2 & S2) then we have [T1, T2] / [S1, S2] = [T1, T2]. - // Therefore, we can skip the negative - for (int i = 0; i < len; i++) { - int index = indices[i]; - if (index >= negLen) { - break; - } - SemType negMemberType = listMemberAt(nt.members(), nt.rest(), index); - SemType common = Core.intersect(memberTypes[i], negMemberType); - if (Core.isEmpty(cx, common)) { - return listInhabited(cx, indices, memberTypes, nRequired, neg.next()); - } - } - // Consider cases we can avoid this negative by having a sufficiently short list - if (len < indices.length && indices[len] < negLen) { - return listInhabited(cx, indices, memberTypes, nRequired, neg.next()); - } - for (int i = nRequired; i < memberTypes.length; i++) { - if (indices[i] >= negLen) { - break; - } - // TODO: avoid creating new arrays here, maybe use an object pool for this - // -- Or use a copy on write array? - SemType[] t = Arrays.copyOfRange(memberTypes, 0, i); - if (listInhabited(cx, indices, t, nRequired, neg.next())) { - return true; - } - } - } - // Now we need to explore the possibility of shapes with length >= neglen - // This is the heart of the algorithm. - // For [v0, v1] not to be in [t0,t1], there are two possibilities - // (1) v0 is not in t0, or - // (2) v1 is not in t1 - // Case (1) - // For v0 to be in s0 but not t0, d0 must not be empty. - // We must then find a [v0,v1] satisfying the remaining negated tuples, - // such that v0 is in d0. - // SemType d0 = diff(s[0], t[0]); - // if !isEmpty(cx, d0) && tupleInhabited(cx, [d0, s[1]], neg.rest) { - // return true; - // } - // Case (2) - // For v1 to be in s1 but not t1, d1 must not be empty. - // We must then find a [v0,v1] satisfying the remaining negated tuples, - // such that v1 is in d1. - // SemType d1 = diff(s[1], t[1]); - // return !isEmpty(cx, d1) && tupleInhabited(cx, [s[0], d1], neg.rest); - // We can generalize this to tuples of arbitrary length. - for (int i = 0; i < memberTypes.length; i++) { - SemType d = Core.diff(memberTypes[i], listMemberAt(nt.members(), nt.rest(), indices[i])); - if (!Core.isEmpty(cx, d)) { - SemType[] t = memberTypes.clone(); - t[i] = d; - // We need to make index i be required - if (listInhabited(cx, indices, t, Integer.max(nRequired, i + 1), neg.next())) { - return true; - } - } - } - // This is correct for length 0, because we know that the length of the - // negative is 0, and [] - [] is empty. - return false; - } - } - - public static Pair listSampleTypes(Context cx, FixedLengthArray members, - SemType rest, Integer[] indices) { - List memberTypes = new ArrayList<>(indices.length); - int nRequired = 0; - for (int i = 0; i < indices.length; i++) { - int index = indices[i]; - SemType t = getCellContainingInnerVal(cx.env, listMemberAt(members, rest, index)); - if (Core.isEmpty(cx, t)) { - break; - } - memberTypes.add(t); - if (index < members.fixedLength()) { - nRequired = i + 1; - } - } - SemType[] buffer = new SemType[memberTypes.size()]; - return Pair.from(memberTypes.toArray(buffer), nRequired); - } - - // Return a list of sample indices for use as second argument of `listInhabited`. - // The positive list type P is represented by `members` and `rest`. - // The negative list types N are represented by `neg` - // The `indices` list (first member of return value) is constructed in two stages. - // First, the set of all non-negative integers is partitioned so that two integers are - // in different partitions if they get different types as an index in P or N. - // Second, we choose a number of samples from each partition. It doesn't matter - // which sample we choose, but (this is the key point) we need at least as many samples - // as there are negatives in N, so that for each negative we can freely choose a type for the sample - // to avoid being matched by that negative. - public static Integer[] listSamples(Context cx, FixedLengthArray members, SemType rest, Conjunction neg) { - int maxInitialLength = members.initial().length; - List fixedLengths = new ArrayList<>(); - fixedLengths.add(members.fixedLength()); - Conjunction tem = neg; - int nNeg = 0; - while (true) { - if (tem != null) { - ListAtomicType lt = cx.listAtomType(tem.atom()); - FixedLengthArray m = lt.members(); - maxInitialLength = Integer.max(maxInitialLength, m.initial().length); - if (m.fixedLength() > maxInitialLength) { - fixedLengths.add(m.fixedLength()); - } - nNeg += 1; - tem = tem.next(); - } else { - break; - } - } - Collections.sort(fixedLengths); - // `boundaries` partitions the non-negative integers - // Construct `boundaries` from `fixedLengths` and `maxInitialLength` - // An index b is a boundary point if indices < b are different from indices >= b - //int[] boundaries = from int i in 1 ... maxInitialLength select i; - List boundaries = new ArrayList<>(fixedLengths.size()); - for (int i = 1; i <= maxInitialLength; i++) { - boundaries.add(i); - } - for (int n : fixedLengths) { - // this also removes duplicates - if (boundaries.isEmpty() || n > boundaries.get(boundaries.size() - 1)) { - boundaries.add(n); - } - } - // Now construct the list of indices by taking nNeg samples from each partition. - List indices = new ArrayList<>(boundaries.size()); - int lastBoundary = 0; - if (nNeg == 0) { - // this is needed for when this is used in listProj - nNeg = 1; - } - for (int b : boundaries) { - int segmentLength = b - lastBoundary; - // Cannot have more samples than are in the parition. - int nSamples = Integer.min(segmentLength, nNeg); - for (int i = b - nSamples; i < b; i++) { - indices.add(i); - } - lastBoundary = b; - } - for (int i = 0; i < nNeg; i++) { - // Be careful to avoid integer overflow. - if (lastBoundary > Integer.MAX_VALUE - i) { - break; - } - indices.add(lastBoundary + i); - } - Integer[] arr = new Integer[indices.size()]; - return indices.toArray(arr); - } - - public static boolean fixedArrayAnyEmpty(Context cx, FixedLengthArray array) { - for (var t : array.initial()) { - if (Core.isEmpty(cx, t)) { - return true; - } - } - return false; - } - - public static Pair listIntersectWith(Env env, FixedLengthArray members1, SemType rest1, - FixedLengthArray members2, SemType rest2) { - - if (listLengthsDisjoint(members1, rest1, members2, rest2)) { - return null; - } - int max = Integer.max(members1.fixedLength(), members2.fixedLength()); - SemType[] initial = new SemType[max]; - for (int i = 0; i < max; i++) { - initial[i] = - intersectCellMemberSemTypes(env, listMemberAt(members1, rest1, i), - listMemberAt(members2, rest2, i)); - } - return Pair.from(FixedLengthArray.from(initial, - Integer.max(members1.fixedLength(), members2.fixedLength())), - intersectCellMemberSemTypes(env, rest1, rest2)); - } - - private static boolean listLengthsDisjoint(FixedLengthArray members1, SemType rest1, - FixedLengthArray members2, SemType rest2) { - int len1 = members1.fixedLength(); - int len2 = members2.fixedLength(); - if (len1 < len2) { - return Core.isNever(cellInnerVal(rest1)); - } - if (len2 < len1) { - return Core.isNever(cellInnerVal(rest2)); - } - return false; - } - - private static SemType listMemberAt(FixedLengthArray fixedArray, SemType rest, int index) { - if (index < fixedArray.fixedLength()) { - return fixedArrayGet(fixedArray, index); - } - return rest; - } - - private static SemType fixedArrayGet(FixedLengthArray members, int index) { - int memberLen = members.initial().length; - int i = Integer.min(index, memberLen - 1); - return members.initial()[i]; - } - - public static SemType listMemberAtInnerVal(FixedLengthArray fixedArray, SemType rest, int index) { - return cellInnerVal(listMemberAt(fixedArray, rest, index)); - } - - public static SemType bddListMemberTypeInnerVal(Context cx, Bdd b, SubTypeData key, SemType accum) { - if (b instanceof BddAllOrNothing allOrNothing) { - return allOrNothing.isAll() ? accum : Builder.getNeverType(); - } else { - BddNode bddNode = (BddNode) b; - return Core.union(bddListMemberTypeInnerVal(cx, bddNode.left(), key, - Core.intersect(listAtomicMemberTypeInnerVal(cx.listAtomType(bddNode.atom()), key), accum)), - Core.union(bddListMemberTypeInnerVal(cx, bddNode.middle(), key, accum), - bddListMemberTypeInnerVal(cx, bddNode.right(), key, accum))); - } - } - - private static SemType listAtomicMemberTypeInnerVal(ListAtomicType atomic, SubTypeData key) { - return Core.diff(listAtomicMemberTypeInner(atomic, key), Builder.getUndefType()); - } - - private static SemType listAtomicMemberTypeInner(ListAtomicType atomic, SubTypeData key) { - return listAtomicMemberTypeAtInner(atomic.members(), atomic.rest(), key); - } - - static SemType listAtomicMemberTypeAtInner(FixedLengthArray fixedArray, SemType rest, SubTypeData key) { - if (key instanceof BIntSubType.IntSubTypeData intSubtype) { - SemType m = Builder.getNeverType(); - int initLen = fixedArray.initial().length; - int fixedLen = fixedArray.fixedLength(); - if (fixedLen != 0) { - for (int i = 0; i < initLen; i++) { - if (intSubtypeContains(key, i)) { - m = Core.union(m, cellInner(fixedArrayGet(fixedArray, i))); - } - } - if (intSubtype.isRangeOverlap(new BIntSubType.Range(initLen, fixedLen - 1))) { - m = Core.union(m, cellInner(fixedArrayGet(fixedArray, fixedLen - 1))); - } - } - if (fixedLen == 0 || intSubtype.max() > fixedLen - 1) { - m = Core.union(m, cellInner(rest)); - } - return m; - } - SemType m = cellInner(rest); - if (fixedArray.fixedLength() > 0) { - for (SemType ty : fixedArray.initial()) { - m = Core.union(m, cellInner(ty)); - } - } - return m; - } - - @Override - public SubTypeData data() { - return inner(); - } - - @Override - public Bdd inner() { - return inner; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof BListSubType that)) { - return false; - } - return Objects.equals(inner, that.inner); - } - - @Override - public int hashCode() { - return Objects.hashCode(inner); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BMappingProj.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BMappingProj.java deleted file mode 100644 index 94f344aa1e85..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BMappingProj.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Bdd; -import io.ballerina.runtime.api.types.semtype.BddAllOrNothing; -import io.ballerina.runtime.api.types.semtype.BddNode; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.SemType; - -import java.util.ArrayList; -import java.util.List; - -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_MAPPING; -import static io.ballerina.runtime.api.types.semtype.Core.diff; -import static io.ballerina.runtime.api.types.semtype.Core.getComplexSubtypeData; -import static io.ballerina.runtime.api.types.semtype.Core.isNothingSubtype; -import static io.ballerina.runtime.api.types.semtype.Core.stringSubtype; - -/** - * Utility class for doing mapping type projection. - * - * @since 2201.11.0 - */ -public final class BMappingProj { - - private BMappingProj() { - } - - public static SemType mappingMemberTypeInnerVal(Context cx, SemType t, SemType k) { - return diff(mappingMemberTypeInner(cx, t, k), Builder.getUndefType()); - } - - // This computes the spec operation called "member type of K in T", - // for when T is a subtype of mapping, and K is either `string` or a singleton string. - // This is what Castagna calls projection. - public static SemType mappingMemberTypeInner(Context cx, SemType t, SemType k) { - if (t.some() == 0) { - return (t.all() & Builder.getMappingType().all()) != 0 ? Builder.getValType() : Builder.getUndefType(); - } else { - SubTypeData keyData = stringSubtype(k); - if (isNothingSubtype(keyData)) { - return Builder.getUndefType(); - } - return bddMappingMemberTypeInner(cx, (Bdd) getComplexSubtypeData(t, BT_MAPPING), keyData, - Builder.getInnerType()); - } - } - - static SemType bddMappingMemberTypeInner(Context cx, Bdd b, SubTypeData key, SemType accum) { - if (b instanceof BddAllOrNothing allOrNothing) { - return allOrNothing.isAll() ? accum : Builder.getNeverType(); - } else { - BddNode bdd = (BddNode) b; - return Core.union( - bddMappingMemberTypeInner(cx, bdd.left(), key, - Core.intersect(mappingAtomicMemberTypeInner(cx.mappingAtomType(bdd.atom()), key), - accum)), - Core.union(bddMappingMemberTypeInner(cx, bdd.middle(), key, accum), - bddMappingMemberTypeInner(cx, bdd.right(), key, accum))); - } - } - - static SemType mappingAtomicMemberTypeInner(MappingAtomicType atomic, SubTypeData key) { - SemType memberType = null; - for (SemType ty : mappingAtomicApplicableMemberTypesInner(atomic, key)) { - if (memberType == null) { - memberType = ty; - } else { - memberType = Core.union(memberType, ty); - } - } - return memberType == null ? Builder.getUndefType() : memberType; - } - - static List mappingAtomicApplicableMemberTypesInner(MappingAtomicType atomic, SubTypeData key) { - List types = new ArrayList<>(atomic.types().length); - for (SemType t : atomic.types()) { - types.add(Core.cellInner(t)); - } - - List memberTypes = new ArrayList<>(); - SemType rest = Core.cellInner(atomic.rest()); - if (isAllSubtype(key)) { - memberTypes.addAll(types); - memberTypes.add(rest); - } else { - BStringSubType.StringSubtypeListCoverage coverage = - ((BStringSubType.StringSubTypeData) key).stringSubtypeListCoverage(atomic.names()); - for (int index : coverage.indices()) { - memberTypes.add(types.get(index)); - } - if (!coverage.isSubType()) { - memberTypes.add(rest); - } - } - return memberTypes; - } - - static boolean isAllSubtype(SubTypeData d) { - return d == AllOrNothing.ALL; - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BMappingSubType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BMappingSubType.java deleted file mode 100644 index bc56809a3c66..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BMappingSubType.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Bdd; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Conjunction; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.FieldPair; -import io.ballerina.runtime.api.types.semtype.FieldPairs; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.SubType; - -import java.util.Arrays; -import java.util.Objects; - -import static io.ballerina.runtime.api.types.semtype.Bdd.bddEvery; - -/** - * Runtime representation of a subtype of mapping type. - * - * @since 2201.11.0 - */ -public class BMappingSubType extends SubType implements DelegatedSubType { - - public final Bdd inner; - - private BMappingSubType(Bdd inner) { - super(inner.isAll(), inner.isNothing()); - this.inner = inner; - } - - public static BMappingSubType createDelegate(SubType inner) { - if (inner instanceof Bdd bdd) { - return new BMappingSubType(bdd); - } else if (inner.isAll() || inner.isNothing()) { - throw new IllegalStateException("unimplemented"); - } else if (inner instanceof BMappingSubType bMapping) { - return new BMappingSubType(bMapping.inner); - } - throw new IllegalArgumentException("Unexpected inner type"); - } - - @Override - public Bdd inner() { - return inner; - } - - @Override - public SubType union(SubType other) { - if (!(other instanceof BMappingSubType otherMapping)) { - throw new IllegalArgumentException("union of different subtypes"); - } - return createDelegate(inner.union(otherMapping.inner)); - } - - @Override - public SubType intersect(SubType other) { - if (!(other instanceof BMappingSubType otherMapping)) { - throw new IllegalArgumentException("intersect of different subtypes"); - } - return createDelegate(inner.intersect(otherMapping.inner)); - } - - @Override - public SubType complement() { - return createDelegate(inner.complement()); - } - - @Override - public boolean isEmpty(Context cx) { - return cx.memoSubtypeIsEmpty(cx.mappingMemo, - (context, bdd) -> bddEvery(context, bdd, BMappingSubType::mappingFormulaIsEmpty), inner); - } - - static boolean mappingFormulaIsEmpty(Context cx, Conjunction posList, Conjunction negList) { - MappingAtomicType combined; - if (posList == null) { - combined = Builder.getMappingAtomicInner(); - } else { - // combine all the positive atoms using intersection - combined = cx.mappingAtomType(posList.atom()); - Conjunction p = posList.next(); - while (true) { - if (p == null) { - break; - } else { - MappingAtomicType m = - combined.intersectMapping(cx.env, cx.mappingAtomType(p.atom())); - if (m == null) { - return true; - } else { - combined = m; - } - p = p.next(); - } - } - for (SemType t : combined.types()) { - if (Core.isEmpty(cx, t)) { - return true; - } - } - - } - return !mappingInhabited(cx, combined, negList); - } - - private static boolean mappingInhabited(Context cx, MappingAtomicType pos, Conjunction negList) { - if (negList == null) { - return true; - } else { - MappingAtomicType neg = cx.mappingAtomType(negList.atom()); - - if (!Core.isEmpty(cx, Core.diff(pos.rest(), neg.rest()))) { - return mappingInhabited(cx, pos, negList.next()); - } - for (FieldPair fieldPair : new FieldPairs(pos, neg)) { - SemType intersect = Core.intersect(fieldPair.type1(), fieldPair.type2()); - // if types of at least one field are disjoint, the neg atom will not contribute to the next iteration. - // Therefore, we can skip the current neg atom. - // i.e. if we have isEmpty(T1 & S1) or isEmpty(T2 & S2) then, - // record { T1 f1; T2 f2; } / record { S1 f1; S2 f2; } = record { T1 f1; T2 f2; } - if (Core.isEmpty(cx, intersect)) { - return mappingInhabited(cx, pos, negList.next()); - } - - SemType d = Core.diff(fieldPair.type1(), fieldPair.type2()); - if (!Core.isEmpty(cx, d)) { - MappingAtomicType mt; - if (fieldPair.index1() == null) { - // the posType came from the rest type - mt = insertField(pos, fieldPair.name(), d); - } else { - SemType[] posTypes = pos.types().clone(); - posTypes[fieldPair.index1()] = d; - mt = new MappingAtomicType(pos.names(), posTypes, pos.rest()); - } - if (mappingInhabited(cx, mt, negList.next())) { - return true; - } - } - } - return false; - } - } - - private static MappingAtomicType insertField(MappingAtomicType m, String name, SemType t) { - String[] orgNames = m.names(); - String[] names = shallowCopyStrings(orgNames, orgNames.length + 1); - SemType[] orgTypes = m.types(); - SemType[] types = shallowCopySemTypes(orgTypes, orgTypes.length + 1); - int i = orgNames.length; - while (true) { - if (i == 0 || Common.codePointCompare(names[i - 1], name)) { - names[i] = name; - types[i] = t; - break; - } - names[i] = names[i - 1]; - types[i] = types[i - 1]; - i -= 1; - } - return new MappingAtomicType(names, types, m.rest()); - } - - static SemType[] shallowCopySemTypes(SemType[] v, int newLength) { - return Arrays.copyOf(v, newLength); - } - - private static String[] shallowCopyStrings(String[] v, int newLength) { - return Arrays.copyOf(v, newLength); - } - - @Override - public SubTypeData data() { - return inner(); - } - - @Override - public SubType diff(SubType other) { - if (!(other instanceof BMappingSubType otherList)) { - throw new IllegalArgumentException("diff of different subtypes"); - } - return createDelegate(inner.diff(otherList.inner)); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof BMappingSubType that)) { - return false; - } - return Objects.equals(inner, that.inner); - } - - @Override - public int hashCode() { - return Objects.hashCode(inner); - } - -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BObjectSubType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BObjectSubType.java deleted file mode 100644 index de6516a4086a..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BObjectSubType.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Bdd; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SubType; - -import java.util.Objects; - -import static io.ballerina.runtime.api.types.semtype.Bdd.bddEveryPositive; - -/** - * Runtime representation of a subtype of object type. - * - * @since 2201.11.0 - */ -public final class BObjectSubType extends SubType implements DelegatedSubType { - - public final Bdd inner; - - private BObjectSubType(Bdd inner) { - super(inner.isAll(), inner.isNothing()); - this.inner = inner; - } - - @Override - public SubType union(SubType other) { - if (!(other instanceof BObjectSubType otherObject)) { - throw new IllegalArgumentException("union of different subtypes"); - } - return createDelegate(inner.union(otherObject.inner)); - } - - @Override - public SubType intersect(SubType other) { - if (!(other instanceof BObjectSubType otherObject)) { - throw new IllegalArgumentException("intersect of different subtypes"); - } - return createDelegate(inner.intersect(otherObject.inner)); - } - - @Override - public SubType complement() { - return createDelegate(inner.complement()); - } - - @Override - public boolean isEmpty(Context cx) { - return cx.memoSubtypeIsEmpty(cx.mappingMemo, - (context, bdd) -> bddEveryPositive(context, bdd, null, null, BMappingSubType::mappingFormulaIsEmpty), - inner); - } - - @Override - public SubTypeData data() { - throw new UnsupportedOperationException("Method not implemented"); - } - - public static BObjectSubType createDelegate(SubType inner) { - if (inner instanceof Bdd bdd) { - return new BObjectSubType(bdd); - } else if (inner.isAll() || inner.isNothing()) { - throw new IllegalStateException("unimplemented"); - } else if (inner instanceof BObjectSubType bMapping) { - return new BObjectSubType(bMapping.inner); - } - throw new IllegalArgumentException("Unexpected inner type"); - } - - @Override - public Bdd inner() { - throw new UnsupportedOperationException("Method not implemented"); - } - - @Override - public SubType diff(SubType other) { - if (!(other instanceof BObjectSubType otherObject)) { - throw new IllegalArgumentException("diff of different subtypes"); - } - return createDelegate(inner.diff(otherObject.inner)); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof BObjectSubType that)) { - return false; - } - return Objects.equals(inner, that.inner); - } - - @Override - public int hashCode() { - return Objects.hashCode(inner); - } - -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BStreamSubType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BStreamSubType.java deleted file mode 100644 index c666b54ce417..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BStreamSubType.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Bdd; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SubType; - -import static io.ballerina.runtime.api.types.semtype.Bdd.bddEvery; - -/** - * Runtime representation of a subtype of stream type. - * - * @since 2201.11.0 - */ -public class BStreamSubType extends SubType implements DelegatedSubType { - - public final Bdd inner; - - private BStreamSubType(Bdd inner) { - super(inner.isAll(), inner.isNothing()); - this.inner = inner; - } - - public static BStreamSubType createDelegate(SubType inner) { - if (inner instanceof Bdd bdd) { - return new BStreamSubType(bdd); - } else if (inner.isAll() || inner.isNothing()) { - throw new IllegalStateException("unimplemented"); - } else if (inner instanceof BStreamSubType bStreamSubType) { - return new BStreamSubType(bStreamSubType.inner); - } - throw new IllegalArgumentException("Unexpected inner type"); - } - - @Override - public SubType union(SubType other) { - if (!(other instanceof BStreamSubType otherStream)) { - throw new IllegalArgumentException("union of different subtypes"); - } - return createDelegate(inner.union(otherStream.inner)); - } - - @Override - public SubType intersect(SubType other) { - if (!(other instanceof BStreamSubType otherStream)) { - throw new IllegalArgumentException("intersect of different subtypes"); - } - return createDelegate(inner.intersect(otherStream.inner)); - } - - @Override - public SubType complement() { - return createDelegate(Builder.getListSubtypeTwoElement().diff(inner)); - } - - @Override - public boolean isEmpty(Context cx) { - Bdd b = inner; - // The goal of this is to ensure that listSubtypeIsEmpty call beneath does - // not get an empty posList, because it will interpret that - // as `[any|error...]` rather than `[any|error, any|error]`. - b = b.posMaybeEmpty() ? (Bdd) b.intersect(Builder.getListSubtypeTwoElement()) : b; - return cx.memoSubtypeIsEmpty(cx.listMemo, - (context, bdd) -> bddEvery(context, bdd, BListSubType::listFormulaIsEmpty), b); - } - - @Override - public SubTypeData data() { - return inner(); - } - - @Override - public Bdd inner() { - return inner; - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BStringSubType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BStringSubType.java deleted file mode 100644 index 0527874f61f1..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BStringSubType.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SubType; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; - -/** - * Runtime representation of subtype of string type. - * - * @since 2201.11.0 - */ -public final class BStringSubType extends SubType { - - final SubTypeData data; - private static final BStringSubType ALL = new BStringSubType(AllOrNothing.ALL); - private static final BStringSubType NOTHING = new BStringSubType(AllOrNothing.NOTHING); - - private BStringSubType(SubTypeData data) { - super(data == AllOrNothing.ALL, data == AllOrNothing.NOTHING); - this.data = data; - } - - public static BStringSubType createStringSubType(boolean charsAllowed, String[] chars, boolean nonCharsAllowed, - String[] nonChars) { - if (chars.length == 0 && nonChars.length == 0) { - if (!charsAllowed && !nonCharsAllowed) { - return ALL; - } else if (charsAllowed && nonCharsAllowed) { - return NOTHING; - } - } - Arrays.sort(chars); - Arrays.sort(nonChars); - ValueData charValues = new ValueData(charsAllowed, chars); - ValueData nonCharValues = new ValueData(nonCharsAllowed, nonChars); - StringSubTypeData data = new StringSubTypeData(charValues, nonCharValues); - return new BStringSubType(data); - } - - @Override - public String toString() { - if (data instanceof StringSubTypeData stringSubTypeData) { - var chars = stringSubTypeData.chars; - var nonChars = stringSubTypeData.nonChars; - if (chars.allowed && chars.values.length > 0 && nonChars.allowed && nonChars.values.length == 0) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < chars.values.length; i++) { - if (i > 0) { - sb.append(", "); - } - sb.append(chars.values[i]); - } - return sb.toString(); - } else if (nonChars.allowed && nonChars.values.length > 0 && chars.allowed && chars.values.length == 0) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < nonChars.values.length; i++) { - if (i > 0) { - sb.append(", "); - } - sb.append(nonChars.values[i]); - } - return sb.toString(); - } - } - return "string"; - } - - @Override - public SubType union(SubType otherSubType) { - BStringSubType other = (BStringSubType) otherSubType; - // TODO: refactor - if (this.data instanceof AllOrNothing || other.data instanceof AllOrNothing) { - if (this.data == AllOrNothing.ALL) { - return this; - } else if (other.data == AllOrNothing.ALL) { - return other; - } else if (this.data == AllOrNothing.NOTHING) { - return other; - } else if (other.data == AllOrNothing.NOTHING) { - return this; - } - throw new IllegalStateException("unreachable"); - } - StringSubTypeData data = (StringSubTypeData) this.data; - StringSubTypeData otherData = (StringSubTypeData) other.data; - List chars = new ArrayList<>(); - boolean charsAllowed = data.chars.union(otherData.chars, chars); - List nonChars = new ArrayList<>(); - boolean nonCharsAllowed = data.nonChars.union(otherData.nonChars, nonChars); - return createStringSubType(charsAllowed, chars.toArray(String[]::new), nonCharsAllowed, - nonChars.toArray(String[]::new)); - } - - @Override - public SubType intersect(SubType otherSubtype) { - BStringSubType other = (BStringSubType) otherSubtype; - if (this.data instanceof AllOrNothing) { - if (this.data == AllOrNothing.ALL) { - return other; - } else { - return NOTHING; - } - } else if (other.data instanceof AllOrNothing) { - if (other.data == AllOrNothing.ALL) { - return this; - } else { - return NOTHING; - } - } - StringSubTypeData data = (StringSubTypeData) this.data; - StringSubTypeData otherData = (StringSubTypeData) other.data; - List chars = new ArrayList<>(); - boolean charsAllowed = data.chars.intersect(otherData.chars, chars); - List nonChars = new ArrayList<>(); - boolean nonCharsAllowed = data.nonChars.intersect(otherData.nonChars, nonChars); - return createStringSubType(charsAllowed, chars.toArray(String[]::new), nonCharsAllowed, - nonChars.toArray(String[]::new)); - } - - @Override - public SubType complement() { - if (data instanceof AllOrNothing) { - if (data == AllOrNothing.ALL) { - return NOTHING; - } else { - return ALL; - } - } - StringSubTypeData stringData = (StringSubTypeData) data; - ValueData chars = stringData.chars; - ValueData nonChars = stringData.nonChars; - return createStringSubType(!chars.allowed, chars.values, !nonChars.allowed, nonChars.values); - } - - @Override - public boolean isEmpty(Context cx) { - return data == AllOrNothing.NOTHING; - } - - @Override - public SubTypeData data() { - return data; - } - - static void stringListIntersect(String[] values, String[] target, List indices) { - int i1 = 0; - int i2 = 0; - int len1 = values.length; - int len2 = target.length; - while (true) { - if (i1 >= len1 || i2 >= len2) { - break; - } else { - switch (compareStrings(values[i1], target[i2])) { - case EQ: - indices.add(i1); - i1 += 1; - i2 += 1; - break; - case LT: - i1 += 1; - break; - case GT: - i2 += 1; - break; - default: - throw new AssertionError("Invalid comparison value!"); - } - } - } - } - - private static ComparisonResult compareStrings(String s1, String s2) { - return Objects.equals(s1, s2) ? ComparisonResult.EQ : - (Common.codePointCompare(s1, s2) ? ComparisonResult.LT : ComparisonResult.GT); - } - - private enum ComparisonResult { - EQ, - LT, - GT - } - - record StringSubTypeData(ValueData chars, ValueData nonChars) implements SubTypeData { - - StringSubtypeListCoverage stringSubtypeListCoverage(String[] values) { - List indices = new ArrayList<>(); - ValueData ch = chars(); - ValueData nonChar = nonChars(); - int stringConsts = 0; - if (ch.allowed) { - stringListIntersect(values, ch.values, indices); - stringConsts = ch.values.length; - } else if (ch.values.length == 0) { - for (int i = 0; i < values.length; i++) { - if (values[i].length() == 1) { - indices.add(i); - } - } - } - if (nonChar.allowed) { - stringListIntersect(values, nonChar.values, indices); - stringConsts += nonChar.values.length; - } else if (nonChar.values.length == 0) { - for (int i = 0; i < values.length; i++) { - if (values[i].length() != 1) { - indices.add(i); - } - } - } - int[] inds = indices.stream().mapToInt(i -> i).toArray(); - return new StringSubtypeListCoverage(stringConsts == indices.size(), inds); - } - } - - record StringSubtypeListCoverage(boolean isSubType, int[] indices) { - - } - - static final class ValueData extends EnumerableSubtypeData { - - private final boolean allowed; - private final String[] values; - - // NOTE: this assumes values are sorted - private ValueData(boolean allowed, String[] values) { - this.allowed = allowed; - this.values = values; - } - - @Override - public boolean allowed() { - return allowed; - } - - @Override - public String[] values() { - return values; - } - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BTableSubType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BTableSubType.java deleted file mode 100644 index 91243d618228..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BTableSubType.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Bdd; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SubType; - -import java.util.Objects; - -import static io.ballerina.runtime.api.types.semtype.Bdd.bddEvery; - -/** - * Represents the subtype of a table type. - * - * @since 2201.11.0 - */ -public final class BTableSubType extends SubType implements DelegatedSubType { - - private final Bdd inner; - - private BTableSubType(Bdd inner) { - super(inner.isAll(), inner.isNothing()); - this.inner = inner; - } - - public static BTableSubType createDelegate(SubType inner) { - if (inner instanceof Bdd bdd) { - return new BTableSubType(bdd); - } else if (inner.isAll() || inner.isNothing()) { - throw new IllegalStateException("unimplemented"); - } else if (inner instanceof BTableSubType other) { - return new BTableSubType(other.inner); - } - throw new IllegalArgumentException("Unexpected inner type"); - } - - @Override - public SubType union(SubType other) { - if (!(other instanceof BTableSubType otherTable)) { - throw new IllegalArgumentException("union of different subtypes"); - } - return createDelegate(inner.union(otherTable.inner)); - } - - @Override - public SubType intersect(SubType other) { - if (!(other instanceof BTableSubType otherTable)) { - throw new IllegalArgumentException("intersect of different subtypes"); - } - return createDelegate(inner.intersect(otherTable.inner)); - } - - @Override - public SubType complement() { - return createDelegate(Builder.getListSubtypeThreeElement().diff(inner)); - } - - @Override - public boolean isEmpty(Context cx) { - Bdd b = inner; - // The goal of this is to ensure that listSubtypeIsEmpty call beneath does - // not get an empty posList, because it will interpret that - // as `(any|error)[]` rather than `[(map)[], any|error, any|error]`. - b = b.posMaybeEmpty() ? (Bdd) b.intersect(Builder.getListSubtypeThreeElement()) : b; - return cx.memoSubtypeIsEmpty(cx.listMemo, - (context, bdd) -> bddEvery(context, bdd, BListSubType::listFormulaIsEmpty), b); - } - - @Override - public SubTypeData data() { - throw new UnsupportedOperationException("Not implemented"); - } - - @Override - public SubType inner() { - throw new UnsupportedOperationException("Not implemented"); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof BTableSubType other)) { - return false; - } - return inner.equals(other.inner); - } - - @Override - public int hashCode() { - return Objects.hash(inner); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BTypedescSubType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BTypedescSubType.java deleted file mode 100644 index b8b0e91212a3..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BTypedescSubType.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Bdd; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SubType; - -import java.util.Objects; - -import static io.ballerina.runtime.api.types.semtype.Bdd.bddEveryPositive; - -/** - * Represents the subtype of a typedesc type. - * - * @since 2201.11.0 - */ -public class BTypedescSubType extends SubType implements DelegatedSubType { - - private final Bdd inner; - - private BTypedescSubType(Bdd inner) { - super(inner.isAll(), inner.isNothing()); - this.inner = inner; - } - - public static BTypedescSubType createDelegate(SubType inner) { - if (inner instanceof Bdd bdd) { - return new BTypedescSubType(bdd); - } else if (inner.isAll() || inner.isNothing()) { - throw new IllegalStateException("unimplemented"); - } else if (inner instanceof BTypedescSubType other) { - return new BTypedescSubType(other.inner); - } - throw new IllegalArgumentException("Unexpected inner type"); - } - - @Override - public SubType union(SubType other) { - if (!(other instanceof BTypedescSubType otherTypedesc)) { - throw new IllegalArgumentException("union of different subtypes"); - } - return createDelegate(inner.union(otherTypedesc.inner)); - } - - @Override - public SubType intersect(SubType other) { - if (!(other instanceof BTypedescSubType otherTypedesc)) { - throw new IllegalArgumentException("union of different subtypes"); - } - return createDelegate(inner.intersect(otherTypedesc.inner)); - } - - @Override - public SubType complement() { - return createDelegate(Builder.getBddSubtypeRo().diff(inner)); - } - - @Override - public boolean isEmpty(Context cx) { - Bdd b = inner; - // The goal of this is to ensure that mappingFormulaIsEmpty call in errorBddIsEmpty beneath - // does not get an empty posList, because it will interpret that - // as `map` rather than `readonly & map`. - b = b.posMaybeEmpty() ? (Bdd) b.intersect(Builder.getBddSubtypeRo()) : b; - return cx.memoSubtypeIsEmpty(cx.mappingMemo, BTypedescSubType::typedescBddIsEmpty, b); - } - - private static boolean typedescBddIsEmpty(Context cx, Bdd b) { - return bddEveryPositive(cx, b, null, null, BMappingSubType::mappingFormulaIsEmpty); - } - - @Override - public SubTypeData data() { - throw new UnsupportedOperationException("Not implemented"); - } - - @Override - public SubType inner() { - throw new UnsupportedOperationException("Not implemented"); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof BTypedescSubType other)) { - return false; - } - return Objects.equals(inner, other.inner); - } - - @Override - public int hashCode() { - return Objects.hash(inner); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BXmlSubType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BXmlSubType.java deleted file mode 100644 index 35479680eb62..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BXmlSubType.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Bdd; -import io.ballerina.runtime.api.types.semtype.Conjunction; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.RecAtom; -import io.ballerina.runtime.api.types.semtype.SubType; - -import java.util.Objects; - -/** - * Represents the subtype of an XML type. - * - * @since 2201.11.0 - */ -public class BXmlSubType extends SubType implements DelegatedSubType { - - public final Bdd inner; - private final int primitives; - - private BXmlSubType(Bdd inner, int primitives) { - super(false, false); - this.inner = inner; - this.primitives = primitives; - } - - public static BXmlSubType createDelegate(int primitives, SubType inner) { - if (inner instanceof Bdd bdd) { - return new BXmlSubType(bdd, primitives); - } else if (inner instanceof BXmlSubType bXml) { - return new BXmlSubType(bXml.inner, primitives); - } - throw new IllegalArgumentException("Unexpected inner type"); - } - - @Override - public SubType union(SubType other) { - BXmlSubType otherXml = (BXmlSubType) other; - int primitives = this.primitives() | otherXml.primitives(); - return createDelegate(primitives, inner.union(otherXml.inner)); - } - - @Override - public SubType intersect(SubType other) { - BXmlSubType otherXml = (BXmlSubType) other; - int primitives = this.primitives() & otherXml.primitives(); - return createDelegate(primitives, inner.intersect(otherXml.inner)); - } - - @Override - public SubType diff(SubType other) { - BXmlSubType otherXml = (BXmlSubType) other; - return diff(this, otherXml); - } - - private static SubType diff(BXmlSubType st1, BXmlSubType st2) { - int primitives = st1.primitives() & ~st2.primitives(); - return createDelegate(primitives, st1.inner.diff(st2.inner)); - } - - @Override - public SubType complement() { - return diff((BXmlSubType) XmlUtils.XML_SUBTYPE_TOP, this); - } - - @Override - public boolean isEmpty(Context cx) { - if (primitives() != 0) { - return false; - } - return xmlBddEmpty(cx); - } - - private boolean xmlBddEmpty(Context cx) { - return Bdd.bddEvery(cx, inner, BXmlSubType::xmlFormulaIsEmpty); - } - - private static boolean xmlFormulaIsEmpty(Context cx, Conjunction pos, Conjunction neg) { - int allPosBits = collectAllPrimitives(pos) & XmlUtils.XML_PRIMITIVE_ALL_MASK; - return xmlHasTotalNegative(allPosBits, neg); - } - - private static boolean xmlHasTotalNegative(int allPosBits, Conjunction conjunction) { - if (allPosBits == 0) { - return true; - } - Conjunction n = conjunction; - while (n != null) { - if ((allPosBits & ~getIndex(n)) == 0) { - return true; - } - n = n.next(); - } - return false; - } - - private static int collectAllPrimitives(Conjunction conjunction) { - int bits = 0; - Conjunction current = conjunction; - while (current != null) { - bits &= getIndex(current); - current = current.next(); - } - return bits; - } - - private static int getIndex(Conjunction conjunction) { - var atom = conjunction.atom(); - assert atom instanceof RecAtom; - return atom.index(); - } - - @Override - public SubTypeData data() { - return this; - } - - @Override - public SubType inner() { - return this; - } - - int primitives() { - return primitives; - } - - Bdd bdd() { - return inner; - } - - @Override - public int hashCode() { - return Objects.hash(inner, primitives); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof BXmlSubType other)) { - return false; - } - return Objects.equals(bdd(), other.bdd()) && primitives() == other.primitives(); - } - -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BddMemo.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BddMemo.java deleted file mode 100644 index 739117d179f5..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/BddMemo.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import java.util.Objects; -import java.util.Optional; - -/** - * Represents the memoization emptiness of a BDD used in Context. - * - * @since 2201.11.0 - */ -public final class BddMemo { - - public Status isEmpty; - - public BddMemo() { - this.isEmpty = Status.NULL; - } - - public enum Status { - // We know where this BDD is empty or not - TRUE, - FALSE, - // There is some recursive part in this type - LOOP, - CYCLIC, - // We are in the process of determining if this BDD is empty or not - PROVISIONAL, - // We just initialized the node, treated to be same as not having a memo - NULL - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof BddMemo bddMemo)) { - return false; - } - return isEmpty == bddMemo.isEmpty; - } - - @Override - public int hashCode() { - return Objects.hashCode(isEmpty); - } - - public Optional isEmpty() { - return switch (isEmpty) { - // Cyclic types are empty because we define types inductively - case TRUE, CYCLIC -> Optional.of(true); - case FALSE -> Optional.of(false); - case LOOP, PROVISIONAL -> { - // If it was provisional we came from a back edge - // Again we treat the loop part as empty - isEmpty = Status.LOOP; - yield Optional.of(true); - } - case NULL -> Optional.empty(); - }; - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/CellAtomicType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/CellAtomicType.java deleted file mode 100644 index 8e75f75af7b6..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/CellAtomicType.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Atom; -import io.ballerina.runtime.api.types.semtype.AtomicType; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.TypeAtom; - -import java.util.HashMap; -import java.util.Map; - -/** - * CellAtomicType node. - * - * @param ty Type "wrapped" by this cell - * @param mut Mutability of the cell - * @since 2201.11.0 - */ -public record CellAtomicType(SemType ty, CellMutability mut) implements AtomicType { - - public CellAtomicType { - assert ty != null; - } - - public static CellAtomicType from(SemType ty, CellMutability mut) { - return CellAtomCache.get(ty, mut); - } - - public static CellAtomicType intersectCellAtomicType(CellAtomicType c1, CellAtomicType c2) { - SemType ty = Core.intersect(c1.ty(), c2.ty()); - CellMutability mut = min(c1.mut(), c2.mut()); - return CellAtomicType.from(ty, mut); - } - - private static CellMutability min(CellMutability m1, - CellMutability m2) { - return m1.compareTo(m2) <= 0 ? m1 : m2; - } - - public static CellAtomicType cellAtomType(Atom atom) { - return (CellAtomicType) ((TypeAtom) atom).atomicType(); - } - - public enum CellMutability { - CELL_MUT_NONE, - CELL_MUT_LIMITED, - CELL_MUT_UNLIMITED - } - - private static final class CellAtomCache { - - private static final Map NONE_CACHE = new HashMap<>(); - private static final Map LIMITED_CACHE = new HashMap<>(); - private static final Map UNLIMITED_CACHE = new HashMap<>(); - - private static CellAtomicType get(SemType semType, CellMutability mut) { - if (semType.some() != 0) { - return new CellAtomicType(semType, mut); - } - int key = semType.all(); - return switch (mut) { - case CELL_MUT_NONE -> NONE_CACHE.computeIfAbsent(key, (ignored) -> new CellAtomicType(semType, mut)); - case CELL_MUT_LIMITED -> - LIMITED_CACHE.computeIfAbsent(key, (ignored) -> new CellAtomicType(semType, mut)); - case CELL_MUT_UNLIMITED -> - UNLIMITED_CACHE.computeIfAbsent(key, (ignored) -> new CellAtomicType(semType, mut)); - }; - } - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/Common.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/Common.java deleted file mode 100644 index 8d057aa5e4ef..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/Common.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package io.ballerina.runtime.internal.types.semtype; - -/** - * Utility class for various operations related to semantic types. - * - * @since 2201.11.0 - */ -public final class Common { - - private Common() { - } - - public static boolean codePointCompare(String s1, String s2) { - if (s1.equals(s2)) { - return false; - } - int len1 = s1.length(); - int len2 = s2.length(); - if (len1 < len2 && s2.substring(0, len1).equals(s1)) { - return true; - } - int cpCount1 = s1.codePointCount(0, len1); - int cpCount2 = s2.codePointCount(0, len2); - for (int cp = 0; cp < cpCount1 && cp < cpCount2; ) { - int codepoint1 = s1.codePointAt(cp); - int codepoint2 = s2.codePointAt(cp); - if (codepoint1 == codepoint2) { - cp++; - continue; - } - return codepoint1 < codepoint2; - } - return false; - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/DefinitionContainer.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/DefinitionContainer.java deleted file mode 100644 index 2b4373a2de5e..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/DefinitionContainer.java +++ /dev/null @@ -1,111 +0,0 @@ -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Definition; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.SemType; - -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.function.Supplier; - -/** - * Container used to maintain concurrency invariants when creating a potentially recursive semtype. - * - * It maintains fallowing invariants. - * 1. When the type is being defined only the thread that is defining the type may proceed - * 2. After definition is completed any number of threads may proceed concurrently In order to achieve this container - * has three phases (init, defining, defined). At init phase (that is no definition has been set) any number of threads - * may proceed concurrently. When a thread sets a definition {@code setDefinition} container enters the defining phase. - * In that phase only that thread may continue in {@code getSemType} method (this is to allow for recursive type - * definitions). Container registers with the {@code Definition} using {@code registerContainer} method. When the - * {@code Definition} has been defined (ie. {@code Env} has an atom corresponding to the definition) it must notify the - * container using {@code definitionUpdated} method. At this point container moves to defined phase allowing concurrent - * access to {@code getSemType}. - * - * @param type of the definition - * @since 2201.11.0 - */ -public class DefinitionContainer { - - private final ReadWriteLock rwLock = new ReentrantReadWriteLock(); - private volatile E definition; - - private final ReentrantLock recTypeLock = new ReentrantLock(); - private volatile boolean isDefining = false; - - public boolean isDefinitionReady() { - try { - rwLock.readLock().lock(); - return definition != null; - } finally { - rwLock.readLock().unlock(); - } - } - - public SemType getSemType(Env env) { - try { - rwLock.readLock().lock(); - // We don't need this check to be synchronized since {@code trySetDefinition} will hold the write lock until - // it completes, So isDefining should always be at a consistent state - if (isDefining) { - // This should prevent threads other than the defining thread to access the rec atom. - recTypeLock.lock(); - } - return definition.getSemType(env); - } finally { - rwLock.readLock().unlock(); - } - } - - public DefinitionUpdateResult trySetDefinition(Supplier supplier) { - try { - rwLock.writeLock().lock(); - boolean updated; - E newDefinition; - if (this.definition != null) { - updated = false; - newDefinition = null; - } else { - updated = true; - newDefinition = supplier.get(); - newDefinition.registerContainer(this); - this.recTypeLock.lock(); - isDefining = true; - this.definition = newDefinition; - } - return new DefinitionUpdateResult<>(newDefinition, updated); - } finally { - rwLock.writeLock().unlock(); - } - } - - public void clear() { - try { - rwLock.writeLock().lock(); - // This shouldn't happen because defining thread should hold the lock. - assert !isDefining; - this.definition = null; - } finally { - rwLock.writeLock().unlock(); - } - } - - public void definitionUpdated() { - recTypeLock.unlock(); - isDefining = false; - } - - /** - * Result of trying to update the definition. - * - * @param Type of the definition - * @param updated If update was successful. If this failed you must get the semtype using the {@code getSemType} - * method of the container - * @param definition If update was successful this will be the new definition. Otherwise, this will be null - * @since 2201.11.0 - */ - public record DefinitionUpdateResult(E definition, boolean updated) { - - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/EnumerableSubtypeData.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/EnumerableSubtypeData.java deleted file mode 100644 index 4f8429d51f1f..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/EnumerableSubtypeData.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * / - * - */ - -package io.ballerina.runtime.internal.types.semtype; - -import java.util.Arrays; -import java.util.List; - -/** - * All {@code SubTypeData} where we can enumerate individual values must extend - * this class. It will provide common operations such as {@code union}, - * {@code intersect} and {@code diff} for all such data. - * - * @param type individual value in the subset - * @since 2201.11.0 - */ -public abstract class EnumerableSubtypeData> { - - public abstract boolean allowed(); - - public abstract E[] values(); - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof EnumerableSubtypeData other)) { - return false; - } - return other.allowed() == this.allowed() && Arrays.equals(other.values(), this.values()); - } - - @Override - public int hashCode() { - return super.hashCode(); - } - - boolean union(EnumerableSubtypeData other, List results) { - boolean b1 = this.allowed(); - boolean b2 = other.allowed(); - if (b1 && b2) { - enumerableListUnion(this.values(), other.values(), results); - return true; - } else if (!b1 && !b2) { - enumerableListIntersection(this.values(), other.values(), results); - return false; - } else if (b1 && !b2) { - enumerableListDiff(other.values(), this.values(), results); - return false; - } else { - enumerableListDiff(this.values(), other.values(), results); - return false; - } - } - - boolean intersect(EnumerableSubtypeData other, List results) { - boolean b1 = this.allowed(); - boolean b2 = other.allowed(); - if (b1 && b2) { - enumerableListIntersection(this.values(), other.values(), results); - return true; - } else if (!b1 && !b2) { - enumerableListUnion(this.values(), other.values(), results); - return false; - } else if (b1 && !b2) { - enumerableListDiff(this.values(), other.values(), results); - return true; - } else { - enumerableListDiff(other.values(), this.values(), results); - return true; - } - } - - private static > void enumerableListUnion(E[] values1, E[] values2, List results) { - int i1, i2; - i1 = i2 = 0; - int len1 = values1.length; - int len2 = values2.length; - while (true) { - if (i1 >= len1) { - if (i2 >= len2) { - break; - } - results.add(values2[i2]); - i2 += 1; - } else if (i2 >= len2) { - results.add(values1[i1]); - i1 += 1; - } else { - E s1 = values1[i1]; - E s2 = values2[i2]; - int result = s1.compareTo(s2); - if (result == 0) { - results.add(s1); - i1 += 1; - i2 += 1; - } else if (result < 0) { - results.add(s1); - i1 += 1; - } else { - results.add(s2); - i2 += 1; - } - } - } - } - - private static > void enumerableListIntersection(E[] v1, E[] v2, List results) { - int i1, i2; - i1 = i2 = 0; - int len1 = v1.length; - int len2 = v2.length; - while (true) { - // TODO: refactor condition - if (i1 >= len1 || i2 >= len2) { - break; - } else { - E s1 = v1[i1]; - E s2 = v2[i2]; - int result = s1.compareTo(s2); - if (result == 0) { - results.add(s1); - i1 += 1; - i2 += 1; - } else if (result < 0) { - i1 += 1; - } else { - i2 += 1; - } - } - } - } - - private static > void enumerableListDiff(E[] t1, E[] t2, List results) { - int i1, i2; - i1 = i2 = 0; - int len1 = t1.length; - int len2 = t2.length; - while (true) { - if (i1 >= len1) { - break; - } - if (i2 >= len2) { - results.add(t1[i1]); - i1 += 1; - } else { - E s1 = t1[i1]; - E s2 = t2[i2]; - int result = s1.compareTo(s2); - if (result == 0) { - i1 += 1; - i2 += 1; - } else if (result < 0) { - results.add(s1); - i1 += 1; - } else { - i2 += 1; - } - } - } - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/ErrorUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/ErrorUtils.java deleted file mode 100644 index 870fae6f4e7a..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/ErrorUtils.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Bdd; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.SubType; - -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_ERROR; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_MAPPING; -import static io.ballerina.runtime.api.types.semtype.BddNode.bddAtom; -import static io.ballerina.runtime.api.types.semtype.Builder.basicSubType; -import static io.ballerina.runtime.api.types.semtype.RecAtom.createDistinctRecAtom; - -/** - * Utility methods for creating error types. - * - * @since 2201.11.0 - */ -public final class ErrorUtils { - - private ErrorUtils() { - } - - public static SemType errorDetail(SemType detail) { - SubTypeData data = Core.subTypeData(detail, BT_MAPPING); - if (data == AllOrNothing.ALL) { - return Builder.getErrorType(); - } else if (data == AllOrNothing.NOTHING) { - return Builder.getNeverType(); - } - - assert data instanceof Bdd; - SubType sd = ((Bdd) data).intersect(Builder.getBddSubtypeRo()); - if (sd.equals(Builder.getBddSubtypeRo())) { - return Builder.getErrorType(); - } - return basicSubType(BT_ERROR, BErrorSubType.createDelegate(sd)); - } - - public static SemType errorDistinct(int distinctId) { - assert distinctId >= 0; - Bdd bdd = bddAtom(createDistinctRecAtom(-distinctId - 1)); - return basicSubType(BT_ERROR, BErrorSubType.createDelegate(bdd)); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/FixedLengthArray.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/FixedLengthArray.java deleted file mode 100644 index 8284a390a38b..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/FixedLengthArray.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.SemType; - -import java.util.Arrays; -import java.util.Objects; - -/** - * Represents required member part of a list atom. - * - * @since 2201.11.0 - */ -public final class FixedLengthArray { - - // We have a separate fixedLength so types such as {@code byte[500]} don't need to store 500 elements - // in {@code initial}. - private final SemType[] initial; - private final int fixedLength; - private Integer hashCode; - - private FixedLengthArray(SemType[] initial, int fixedLength) { - for (SemType semType : initial) { - if (semType == null) { - throw new IllegalArgumentException("initial members can't be null"); - } - } - this.initial = initial; - this.fixedLength = fixedLength; - } - - public static FixedLengthArray from(SemType[] initial, int fixedLength) { - return new FixedLengthArray(initial, fixedLength); - } - - private static final FixedLengthArray EMPTY = new FixedLengthArray(new SemType[0], 0); - - static FixedLengthArray normalized(SemType[] initial, int fixedLength) { - if (initial.length < 2) { - return new FixedLengthArray(initial, fixedLength); - } - int i = initial.length - 1; - SemType last = initial[i]; - i -= 1; - while (i >= 0) { - if (last != initial[i]) { - break; - } - i -= 1; - } - int length = Integer.max(1, i + 2); - SemType[] buffer = new SemType[length]; - if (length == 1) { - buffer[0] = last; - } else { - System.arraycopy(initial, 0, buffer, 0, length); - } - return new FixedLengthArray(buffer, fixedLength); - } - - public static FixedLengthArray empty() { - return EMPTY; - } - - public FixedLengthArray shallowCopy() { - // TODO: may be create a copy of write array instead - return new FixedLengthArray(initial.clone(), fixedLength); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof FixedLengthArray that)) { - return false; - } - return fixedLength == that.fixedLength && Objects.deepEquals(initial, that.initial); - } - - @Override - public int hashCode() { - Integer result = hashCode; - if (result == null) { - synchronized (this) { - result = hashCode; - if (result == null) { - hashCode = result = computeHashCode(); - } - } - } - return result; - } - - private int computeHashCode() { - return Objects.hash(Arrays.hashCode(initial), fixedLength); - } - - public int fixedLength() { - return fixedLength; - } - - public SemType[] initial() { - return initial; - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/FunctionAtomicType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/FunctionAtomicType.java deleted file mode 100644 index 349ca151de59..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/FunctionAtomicType.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.AtomicType; -import io.ballerina.runtime.api.types.semtype.SemType; - -/** - * Represents a function atomic type. - * - * @param paramType function parameters. This is a list type - * @param retType return type - * @param qualifiers function qualifiers. This is a list type - * @since 2201.11.0 - */ -public record FunctionAtomicType(SemType paramType, SemType retType, SemType qualifiers) implements AtomicType { - -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/FunctionDefinition.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/FunctionDefinition.java deleted file mode 100644 index 4878cbe1f717..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/FunctionDefinition.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Atom; -import io.ballerina.runtime.api.types.semtype.BasicTypeCode; -import io.ballerina.runtime.api.types.semtype.BddNode; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Definition; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.RecAtom; -import io.ballerina.runtime.api.types.semtype.SemType; - -/** - * {@code Definition} used to create function subtypes. - * - * @since 2201.11.0 - */ -public class FunctionDefinition extends Definition { - - private volatile RecAtom rec; - private volatile SemType semType; - - @Override - public SemType getSemType(Env env) { - if (this.semType != null) { - return this.semType; - } else { - RecAtom rec = env.recFunctionAtom(); - this.rec = rec; - return this.createSemType(rec); - } - } - - private SemType createSemType(Atom atom) { - BddNode bdd = BddNode.bddAtom(atom); - SemType semType = Builder.basicSubType(BasicTypeCode.BT_FUNCTION, BFunctionSubType.createDelegate(bdd)); - this.semType = semType; - return semType; - } - - public SemType define(Env env, SemType args, SemType ret, FunctionQualifiers qualifiers) { - FunctionAtomicType atomicType = new FunctionAtomicType(args, ret, qualifiers.toSemType(env)); - RecAtom rec = this.rec; - Atom atom; - if (rec != null) { - atom = rec; - env.setRecFunctionAtomType(rec, atomicType); - } else { - atom = env.functionAtom(atomicType); - } - SemType semType = this.createSemType(atom); - notifyContainer(); - return semType; - } - -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/FunctionQualifiers.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/FunctionQualifiers.java deleted file mode 100644 index 0b90e9bad41d..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/FunctionQualifiers.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.SemType; - -/** - * Represents the qualifiers of a function. - * - * @since 2201.11.0 - */ -public final class FunctionQualifiers { - - private static final FunctionQualifiers DEFAULT = new FunctionQualifiers(false, false); - private final boolean isolated; - private final boolean transactional; - private SemType semType; - - private FunctionQualifiers(boolean isolated, boolean transactional) { - this.isolated = isolated; - this.transactional = transactional; - } - - public static FunctionQualifiers create(boolean isolated, boolean transactional) { - if (!isolated && !transactional) { - return DEFAULT; - } - return new FunctionQualifiers(isolated, transactional); - } - - synchronized SemType toSemType(Env env) { - if (semType == null) { - ListDefinition ld = new ListDefinition(); - SemType[] members = { - isolated ? Builder.getBooleanConst(true) : Builder.getBooleanType(), - transactional ? Builder.getBooleanType() : Builder.getBooleanConst(false) - }; - semType = ld.defineListTypeWrapped(env, members, 2, Builder.getNeverType(), - CellAtomicType.CellMutability.CELL_MUT_NONE); - } - return semType; - } - - public boolean isolated() { - return isolated; - } - - public boolean transactional() { - return transactional; - } - - @Override - public String toString() { - return "FunctionQualifiers[" + - "isolated=" + isolated + ", " + - "transactional=" + transactional + ']'; - } - -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/FutureUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/FutureUtils.java deleted file mode 100644 index 8c927ac0b442..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/FutureUtils.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.BasicTypeCode; -import io.ballerina.runtime.api.types.semtype.Bdd; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.SemType; - -import static io.ballerina.runtime.api.types.semtype.Core.createBasicSemType; -import static io.ballerina.runtime.api.types.semtype.Core.subTypeData; - -/** - * Utility methods for creating future types. - * - * @since 2201.11.0 - */ -public final class FutureUtils { - - private static final MappingDefinition.Field[] EMPTY_FIELDS = new MappingDefinition.Field[0]; - - private FutureUtils() { - } - - public static SemType futureContaining(Env env, SemType constraint) { - if (constraint == Builder.getValType()) { - return Builder.getFutureType(); - } - MappingDefinition md = new MappingDefinition(); - SemType mappingType = md.defineMappingTypeWrapped(env, EMPTY_FIELDS, constraint, - CellAtomicType.CellMutability.CELL_MUT_LIMITED); - Bdd bdd = (Bdd) subTypeData(mappingType, BasicTypeCode.BT_MAPPING); - return createBasicSemType(BasicTypeCode.BT_FUTURE, bdd); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/ImmutableSemType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/ImmutableSemType.java deleted file mode 100644 index d63513b1b31f..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/ImmutableSemType.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.SubType; -import io.ballerina.runtime.internal.types.BSemTypeWrapper; - -import java.util.Arrays; -import java.util.Objects; - -/** - * Runtime representation of an immutable semtype. - * - * @since 2201.11.0 - */ -public abstract sealed class ImmutableSemType extends SemType permits BSemTypeWrapper { - - private static final SubType[] EMPTY_SUBTYPE_DATA = new SubType[0]; - - private Integer hashCode; - - ImmutableSemType(int all, int some, SubType[] subTypeData) { - super(all, some, subTypeData); - } - - ImmutableSemType(int all) { - this(all, 0, EMPTY_SUBTYPE_DATA); - } - - protected ImmutableSemType(SemType semType) { - this(semType.all(), semType.some(), semType.subTypeData()); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof ImmutableSemType semType)) { - return false; - } - return all() == semType.all() && some() == semType.some() && - Objects.deepEquals(this.subTypeData(), semType.subTypeData()); - } - - @Override - public int hashCode() { - Integer result = hashCode; - if (result == null) { - synchronized (this) { - result = hashCode; - if (result == null) { - hashCode = result = computeHashCode(); - } - } - } - return result; - } - - private int computeHashCode() { - return Objects.hash(all(), some(), Arrays.hashCode(subTypeData())); - } - - @Override - protected void setAll(int all) { - throw new UnsupportedOperationException("Immutable semtypes cannot be modified"); - } - - @Override - protected void setSome(int some, SubType[] subTypeData) { - throw new UnsupportedOperationException("Immutable semtypes cannot be modified"); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/ListAtomicType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/ListAtomicType.java deleted file mode 100644 index 5631bbc55036..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/ListAtomicType.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.AtomicType; -import io.ballerina.runtime.api.types.semtype.SemType; - -/** - * Represent list atomic type. - * - * @param members required member types of the list - * @param rest rest of member type of the list - * @since 2201.11.0 - */ -public record ListAtomicType(FixedLengthArray members, SemType rest) implements AtomicType { - -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/ListDefinition.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/ListDefinition.java deleted file mode 100644 index 58bd4674453e..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/ListDefinition.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Atom; -import io.ballerina.runtime.api.types.semtype.BasicTypeCode; -import io.ballerina.runtime.api.types.semtype.BddNode; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Definition; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.RecAtom; -import io.ballerina.runtime.api.types.semtype.SemType; - -import static io.ballerina.runtime.api.types.semtype.BddNode.bddAtom; -import static io.ballerina.runtime.api.types.semtype.Builder.basicSubType; -import static io.ballerina.runtime.api.types.semtype.Builder.getUndefType; -import static io.ballerina.runtime.api.types.semtype.Core.isNever; -import static io.ballerina.runtime.api.types.semtype.Core.union; -import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_NONE; - -/** - * {@code Definition} used to create a list type. - * - * @since 2201.11.0 - */ -public class ListDefinition extends Definition { - - private volatile RecAtom rec = null; - private volatile SemType semType = null; - - @Override - public SemType getSemType(Env env) { - SemType s = this.semType; - if (s == null) { - RecAtom rec = env.recListAtom(); - this.rec = rec; - return this.createSemType(env, rec); - } - return s; - } - - public SemType defineListTypeWrapped(Env env, SemType[] initial, int fixedLength, SemType rest, - CellAtomicType.CellMutability mut) { - SemType[] initialCells = new SemType[initial.length]; - for (int i = 0; i < initial.length; i++) { - initialCells[i] = Builder.getCellContaining(env, initial[i], mut); - } - SemType restCell = - Builder.getCellContaining(env, union(rest, getUndefType()), isNever(rest) ? CELL_MUT_NONE : mut); - SemType semType = define(env, initialCells, fixedLength, restCell); - notifyContainer(); - return semType; - } - - private SemType define(Env env, SemType[] initial, int fixedLength, SemType rest) { - FixedLengthArray members = FixedLengthArray.normalized(initial, fixedLength); - ListAtomicType atomicType = new ListAtomicType(members, rest); - Atom atom; - RecAtom rec = this.rec; - if (rec != null) { - atom = rec; - env.setRecListAtomType(rec, atomicType); - } else { - atom = env.listAtom(atomicType); - } - return this.createSemType(env, atom); - } - - private SemType createSemType(Env env, Atom atom) { - BddNode bdd = bddAtom(atom); - this.semType = basicSubType(BasicTypeCode.BT_LIST, BListSubType.createDelegate(bdd)); - return this.semType; - } - -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/MappingAtomicType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/MappingAtomicType.java deleted file mode 100644 index 9ad1916a6637..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/MappingAtomicType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.AtomicType; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.FieldPair; -import io.ballerina.runtime.api.types.semtype.FieldPairs; -import io.ballerina.runtime.api.types.semtype.SemType; - -import java.util.ArrayList; -import java.util.Collection; - -import static io.ballerina.runtime.api.types.semtype.Core.cellInner; -import static io.ballerina.runtime.api.types.semtype.Core.intersectCellMemberSemTypes; -import static io.ballerina.runtime.api.types.semtype.Core.isNever; - -/** - * Represent mapping atomic type. - * - * @param names required member names of the mapping - * @param types required member types of the mapping - * @param rest rest of member type of the mapping - * @since 2201.11.0 - */ -public record MappingAtomicType(String[] names, SemType[] types, SemType rest) implements AtomicType { - - public MappingAtomicType { - assert names.length == types.length; - } - - public MappingAtomicType intersectMapping(Env env, MappingAtomicType other) { - int expectedSize = Integer.min(types().length, other.types().length); - Collection names = new ArrayList<>(expectedSize); - Collection types = new ArrayList<>(expectedSize); - for (FieldPair fieldPair : new FieldPairs(this, other)) { - names.add(fieldPair.name()); - SemType t = intersectCellMemberSemTypes(env, fieldPair.type1(), fieldPair.type2()); - if (isNever(cellInner(fieldPair.type1()))) { - return null; - - } - types.add(t); - } - SemType rest = intersectCellMemberSemTypes(env, this.rest(), other.rest()); - return new MappingAtomicType(names.toArray(String[]::new), types.toArray(SemType[]::new), rest); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/MappingDefinition.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/MappingDefinition.java deleted file mode 100644 index 5e9ae332e55b..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/MappingDefinition.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Atom; -import io.ballerina.runtime.api.types.semtype.BasicTypeCode; -import io.ballerina.runtime.api.types.semtype.BddNode; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Definition; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.RecAtom; -import io.ballerina.runtime.api.types.semtype.SemType; - -import java.util.Arrays; -import java.util.Comparator; - -import static io.ballerina.runtime.api.types.semtype.BddNode.bddAtom; -import static io.ballerina.runtime.api.types.semtype.Builder.basicSubType; -import static io.ballerina.runtime.api.types.semtype.Builder.getUndefType; -import static io.ballerina.runtime.api.types.semtype.Core.isNever; -import static io.ballerina.runtime.api.types.semtype.Core.union; - -/** - * {@code Definition} used to create a mapping type. - * - * @since 2201.11.0 - */ -public class MappingDefinition extends Definition { - - private volatile RecAtom rec = null; - private volatile SemType semType = null; - - @Override - public SemType getSemType(Env env) { - SemType s = this.semType; - if (s == null) { - RecAtom rec = env.recMappingAtom(); - this.rec = rec; - return this.createSemType(env, rec); - } else { - return s; - } - } - - private SemType createSemType(Env env, Atom atom) { - BddNode bdd = bddAtom(atom); - this.semType = basicSubType(BasicTypeCode.BT_MAPPING, BMappingSubType.createDelegate(bdd)); - return this.semType; - } - - public SemType defineMappingTypeWrapped(Env env, Field[] fields, SemType rest, CellAtomicType.CellMutability mut) { - assert rest != null; - BCellField[] cellFields = new BCellField[fields.length]; - for (int i = 0; i < fields.length; i++) { - Field field = fields[i]; - BCellField cellField = BCellField.from(env, field, mut); - cellFields[i] = cellField; - } - SemType restCell = Builder.getCellContaining(env, union(rest, getUndefType()), - isNever(rest) ? CellAtomicType.CellMutability.CELL_MUT_NONE : mut); - SemType semType = define(env, cellFields, restCell); - notifyContainer(); - return semType; - } - - SemType define(Env env, BCellField[] cellFields, SemType rest) { - String[] names = new String[cellFields.length]; - SemType[] types = new SemType[cellFields.length]; - sortAndSplitFields(cellFields, names, types); - MappingAtomicType atomicType = new MappingAtomicType(names, types, rest); - Atom atom; - RecAtom rec = this.rec; - if (rec != null) { - atom = rec; - env.setRecMappingAtomType(rec, atomicType); - } else { - atom = env.mappingAtom(atomicType); - } - return this.createSemType(env, atom); - } - - private void sortAndSplitFields(BCellField[] fields, String[] names, SemType[] types) { - assert fields.length == names.length && fields.length == types.length; - Arrays.sort(fields, Comparator.comparing((field) -> field.name)); - for (int i = 0; i < fields.length; i++) { - names[i] = fields[i].name; - types[i] = fields[i].type; - } - } - - public record Field(String name, SemType ty, boolean readonly, boolean optional) { - - } - - record BCellField(String name, SemType type) { - - static BCellField from(Env env, Field field, CellAtomicType.CellMutability mut) { - SemType type = field.ty; - SemType cellType = Builder.getCellContaining(env, field.optional ? union(type, getUndefType()) : type, - field.readonly ? CellAtomicType.CellMutability.CELL_MUT_NONE : mut); - BCellField cellField = new BCellField(field.name, cellType); - return cellField; - } - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/Member.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/Member.java deleted file mode 100644 index 19a6938b9d68..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/Member.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.SemType; - -import static io.ballerina.runtime.api.types.semtype.Builder.getStringConst; - -/** - * Represents a member of an object type. - * - * @param name the name of the member. For methods, this is the method name, and for fields, this is the field - * name. - * @param valueTy the type of the member - * @param kind the kind of the member (either {@link Kind#Field} or {@link Kind#Method}) - * @param visibility the visibility of the member (either {@link Visibility#Public} or {@link Visibility#Private}) - * @param immutable whether the member is immutable - * @since 2201.11.0 - */ -public record Member(String name, SemType valueTy, Kind kind, Visibility visibility, boolean immutable) { - - public enum Kind { - Field, - Method; - - private static final MappingDefinition.Field FIELD = - new MappingDefinition.Field("kind", getStringConst("field"), true, false); - private static final MappingDefinition.Field METHOD = - new MappingDefinition.Field("kind", getStringConst("method"), true, false); - - public MappingDefinition.Field field() { - return switch (this) { - case Field -> FIELD; - case Method -> METHOD; - }; - } - } - - public enum Visibility { - Public, - Private; - - private static final SemType PUBLIC_TAG = getStringConst("public"); - private static final MappingDefinition.Field PUBLIC = - new MappingDefinition.Field("visibility", PUBLIC_TAG, true, false); - private static final SemType PRIVATE_TAG = getStringConst("private"); - private static final MappingDefinition.Field PRIVATE = - new MappingDefinition.Field("visibility", PRIVATE_TAG, true, false); - static final MappingDefinition.Field ALL = - new MappingDefinition.Field("visibility", Core.union(PRIVATE_TAG, PUBLIC_TAG), true, false); - - public MappingDefinition.Field field() { - return switch (this) { - case Public -> PUBLIC; - case Private -> PRIVATE; - }; - } - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/MutableSemType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/MutableSemType.java deleted file mode 100644 index 2059cb237766..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/MutableSemType.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.internal.types.BType; - -/** - * Represents a mutable semantic type. Note in the current implementation we assume after type checking this is to be - * immutable. - * - * @since 2201.11.0 - */ -public sealed interface MutableSemType permits BType { - - SemType createSemType(); - - void resetSemType(); - - void updateInnerSemTypeIfNeeded(); -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/ObjectDefinition.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/ObjectDefinition.java deleted file mode 100644 index f843d04d43b2..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/ObjectDefinition.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.BasicTypeCode; -import io.ballerina.runtime.api.types.semtype.Bdd; -import io.ballerina.runtime.api.types.semtype.BddNode; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.Definition; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.SemType; - -import java.util.List; -import java.util.stream.Stream; - -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.BT_OBJECT; -import static io.ballerina.runtime.api.types.semtype.BddNode.bddAtom; -import static io.ballerina.runtime.api.types.semtype.Core.createBasicSemType; -import static io.ballerina.runtime.api.types.semtype.Core.union; -import static io.ballerina.runtime.api.types.semtype.RecAtom.createDistinctRecAtom; - -/** - * {@code Definition} used to create an object type. - *

- * Each object type is represented as mapping type (with its basic type set to object) as fallows - * {@code { "$qualifiers": { boolean isolated, "client"|"service" network }, [field_name]: { "field"|"method" kind, - * "public"|"private" visibility, VAL value; } ...{ "field" kind, "public"|"private" visibility, VAL value; } | { - * "method" kind, "public"|"private" visibility, FUNCTION value; } }} - * - * @since 2201.11.0 - */ -public class ObjectDefinition extends Definition { - - private final MappingDefinition mappingDefinition = new MappingDefinition(); - - @Override - public SemType getSemType(Env env) { - return objectContaining(mappingDefinition.getSemType(env)); - } - - public SemType define(Env env, ObjectQualifiers qualifiers, List members, - CellAtomicType.CellMutability mut) { - Stream memberStream = - members.stream().map(member -> memberField(env, member, qualifiers.readonly())); - Stream qualifierStream = Stream.of(qualifiers.field(env)); - SemType mappingType = mappingDefinition.define(env, Stream.concat(memberStream, qualifierStream) - .map(field -> MappingDefinition.BCellField.from(env, field, mut)) - .toArray(MappingDefinition.BCellField[]::new), restMemberType(env, mut, qualifiers.readonly())); - SemType semType = objectContaining(mappingType); - notifyContainer(); - return semType; - } - - private SemType objectContaining(SemType mappingType) { - Bdd mappingSubTypeData = (Bdd) Core.subTypeData(mappingType, BasicTypeCode.BT_MAPPING); - return createBasicSemType(BT_OBJECT, mappingSubTypeData); - } - - private SemType restMemberType(Env env, CellAtomicType.CellMutability mut, boolean readonly) { - MappingDefinition fieldDefn = new MappingDefinition(); - SemType fieldMemberType = fieldDefn.defineMappingTypeWrapped(env, new MappingDefinition.Field[]{ - new MappingDefinition.Field( - "value", - readonly ? Builder.getReadonlyType() : Builder.getValType(), - readonly, - false), - Member.Kind.Field.field(), Member.Visibility.ALL}, Builder.getNeverType(), - CellAtomicType.CellMutability.CELL_MUT_LIMITED); - MappingDefinition methodDefn = new MappingDefinition(); - - SemType methodMemberType = methodDefn.defineMappingTypeWrapped(env, new MappingDefinition.Field[]{ - new MappingDefinition.Field("value", Builder.getFunctionType(), true, false), - Member.Kind.Method.field(), Member.Visibility.ALL}, Builder.getNeverType(), - CellAtomicType.CellMutability.CELL_MUT_LIMITED); - return Builder.getCellContaining(env, union(fieldMemberType, methodMemberType), mut); - } - - private static MappingDefinition.Field memberField(Env env, Member member, boolean immutableObject) { - MappingDefinition md = new MappingDefinition(); - SemType semtype = md.defineMappingTypeWrapped(env, new MappingDefinition.Field[]{ - new MappingDefinition.Field("value", member.valueTy(), member.immutable(), false), - member.kind().field(), member.visibility().field()}, Builder.getNeverType(), - CellAtomicType.CellMutability.CELL_MUT_LIMITED); - return new MappingDefinition.Field(member.name(), semtype, immutableObject | member.immutable(), false); - } - - public static SemType distinct(int distinctId) { - assert distinctId >= 0; - BddNode bdd = bddAtom(createDistinctRecAtom(-distinctId - 1)); - return createBasicSemType(BT_OBJECT, bdd); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/ObjectQualifiers.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/ObjectQualifiers.java deleted file mode 100644 index 33d52a1816a9..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/ObjectQualifiers.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.SemType; - -import static io.ballerina.runtime.api.types.semtype.Builder.getBooleanConst; -import static io.ballerina.runtime.api.types.semtype.Builder.getStringConst; -import static io.ballerina.runtime.api.types.semtype.Core.union; - -/** - * Represents the qualifiers of an object type. - * - * @param isolated whether the object is isolated - * @param readonly whether the object is readonly - * @param networkQualifier the network qualifier of the object (either {@link NetworkQualifier#Client}, - * {@link NetworkQualifier#Service}, or {@link NetworkQualifier#None}) - * @since 2201.11.0 - */ -public record ObjectQualifiers(boolean isolated, boolean readonly, NetworkQualifier networkQualifier) { - - public MappingDefinition.Field field(Env env) { - MappingDefinition md = new MappingDefinition(); - MappingDefinition.Field isolatedField = - new MappingDefinition.Field("isolated", isolated ? getBooleanConst(true) : Builder.getBooleanType(), - true, false); - MappingDefinition.Field networkField = networkQualifier.field(); - SemType ty = md.defineMappingTypeWrapped(env, new MappingDefinition.Field[]{isolatedField, networkField}, - Builder.getNeverType(), CellAtomicType.CellMutability.CELL_MUT_NONE); - return new MappingDefinition.Field("$qualifiers", ty, true, false); - } - - public enum NetworkQualifier { - Client, - Service, - None; - - private static final SemType CLIENT_TAG = getStringConst("client"); - private static final MappingDefinition.Field CLIENT = - new MappingDefinition.Field("network", CLIENT_TAG, true, false); - - private static final SemType SERVICE_TAG = getStringConst("service"); - private static final MappingDefinition.Field SERVICE = - new MappingDefinition.Field("network", SERVICE_TAG, true, false); - - // Object can't be both client and service, which is enforced by the enum. We are using a union here so that - // if this is none it matches both - private static final MappingDefinition.Field NONE = - new MappingDefinition.Field("network", union(CLIENT_TAG, SERVICE_TAG), true, false); - - private MappingDefinition.Field field() { - return switch (this) { - case Client -> CLIENT; - case Service -> SERVICE; - case None -> NONE; - }; - } - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/RegexUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/RegexUtils.java deleted file mode 100644 index 39c4264ba8cc..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/RegexUtils.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.BasicTypeCode; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.SemType; - -/** - * Utility class for creating semtypes of regex tagged basic type. - * - * @since 2201.11.0 - */ -public final class RegexUtils { - - private RegexUtils() { - - } - - public static SemType regexShape(String value) { - SemType stringSubtype = Builder.getStringConst(value); - BStringSubType stringSubType = (BStringSubType) stringSubtype.subTypeByCode(BasicTypeCode.CODE_STRING); - return Builder.basicSubType(BasicTypeCode.BT_REGEXP, stringSubType); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/SemTypeHelper.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/SemTypeHelper.java deleted file mode 100644 index 7bad30e0127b..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/SemTypeHelper.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.SemType; - -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_BOOLEAN; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_CELL; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_DECIMAL; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_ERROR; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_FLOAT; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_FUNCTION; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_FUTURE; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_HANDLE; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_INT; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_LIST; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_MAPPING; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_NIL; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_OBJECT; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_REGEXP; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_STREAM; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_STRING; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_TABLE; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_TYPEDESC; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_UNDEF; -import static io.ballerina.runtime.api.types.semtype.BasicTypeCode.CODE_XML; - -/** - * Collection of utility function on {@code SemType}. - * - * @since 2201.11.0 - */ -public final class SemTypeHelper { - - private SemTypeHelper() { - } - - public static String stringRepr(SemType ty) { - return "all[" + bitSetRepr(ty.all()) + "] some [" + bitSetRepr(ty.some()) + "]"; - } - - public static String bitSetRepr(int bits) { - StringBuilder sb = new StringBuilder(); - appendBitSetRepr(sb, bits, CODE_NIL, "NIL"); - appendBitSetRepr(sb, bits, CODE_BOOLEAN, "BOOLEAN"); - appendBitSetRepr(sb, bits, CODE_INT, "INT"); - appendBitSetRepr(sb, bits, CODE_FLOAT, "FLOAT"); - appendBitSetRepr(sb, bits, CODE_DECIMAL, "DECIMAL"); - appendBitSetRepr(sb, bits, CODE_STRING, "STRING"); - appendBitSetRepr(sb, bits, CODE_ERROR, "ERROR"); - appendBitSetRepr(sb, bits, CODE_TYPEDESC, "TYPE_DESC"); - appendBitSetRepr(sb, bits, CODE_HANDLE, "HANDLE"); - appendBitSetRepr(sb, bits, CODE_REGEXP, "REGEXP"); - appendBitSetRepr(sb, bits, CODE_FUNCTION, "FUNCTION"); - appendBitSetRepr(sb, bits, CODE_FUTURE, "FUTURE"); - appendBitSetRepr(sb, bits, CODE_STREAM, "STREAM"); - appendBitSetRepr(sb, bits, CODE_LIST, "LIST"); - appendBitSetRepr(sb, bits, CODE_MAPPING, "MAPPING"); - appendBitSetRepr(sb, bits, CODE_TABLE, "TABLE"); - appendBitSetRepr(sb, bits, CODE_XML, "XML"); - appendBitSetRepr(sb, bits, CODE_OBJECT, "OBJECT"); - appendBitSetRepr(sb, bits, CODE_CELL, "CELL"); - appendBitSetRepr(sb, bits, CODE_UNDEF, "UNDEF"); - return sb.toString(); - } - - private static void appendBitSetRepr(StringBuilder sb, int bits, int index, String name) { - int mask = 1 << index; - if ((bits & mask) != 0) { - if (!sb.isEmpty()) { - sb.append(", "); - } - sb.append(name).append(" "); - } - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/StreamDefinition.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/StreamDefinition.java deleted file mode 100644 index 2023672f5848..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/StreamDefinition.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.BasicTypeCode; -import io.ballerina.runtime.api.types.semtype.Bdd; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Definition; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.SemType; - -import static io.ballerina.runtime.api.types.semtype.Core.createBasicSemType; -import static io.ballerina.runtime.api.types.semtype.Core.subTypeData; - -/** - * {@code Definition} used to create a stream type. Stream is represented as a - * tuple of {@code [valueType, completionType]} - * - * @since 2201.11.0 - */ -public class StreamDefinition extends Definition { - - private final ListDefinition listDefinition = new ListDefinition(); - - @Override - public SemType getSemType(Env env) { - return streamContaining(listDefinition.getSemType(env)); - } - - public SemType define(Env env, SemType valueType, SemType completionType) { - if (Builder.getValType() == completionType && Builder.getValType() == valueType) { - return Builder.getStreamType(); - } - SemType tuple = listDefinition.defineListTypeWrapped(env, new SemType[]{valueType, completionType}, 2, - Builder.getNeverType(), CellAtomicType.CellMutability.CELL_MUT_LIMITED); - SemType semType = streamContaining(tuple); - notifyContainer(); - return semType; - } - - private SemType streamContaining(SemType tupleType) { - SubTypeData bdd = subTypeData(tupleType, BasicTypeCode.BT_LIST); - assert bdd instanceof Bdd; - return createBasicSemType(BasicTypeCode.BT_STREAM, (Bdd) bdd); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/SubtypePair.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/SubtypePair.java deleted file mode 100644 index d56e4bd33899..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/SubtypePair.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.SubType; - -/** - * Represents the corresponding subtype pairs of two semtypes. - * - * @param typeCode the type code of the semtype - * @param subType1 the first subtype. This will if the first semtype don't have - * this subtype - * @param subType2 the second subtype. This will if the second semtype don't - * have this subtype - * @since 2201.11.0 - */ -public record SubtypePair(int typeCode, SubType subType1, SubType subType2) { - - public SubtypePair { - if (subType1 == null && subType2 == null) { - throw new IllegalArgumentException("both subType1 and subType2 cannot be null"); - } - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/SubtypePairIterator.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/SubtypePairIterator.java deleted file mode 100644 index f061b012896a..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/SubtypePairIterator.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.BasicTypeCode; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.SubType; - -import java.util.Iterator; - -/** - * Iteration implementation of `SubtypePairIterator`. - * - * @since 2201.11.0 - */ -final class SubtypePairIterator implements Iterator { - - // NOTE: this needs to be very efficient since pretty much all type operations depends on it - private int index = 0; - private static final int maxIndex = BasicTypeCode.CODE_UNDEF + 1; - private final int some; - private final SemType t1; - private final SemType t2; - - SubtypePairIterator(SemType t1, SemType t2, int some) { - this.some = some; - this.t1 = t1; - this.t2 = t2; - incrementIndex(); - } - - @Override - public boolean hasNext() { - return index < maxIndex; - } - - private void incrementIndex() { - int rest = some >> index; - int offset = Integer.numberOfTrailingZeros(rest); - index += offset; - } - - @Override - public SubtypePair next() { - SubType subType1 = t1.subTypeByCode(index); - SubType subType2 = t2.subTypeByCode(index); - assert (!(subType1 == null && subType2 == null)); - int typeCode = index; - index++; - incrementIndex(); - return new SubtypePair(typeCode, subType1, subType2); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/SubtypePairs.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/SubtypePairs.java deleted file mode 100644 index 95844611c535..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/SubtypePairs.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.SemType; - -import java.util.Iterator; - -/** - * Implements the iterable for `SubtypePairIteratorImpl`. - * - * @since 2201.11.0 - */ -public class SubtypePairs implements Iterable { - - private final SemType t1; - private final SemType t2; - private final int bits; - - public SubtypePairs(SemType t1, SemType t2, int bits) { - this.t1 = t1; - this.t2 = t2; - this.bits = bits; - } - - @Override - public Iterator iterator() { - return new SubtypePairIterator(t1, t2, bits); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/TableUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/TableUtils.java deleted file mode 100644 index 158259252366..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/TableUtils.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.BasicTypeCode; -import io.ballerina.runtime.api.types.semtype.Bdd; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.SemType; - -import java.util.Optional; - -import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_LIMITED; -import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_NONE; -import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_UNLIMITED; - -/** - * Utility class for creating semtypes of table type. - * - * @since 2201.11.0 - */ -public final class TableUtils { - - private static final SemType[] EMPTY_SEMTYPE_ARR = new SemType[0]; - - private TableUtils() { - } - - public static SemType acceptedTypeContainingKeySpecifier(Context cx, SemType tableConstraint, String[] fieldNames) { - return tableContainingKeySpecifierInner(fieldNames, cx, tableConstraint, CELL_MUT_UNLIMITED); - } - - public static SemType tableContainingKeySpecifier(Context cx, SemType tableConstraint, String[] fieldNames) { - return tableContainingKeySpecifierInner(fieldNames, cx, tableConstraint, CELL_MUT_LIMITED); - } - - private static SemType tableContainingKeySpecifierInner(String[] fieldNames, Context cx, SemType tableConstraint, - CellAtomicType.CellMutability cellMutLimited) { - SemType[] fieldNameSingletons = new SemType[fieldNames.length]; - SemType[] fieldTypes = new SemType[fieldNames.length]; - for (int i = 0; i < fieldNames.length; i++) { - SemType key = Builder.getStringConst(fieldNames[i]); - fieldNameSingletons[i] = key; - fieldTypes[i] = Core.mappingMemberTypeInnerVal(cx, tableConstraint, key); - } - - SemType normalizedKs = - new ListDefinition().defineListTypeWrapped(cx.env, fieldNameSingletons, fieldNameSingletons.length, - Builder.getNeverType(), CELL_MUT_NONE); - - SemType normalizedKc = fieldNames.length > 1 ? new ListDefinition().defineListTypeWrapped(cx.env, fieldTypes, - fieldTypes.length, Builder.getNeverType(), CELL_MUT_NONE) : fieldTypes[0]; - - return tableContaining(cx.env, tableConstraint, normalizedKc, normalizedKs, cellMutLimited); - } - - public static SemType acceptedTypeContainingKeyConstraint(Context cx, SemType tableConstraint, - SemType keyConstraint) { - return tableContainingKeyConstraintInner(cx, tableConstraint, keyConstraint, CELL_MUT_UNLIMITED); - } - - public static SemType tableContainingKeyConstraint(Context cx, SemType tableConstraint, SemType keyConstraint) { - return tableContainingKeyConstraintInner(cx, tableConstraint, keyConstraint, CELL_MUT_LIMITED); - } - - private static SemType tableContainingKeyConstraintInner(Context cx, SemType tableConstraint, SemType keyConstraint, - CellAtomicType.CellMutability mut) { - Optional lat = Core.listAtomicType(cx, keyConstraint); - SemType normalizedKc = lat.map(atom -> { - FixedLengthArray member = atom.members(); - return switch (member.fixedLength()) { - case 0 -> Builder.getValType(); - case 1 -> Core.cellAtomicType(member.initial()[0]).orElseThrow().ty(); - default -> keyConstraint; - }; - }).orElse(keyConstraint); - return tableContaining(cx.env, tableConstraint, normalizedKc, Builder.getValType(), mut); - } - - public static SemType tableContaining(Env env, SemType tableConstraint) { - return tableContaining(env, tableConstraint, CELL_MUT_LIMITED); - } - - public static SemType acceptedType(Env env, SemType tableConstraint) { - return tableContaining(env, tableConstraint, CELL_MUT_UNLIMITED); - } - - private static SemType tableContaining(Env env, SemType tableConstraint, CellAtomicType.CellMutability mut) { - return tableContaining(env, tableConstraint, Builder.getValType(), Builder.getValType(), mut); - } - - private static SemType tableContaining(Env env, SemType tableConstraint, SemType normalizedKc, SemType normalizedKs, - CellAtomicType.CellMutability mut) { - tableConstraint = Core.intersect(tableConstraint, Builder.getMappingType()); - ListDefinition typeParamArrDef = new ListDefinition(); - SemType typeParamArray = typeParamArrDef.defineListTypeWrapped(env, EMPTY_SEMTYPE_ARR, 0, tableConstraint, mut); - - ListDefinition listDef = new ListDefinition(); - SemType tupleType = - listDef.defineListTypeWrapped(env, new SemType[]{typeParamArray, normalizedKc, normalizedKs}, 3, - Builder.getNeverType(), - CELL_MUT_LIMITED); - Bdd bdd = (Bdd) Core.subTypeData(tupleType, BasicTypeCode.BT_LIST); - return Core.createBasicSemType(BasicTypeCode.BT_TABLE, bdd); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/TypedescUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/TypedescUtils.java deleted file mode 100644 index 4bf7b6a78406..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/TypedescUtils.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.BasicTypeCode; -import io.ballerina.runtime.api.types.semtype.Bdd; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.SemType; - -import static io.ballerina.runtime.api.types.semtype.Core.createBasicSemType; -import static io.ballerina.runtime.api.types.semtype.Core.subTypeData; - -/** - * Utility class for creating semtypes of typedesc type. - * - * @since 2201.11.0 - */ -public final class TypedescUtils { - - private static final MappingDefinition.Field[] EMPTY_FIELDS = new MappingDefinition.Field[0]; - - private TypedescUtils() { - - } - - public static SemType typedescContaining(Env env, SemType constraint) { - if (constraint == Builder.getValType()) { - return Builder.getTypeDescType(); - } - MappingDefinition md = new MappingDefinition(); - SemType mappingType = md.defineMappingTypeWrapped(env, EMPTY_FIELDS, constraint, - CellAtomicType.CellMutability.CELL_MUT_NONE); - Bdd bdd = (Bdd) subTypeData(mappingType, BasicTypeCode.BT_MAPPING); - return createBasicSemType(BasicTypeCode.BT_TYPEDESC, bdd); - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/XmlUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/XmlUtils.java deleted file mode 100644 index f05813ead001..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/XmlUtils.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.BasicTypeCode; -import io.ballerina.runtime.api.types.semtype.Bdd; -import io.ballerina.runtime.api.types.semtype.BddAllOrNothing; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.RecAtom; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.SubType; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import static io.ballerina.runtime.api.types.semtype.BddNode.bddAtom; - -/** - * Utility class for creating semtypes of XML type. - * - * @since 2201.11.0 - */ -public final class XmlUtils { - - public static final int XML_PRIMITIVE_NEVER = 1; - public static final int XML_PRIMITIVE_TEXT = 1 << 1; - public static final int XML_PRIMITIVE_ELEMENT_RO = 1 << 2; - public static final int XML_PRIMITIVE_PI_RO = 1 << 3; - public static final int XML_PRIMITIVE_COMMENT_RO = 1 << 4; - public static final int XML_PRIMITIVE_ELEMENT_RW = 1 << 5; - public static final int XML_PRIMITIVE_PI_RW = 1 << 6; - public static final int XML_PRIMITIVE_COMMENT_RW = 1 << 7; - - public static final int XML_PRIMITIVE_RO_SINGLETON = XML_PRIMITIVE_TEXT | XML_PRIMITIVE_ELEMENT_RO - | XML_PRIMITIVE_PI_RO | XML_PRIMITIVE_COMMENT_RO; - public static final int XML_PRIMITIVE_RO_MASK = XML_PRIMITIVE_NEVER | XML_PRIMITIVE_RO_SINGLETON; - public static final int XML_PRIMITIVE_RW_MASK = XML_PRIMITIVE_ELEMENT_RW | XML_PRIMITIVE_PI_RW - | XML_PRIMITIVE_COMMENT_RW; - public static final int XML_PRIMITIVE_SINGLETON = XML_PRIMITIVE_RO_SINGLETON | XML_PRIMITIVE_RW_MASK; - public static final int XML_PRIMITIVE_ALL_MASK = XML_PRIMITIVE_RO_MASK | XML_PRIMITIVE_RW_MASK; - - public static final SubTypeData XML_SUBTYPE_TOP = from(XML_PRIMITIVE_ALL_MASK, BddAllOrNothing.ALL); - public static final SubType XML_SUBTYPE_RO = - BXmlSubType.createDelegate(XML_PRIMITIVE_RO_MASK, - bddAtom(RecAtom.createRecAtom(XML_PRIMITIVE_RO_SINGLETON))); - - private XmlUtils() { - } - - public static SemType xmlSingleton(int primitive) { - if (XmlSingletonCache.isCached(primitive)) { - return XmlSingletonCache.get(primitive); - } - return createXmlSingleton(primitive); - } - - private static SemType createXmlSingleton(int primitive) { - return createXmlSemtype(createXmlSubtype(primitive, BddAllOrNothing.NOTHING)); - } - - private static SemType createXmlSemtype(SubTypeData xmlSubtype) { - if (xmlSubtype instanceof AllOrNothing) { - return xmlSubtype == AllOrNothing.ALL ? Builder.getXmlType() : Builder.getNeverType(); - } - assert xmlSubtype instanceof BXmlSubType : "subtype must be wrapped by delegate by now"; - return Builder.basicSubType(BasicTypeCode.BT_XML, (SubType) xmlSubtype); - } - - private static SubTypeData createXmlSubtype(int primitives, Bdd sequence) { - int p = primitives & XML_PRIMITIVE_ALL_MASK; - if (primitiveShouldIncludeNever(p)) { - p |= XML_PRIMITIVE_NEVER; - } - if (sequence == BddAllOrNothing.ALL && p == XML_PRIMITIVE_ALL_MASK) { - return AllOrNothing.ALL; - } else if (sequence == BddAllOrNothing.NOTHING && p == 0) { - return AllOrNothing.NOTHING; - } - return from(p, sequence); - } - - private static boolean primitiveShouldIncludeNever(int primitive) { - return (primitive & XML_PRIMITIVE_TEXT) == XML_PRIMITIVE_TEXT; - } - - public static SubTypeData from(int primitives, Bdd sequence) { - return BXmlSubType.createDelegate(primitives, sequence); - } - - public static SemType xmlSequence(SemType constituentType) { - assert Core.isSubtypeSimple(constituentType, Builder.getXmlType()) : - "It is a precondition that constituentType is a subtype of XML"; - if (Core.isNever(constituentType)) { - return xmlSequence(xmlSingleton(XML_PRIMITIVE_NEVER)); - } else if (constituentType.some() == 0) { - assert Core.isNever(Core.diff(Builder.getXmlType(), constituentType)); - return constituentType; - } else { - SubType xmlSubType = - Core.getComplexSubtypeData(constituentType, BasicTypeCode.BT_XML); - if (!xmlSubType.isAll() && !xmlSubType.isNothing()) { - xmlSubType = makeXmlSequence((BXmlSubType) xmlSubType); - } - return createXmlSemtype((SubTypeData) xmlSubType); - } - } - - private static SubType makeXmlSequence(BXmlSubType xmlSubType) { - int primitives = xmlSubType.primitives() | XML_PRIMITIVE_NEVER; - int atom = xmlSubType.primitives() & XML_PRIMITIVE_SINGLETON; - Bdd sequence = (Bdd) xmlSubType.bdd().union(bddAtom(RecAtom.createRecAtom(atom))); - return BXmlSubType.createDelegate(primitives, sequence); - } - - private static final class XmlSingletonCache { - - private static final Map CACHE = new ConcurrentHashMap<>(); - - private static boolean isCached(int primitive) { - return Integer.bitCount(primitive) < 3; - } - - private static SemType get(int primitive) { - return CACHE.computeIfAbsent(primitive, XmlUtils::createXmlSingleton); - } - - } -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/utils/MapUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/utils/MapUtils.java index 62ac70673626..2ae27c4cd2cb 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/utils/MapUtils.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/utils/MapUtils.java @@ -20,22 +20,22 @@ import io.ballerina.runtime.api.creators.ErrorCreator; import io.ballerina.runtime.api.flags.SymbolFlags; import io.ballerina.runtime.api.types.Field; -import io.ballerina.runtime.api.types.MapType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.SemType; import io.ballerina.runtime.api.utils.TypeUtils; import io.ballerina.runtime.api.values.BError; import io.ballerina.runtime.api.values.BString; import io.ballerina.runtime.internal.TypeChecker; import io.ballerina.runtime.internal.errors.ErrorCodes; import io.ballerina.runtime.internal.errors.ErrorHelper; +import io.ballerina.runtime.internal.types.BMapType; import io.ballerina.runtime.internal.types.BRecordType; import io.ballerina.runtime.internal.types.BTypeReferenceType; +import io.ballerina.runtime.internal.types.BUnionType; import io.ballerina.runtime.internal.values.MapValue; +import java.util.List; + import static io.ballerina.runtime.api.constants.RuntimeConstants.MAP_LANG_LIB; import static io.ballerina.runtime.internal.errors.ErrorReasons.INHERENT_TYPE_VIOLATION_ERROR_IDENTIFIER; import static io.ballerina.runtime.internal.errors.ErrorReasons.MAP_KEY_NOT_FOUND_ERROR; @@ -56,7 +56,7 @@ public static void handleMapStore(MapValue mapValue, BString fi updateMapValue(TypeUtils.getImpliedType(mapValue.getType()), mapValue, fieldName, value); } - public static void handleInherentTypeViolatingMapUpdate(Object value, MapType mapType) { + public static void handleInherentTypeViolatingMapUpdate(Object value, BMapType mapType) { if (TypeChecker.checkIsType(value, mapType.getConstrainedType())) { return; } @@ -118,7 +118,17 @@ public static boolean handleInherentTypeViolatingRecordUpdate( } private static boolean containsNilType(Type type) { - return Core.containsBasicType(SemType.tryInto(type), Builder.getNilType()); + type = TypeUtils.getImpliedType(type); + int tag = type.getTag(); + if (tag == TypeTags.UNION_TAG) { + List memTypes = ((BUnionType) type).getMemberTypes(); + for (Type memType : memTypes) { + if (containsNilType(memType)) { + return true; + } + } + } + return tag == TypeTags.NULL_TAG; } public static BError createOpNotSupportedError(Type type, String op) { @@ -142,7 +152,7 @@ private static void updateMapValue(Type mapType, MapValue mapVa switch (mapType.getTag()) { case TypeTags.MAP_TAG: - handleInherentTypeViolatingMapUpdate(value, (MapType) mapType); + handleInherentTypeViolatingMapUpdate(value, (BMapType) mapType); mapValue.put(fieldName, value); return; case TypeTags.RECORD_TYPE_TAG: diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/utils/ValueComparisonUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/utils/ValueComparisonUtils.java index 8bb1312eb5d2..48f33fda34ab 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/utils/ValueComparisonUtils.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/utils/ValueComparisonUtils.java @@ -219,6 +219,14 @@ public static int compareValues(Object lhsValue, Object rhsValue, String directi return codePointCompare(lhsValue.toString(), rhsValue.toString()); } + if (TypeTags.isIntegerTypeTag(lhsTypeTag) && TypeTags.isIntegerTypeTag(rhsTypeTag)) { + return Long.compare((long) lhsValue, (long) rhsValue); + } else if (TypeTags.isIntegerTypeTag(lhsTypeTag) && TypeTags.BYTE_TAG == rhsTypeTag) { + return Long.compare((long) lhsValue, (int) rhsValue); + } else if (TypeTags.BYTE_TAG == lhsTypeTag && TypeTags.isIntegerTypeTag(rhsTypeTag)) { + return Long.compare((int) lhsValue, (long) rhsValue); + } + if (lhsTypeTag == rhsTypeTag) { switch (lhsTypeTag) { case TypeTags.BOOLEAN_TAG: @@ -238,14 +246,6 @@ public static int compareValues(Object lhsValue, Object rhsValue, String directi } } - if (TypeTags.BYTE_TAG == lhsTypeTag && TypeTags.isIntegerTypeTag(rhsTypeTag)) { - return Long.compare((int) lhsValue, (long) rhsValue); - } else if (TypeTags.isIntegerTypeTag(lhsTypeTag) && TypeTags.BYTE_TAG == rhsTypeTag) { - return Long.compare((long) lhsValue, (int) rhsValue); - } else if (TypeTags.isIntegerTypeTag(lhsTypeTag) && TypeTags.isIntegerTypeTag(rhsTypeTag)) { - return Long.compare((long) lhsValue, (long) rhsValue); - } - if ((lhsTypeTag == TypeTags.ARRAY_TAG || lhsTypeTag == TypeTags.TUPLE_TAG) && (rhsTypeTag == TypeTags.ARRAY_TAG || rhsTypeTag == TypeTags.TUPLE_TAG)) { return compareArrayValues(lhsValue, rhsValue, lhsTypeTag, rhsTypeTag, direction); diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/utils/ValueConverter.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/utils/ValueConverter.java index b610c8a18316..ec772ed9b133 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/utils/ValueConverter.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/utils/ValueConverter.java @@ -31,10 +31,6 @@ import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; import io.ballerina.runtime.api.types.TypedescType; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.SemType; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.utils.TypeUtils; import io.ballerina.runtime.api.values.BArray; @@ -61,7 +57,6 @@ import io.ballerina.runtime.internal.values.ReadOnlyUtils; import io.ballerina.runtime.internal.values.TableValueImpl; import io.ballerina.runtime.internal.values.TupleValueImpl; -import io.ballerina.runtime.internal.values.XmlSequence; import java.util.ArrayList; import java.util.HashMap; @@ -151,7 +146,6 @@ private static Object convert(Object value, Type targetType, Set if (matchingType.isReadOnly()) { newValue = CloneUtils.cloneReadOnly(newValue); } - newValue = xmlSequenceHack(newValue, matchingType); break; } @@ -177,27 +171,6 @@ private static Object convert(Object value, Type targetType, Set return newValue; } - // This is a hack to workaround #43231 - private static Object xmlSequenceHack(Object value, Type targetType) { - if (!(value instanceof XmlSequence xmlSequence)) { - return value; - } - Context cx = TypeChecker.context(); - List list = new ArrayList<>(); - SemType targetSemType = SemType.tryInto(targetType); - for (BXml child : xmlSequence.getChildrenList()) { - SemType childType = SemType.tryInto(child.getType()); - boolean isReadonly = - Core.isSubType(cx, Core.intersect(childType, targetSemType), Builder.getReadonlyType()); - if (isReadonly) { - list.add((BXml) CloneUtils.cloneReadOnly(child)); - } else { - list.add(child); - } - } - return new XmlSequence(list); - } - private static Type getTargetFromTypeDesc(Type targetType) { Type referredType = TypeUtils.getImpliedType(targetType); if (referredType.getTag() == TypeTags.TYPEDESC_TAG) { diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/AbstractArrayValue.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/AbstractArrayValue.java index a129148baf23..4768e51ecd52 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/AbstractArrayValue.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/AbstractArrayValue.java @@ -20,17 +20,12 @@ import io.ballerina.runtime.api.creators.ErrorCreator; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.ShapeAnalyzer; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.utils.TypeUtils; import io.ballerina.runtime.internal.errors.ErrorHelper; import io.ballerina.runtime.internal.json.JsonGenerator; import io.ballerina.runtime.internal.types.BTupleType; import io.ballerina.runtime.internal.types.BUnionType; -import io.ballerina.runtime.internal.types.TypeWithShape; -import io.ballerina.runtime.internal.types.semtype.ListDefinition; import io.ballerina.runtime.internal.utils.IteratorUtils; import java.io.ByteArrayOutputStream; @@ -38,7 +33,6 @@ import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.Map; -import java.util.Optional; import java.util.Set; import static io.ballerina.runtime.api.constants.RuntimeConstants.ARRAY_LANG_LIB; @@ -57,10 +51,9 @@ * * @since 1.1.0 */ -public abstract class AbstractArrayValue implements ArrayValue, RecursiveValue { +public abstract class AbstractArrayValue implements ArrayValue { static final int SYSTEM_ARRAY_MAX = Integer.MAX_VALUE - 8; - private final ThreadLocal readonlyAttachedDefinition = new ThreadLocal<>(); /** * The maximum size of arrays to allocate. @@ -84,9 +77,6 @@ public void append(Object value) { @Override public boolean equals(Object o, Set visitedValues) { - if (!(o instanceof ArrayValue arrayValue)) { - return false; - } ValuePair compValuePair = new ValuePair(this, o); for (ValuePair valuePair : visitedValues) { if (valuePair.equals(compValuePair)) { @@ -95,6 +85,7 @@ public boolean equals(Object o, Set visitedValues) { } visitedValues.add(compValuePair); + ArrayValue arrayValue = (ArrayValue) o; if (arrayValue.size() != this.size()) { return false; } @@ -312,25 +303,4 @@ public boolean hasNext() { return cursor < length; } } - - @Override - public synchronized ListDefinition getReadonlyShapeDefinition() { - return readonlyAttachedDefinition.get(); - } - - @Override - public synchronized void setReadonlyShapeDefinition(ListDefinition definition) { - readonlyAttachedDefinition.set(definition); - } - - @Override - public synchronized void resetReadonlyShapeDefinition() { - readonlyAttachedDefinition.remove(); - } - - @Override - public Optional inherentTypeOf(Context cx) { - TypeWithShape typeWithShape = (TypeWithShape) getType(); - return typeWithShape.inherentTypeOf(cx, ShapeAnalyzer::inherentTypeOf, this); - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/AbstractObjectValue.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/AbstractObjectValue.java index 5457ca79574e..07d20399f30d 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/AbstractObjectValue.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/AbstractObjectValue.java @@ -23,9 +23,6 @@ import io.ballerina.runtime.api.types.ObjectType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeId; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.ShapeAnalyzer; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.utils.TypeUtils; import io.ballerina.runtime.api.values.BArray; @@ -38,13 +35,10 @@ import io.ballerina.runtime.internal.errors.ErrorCodes; import io.ballerina.runtime.internal.errors.ErrorHelper; import io.ballerina.runtime.internal.types.BObjectType; -import io.ballerina.runtime.internal.types.TypeWithShape; -import io.ballerina.runtime.internal.types.semtype.ObjectDefinition; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.StringJoiner; import static io.ballerina.runtime.api.constants.RuntimeConstants.DOT; @@ -63,12 +57,10 @@ * * @since 0.995.0 */ -public abstract class AbstractObjectValue implements ObjectValue, RecursiveValue { +public abstract class AbstractObjectValue implements ObjectValue { private BTypedesc typedesc; private final BObjectType objectType; private final Type type; - private SemType shape; - private final ThreadLocal readonlyAttachedDefinition = new ThreadLocal<>(); private final HashMap nativeData = new HashMap<>(); @@ -241,33 +233,4 @@ private void checkFieldUpdateType(String fieldName, Object value) { ErrorHelper.getErrorDetails(ErrorCodes.INVALID_OBJECT_FIELD_VALUE_ERROR, fieldName, fieldType, TypeChecker.getType(value))); } - - public final SemType shapeOf() { - return shape; - } - - public final void cacheShape(SemType semType) { - this.shape = semType; - } - - @Override - public Optional inherentTypeOf(Context cx) { - TypeWithShape typeWithShape = (TypeWithShape) getType(); - return typeWithShape.inherentTypeOf(cx, ShapeAnalyzer::inherentTypeOf, this); - } - - @Override - public ObjectDefinition getReadonlyShapeDefinition() { - return readonlyAttachedDefinition.get(); - } - - @Override - public void setReadonlyShapeDefinition(ObjectDefinition definition) { - readonlyAttachedDefinition.set(definition); - } - - @Override - public void resetReadonlyShapeDefinition() { - readonlyAttachedDefinition.remove(); - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/ArrayValueImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/ArrayValueImpl.java index 8325e6781c78..67716521a8c4 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/ArrayValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/ArrayValueImpl.java @@ -24,7 +24,6 @@ import io.ballerina.runtime.api.types.PredefinedTypes; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.SemType; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.utils.TypeUtils; import io.ballerina.runtime.api.values.BArray; @@ -87,8 +86,6 @@ public class ArrayValueImpl extends AbstractArrayValue { private double[] floatValues; private BString[] bStringValues; private BTypedesc typedesc; - - private SemType shape; // ------------------------ Constructors ------------------------------------------------------------------- public ArrayValueImpl(Object[] values, ArrayType type) { @@ -616,15 +613,15 @@ public void convertStringAndAddRefValue(long index, Object value) { public void addRefValue(long index, Object value) { switch (this.elementReferredType.getTag()) { case TypeTags.BOOLEAN_TAG: - prepareForAdd(index, value, booleanValues.length); + prepareForAdd(index, value, type, booleanValues.length); this.booleanValues[(int) index] = (Boolean) value; return; case TypeTags.FLOAT_TAG: - prepareForAdd(index, value, floatValues.length); + prepareForAdd(index, value, type, floatValues.length); this.floatValues[(int) index] = (Double) value; return; case TypeTags.BYTE_TAG: - prepareForAdd(index, value, byteValues.length); + prepareForAdd(index, value, type, byteValues.length); this.byteValues[(int) index] = ((Number) value).byteValue(); return; case TypeTags.INT_TAG: @@ -634,16 +631,16 @@ public void addRefValue(long index, Object value) { case TypeTags.UNSIGNED32_INT_TAG: case TypeTags.UNSIGNED16_INT_TAG: case TypeTags.UNSIGNED8_INT_TAG: - prepareForAdd(index, value, intValues.length); + prepareForAdd(index, value, type, intValues.length); this.intValues[(int) index] = (Long) value; return; case TypeTags.STRING_TAG: case TypeTags.CHAR_STRING_TAG: - prepareForAdd(index, value, bStringValues.length); + prepareForAdd(index, value, type, bStringValues.length); this.bStringValues[(int) index] = (BString) value; return; default: - prepareForAdd(index, value, refValues.length); + prepareForAdd(index, value, type, refValues.length); this.refValues[(int) index] = value; } } @@ -662,34 +659,27 @@ public void setArrayRefTypeForcefully(ArrayType type, int size) { public void addInt(long index, long value) { Type sourceType = TypeChecker.getType(value); if (intValues != null) { - if (sourceType == this.elementType) { - prepareForAddWithoutTypeCheck(index, intValues.length); - } else { - prepareForAdd(index, value, intValues.length); - } + prepareForAdd(index, value, PredefinedTypes.TYPE_INT, intValues.length); intValues[(int) index] = value; return; } - if (sourceType == this.elementType) { - prepareForAddWithoutTypeCheck(index, byteValues.length); - } else { - prepareForAdd(index, value, byteValues.length); - } + + prepareForAdd(index, value, TypeChecker.getType(value), byteValues.length); byteValues[(int) index] = (byte) ((Long) value).intValue(); } private void addBoolean(long index, boolean value) { - prepareForAddWithoutTypeCheck(index, booleanValues.length); + prepareForAdd(index, value, PredefinedTypes.TYPE_BOOLEAN, booleanValues.length); booleanValues[(int) index] = value; } private void addByte(long index, byte value) { - prepareForAddWithoutTypeCheck(index, byteValues.length); + prepareForAdd(index, value, PredefinedTypes.TYPE_BYTE, byteValues.length); byteValues[(int) index] = value; } private void addFloat(long index, double value) { - prepareForAddWithoutTypeCheck(index, floatValues.length); + prepareForAdd(index, value, PredefinedTypes.TYPE_FLOAT, floatValues.length); floatValues[(int) index] = value; } @@ -699,12 +689,7 @@ private void addString(long index, String value) { } private void addBString(long index, BString value) { - Type sourceType = TypeChecker.getType(value); - if (sourceType == this.elementType) { - prepareForAddWithoutTypeCheck(index, bStringValues.length); - } else { - prepareForAdd(index, value, bStringValues.length); - } + prepareForAdd(index, value, PredefinedTypes.TYPE_STRING, bStringValues.length); bStringValues[(int) index] = value; } @@ -1272,12 +1257,12 @@ protected void unshift(long index, Object[] vals) { // Private methods - private void prepareForAdd(long index, Object value, int currentArraySize) { + private void prepareForAdd(long index, Object value, Type sourceType, int currentArraySize) { // check types - if (!TypeChecker.checkIsType(value, this.elementType)) { + if (!TypeChecker.checkIsType(null, value, sourceType, this.elementType)) { throw ErrorCreator.createError(getModulePrefixedReason(ARRAY_LANG_LIB, INHERENT_TYPE_VIOLATION_ERROR_IDENTIFIER), ErrorHelper.getErrorDetails( - ErrorCodes.INCOMPATIBLE_TYPE, this.elementType, TypeChecker.getType(value))); + ErrorCodes.INCOMPATIBLE_TYPE, this.elementType, sourceType)); } prepareForAddWithoutTypeCheck(index, currentArraySize); } @@ -1421,14 +1406,4 @@ private int calculateHashCode(List visited) { } return result; } - - @Override - public void cacheShape(SemType semType) { - shape = semType; - } - - @Override - public SemType shapeOf() { - return shape; - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/DecimalValue.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/DecimalValue.java index d5e5e918e02e..ec48ef7789af 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/DecimalValue.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/DecimalValue.java @@ -22,22 +22,17 @@ import io.ballerina.runtime.api.creators.ErrorCreator; import io.ballerina.runtime.api.types.PredefinedTypes; import io.ballerina.runtime.api.types.Type; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SemType; import io.ballerina.runtime.api.values.BDecimal; import io.ballerina.runtime.api.values.BLink; import io.ballerina.runtime.internal.errors.ErrorCodes; import io.ballerina.runtime.internal.errors.ErrorHelper; import io.ballerina.runtime.internal.errors.ErrorReasons; -import io.ballerina.runtime.internal.types.BDecimalType; import io.ballerina.runtime.internal.utils.ErrorUtils; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; import java.util.Map; -import java.util.Optional; /** *

@@ -65,10 +60,8 @@ public class DecimalValue implements SimpleValue, BDecimal { public DecimalValueKind valueKind = DecimalValueKind.OTHER; private final BigDecimal value; - private final Type singletonType; public DecimalValue(BigDecimal value) { - this.singletonType = BDecimalType.singletonType(value); this.value = getValidDecimalValue(value); if (!this.booleanValue()) { this.valueKind = DecimalValueKind.ZERO; @@ -90,7 +83,7 @@ public DecimalValue(String value) { throw exception; } this.value = getValidDecimalValue(bd); - this.singletonType = BDecimalType.singletonType(this.value); + if (!this.booleanValue()) { this.valueKind = DecimalValueKind.ZERO; } @@ -236,7 +229,7 @@ public BigDecimal value() { */ @Override public Type getType() { - return singletonType; + return PredefinedTypes.TYPE_DECIMAL; } //========================= Mathematical operations supported =============================== @@ -487,9 +480,4 @@ public static DecimalValue valueOfJ(BigDecimal value) { return new DecimalValue(new BigDecimal(value.toString(), MathContext.DECIMAL128) .setScale(1, BigDecimal.ROUND_HALF_EVEN)); } - - @Override - public Optional inherentTypeOf(Context cx) { - return Optional.of(Builder.getDecimalConst(value)); - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/ErrorValue.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/ErrorValue.java index 140cd7d0dc08..f8cd391a127a 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/ErrorValue.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/ErrorValue.java @@ -86,7 +86,7 @@ public class ErrorValue extends BError implements RefValue { private static final String STOP_FUNCTION_SUFFIX = "."; public ErrorValue(BString message) { - this(new BErrorType(TypeConstants.ERROR, PredefinedTypes.TYPE_ERROR.getPackage(), PredefinedTypes.TYPE_DETAIL), + this(new BErrorType(TypeConstants.ERROR, PredefinedTypes.TYPE_ERROR.getPackage(), TYPE_MAP), message, null, new MapValueImpl<>(PredefinedTypes.TYPE_ERROR_DETAIL)); } @@ -469,9 +469,7 @@ private boolean isCompilerAddedName(String name) { */ @Override public boolean equals(Object o, Set visitedValues) { - if (!(o instanceof ErrorValue errorValue)) { - return false; - } + ErrorValue errorValue = (ErrorValue) o; return isEqual(this.getMessage(), errorValue.getMessage(), visitedValues) && ((MapValueImpl) this.getDetails()).equals(errorValue.getDetails(), visitedValues) && isEqual(this.getCause(), errorValue.getCause(), visitedValues); diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/FPValue.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/FPValue.java index 6e116666a45b..35dd9a28be60 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/FPValue.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/FPValue.java @@ -20,15 +20,12 @@ import io.ballerina.runtime.api.Runtime; import io.ballerina.runtime.api.constants.RuntimeConstants; import io.ballerina.runtime.api.types.Type; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SemType; import io.ballerina.runtime.api.values.BFunctionPointer; import io.ballerina.runtime.api.values.BLink; import io.ballerina.runtime.api.values.BTypedesc; import io.ballerina.runtime.internal.BalRuntime; import java.util.Map; -import java.util.Optional; import java.util.function.Function; /** @@ -104,9 +101,4 @@ public String getName() { public String toString() { return RuntimeConstants.EMPTY; } - - @Override - public Optional inherentTypeOf(Context cx) { - return Optional.of(SemType.tryInto(getType())); - } } 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 30630dc86aa8..ebbdce07f208 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 @@ -19,13 +19,9 @@ import io.ballerina.runtime.api.creators.ErrorCreator; import io.ballerina.runtime.api.types.Field; -import io.ballerina.runtime.api.types.MapType; import io.ballerina.runtime.api.types.PredefinedTypes; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.ShapeAnalyzer; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.values.BArray; import io.ballerina.runtime.api.values.BError; @@ -45,11 +41,10 @@ import io.ballerina.runtime.internal.json.JsonInternalUtils; import io.ballerina.runtime.internal.scheduling.Scheduler; import io.ballerina.runtime.internal.types.BField; +import io.ballerina.runtime.internal.types.BMapType; import io.ballerina.runtime.internal.types.BRecordType; import io.ballerina.runtime.internal.types.BTupleType; import io.ballerina.runtime.internal.types.BUnionType; -import io.ballerina.runtime.internal.types.TypeWithShape; -import io.ballerina.runtime.internal.types.semtype.MappingDefinition; import io.ballerina.runtime.internal.utils.CycleUtils; import io.ballerina.runtime.internal.utils.IteratorUtils; import io.ballerina.runtime.internal.utils.MapUtils; @@ -65,7 +60,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.StringJoiner; import java.util.stream.Collectors; @@ -99,15 +93,13 @@ * @since 0.995.0 */ public class MapValueImpl extends LinkedHashMap implements RefValue, CollectionValue, MapValue, - BMap, RecursiveValue { + BMap { private BTypedesc typedesc; private Type type; private Type referredType; private final Map nativeData = new HashMap<>(); private Type iteratorNextReturnType; - private SemType shape; - private final ThreadLocal readonlyAttachedDefinition = new ThreadLocal<>(); public MapValueImpl(TypedescValue typedesc) { this(typedesc.getDescribingType()); @@ -241,7 +233,7 @@ public V fillAndGet(Object key) { expectedType = recordType.restFieldType; } } else { - expectedType = ((MapType) this.referredType).getConstrainedType(); + expectedType = ((BMapType) this.referredType).getConstrainedType(); } if (!TypeChecker.hasFillerValue(expectedType)) { @@ -355,7 +347,7 @@ protected void populateInitialValues(BMapInitialValueEntry[] initialValues) { @Override public void populateInitialValue(K key, V value) { if (referredType.getTag() == TypeTags.MAP_TAG) { - MapUtils.handleInherentTypeViolatingMapUpdate(value, (MapType) referredType); + MapUtils.handleInherentTypeViolatingMapUpdate(value, (BMapType) referredType); putValue(key, value); } else { BString fieldName = (BString) key; @@ -617,21 +609,6 @@ public IteratorValue getIterator() { return new MapIterator<>(new LinkedHashSet<>(this.entrySet()).iterator()); } - @Override - public synchronized MappingDefinition getReadonlyShapeDefinition() { - return readonlyAttachedDefinition.get(); - } - - @Override - public synchronized void setReadonlyShapeDefinition(MappingDefinition definition) { - readonlyAttachedDefinition.set(definition); - } - - @Override - public synchronized void resetReadonlyShapeDefinition() { - readonlyAttachedDefinition.remove(); - } - /** * {@link MapIterator} iteration provider for ballerina maps. * @@ -711,7 +688,7 @@ public Map getNativeDataMap() { private void initializeIteratorNextReturnType() { Type type; if (this.referredType.getTag() == PredefinedTypes.TYPE_MAP.getTag()) { - MapType mapType = (MapType) this.referredType; + BMapType mapType = (BMapType) this.referredType; type = mapType.getConstrainedType(); } else { BRecordType recordType = (BRecordType) this.referredType; @@ -745,20 +722,4 @@ public Type getIteratorNextReturnType() { protected V putValue(K key, V value) { return super.put(key, value); } - - @Override - public void cacheShape(SemType semType) { - shape = semType; - } - - @Override - public SemType shapeOf() { - return shape; - } - - @Override - public Optional inherentTypeOf(Context cx) { - TypeWithShape typeWithShape = (TypeWithShape) type; - return typeWithShape.inherentTypeOf(cx, ShapeAnalyzer::inherentTypeOf, this); - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/ReadOnlyUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/ReadOnlyUtils.java index 8e23ef16c232..c9ba580378da 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/ReadOnlyUtils.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/ReadOnlyUtils.java @@ -26,7 +26,6 @@ import io.ballerina.runtime.api.types.Field; import io.ballerina.runtime.api.types.IntersectableReferenceType; import io.ballerina.runtime.api.types.IntersectionType; -import io.ballerina.runtime.api.types.MapType; import io.ballerina.runtime.api.types.PredefinedTypes; import io.ballerina.runtime.api.types.ReferenceType; import io.ballerina.runtime.api.types.SelectivelyImmutableReferenceType; @@ -185,9 +184,9 @@ private static BIntersectionType setImmutableIntersectionType(Type type, Set Type of the definition - * - * @since 2201.11.0 - */ -interface RecursiveValue { - - E getReadonlyShapeDefinition(); - - void setReadonlyShapeDefinition(E definition); - - void resetReadonlyShapeDefinition(); -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/RegExpValue.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/RegExpValue.java index a00800f64b53..c9a4fd8f30c7 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/RegExpValue.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/RegExpValue.java @@ -17,17 +17,12 @@ import io.ballerina.runtime.api.types.PredefinedTypes; import io.ballerina.runtime.api.types.Type; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SemType; import io.ballerina.runtime.api.values.BLink; import io.ballerina.runtime.api.values.BRegexpValue; import io.ballerina.runtime.api.values.BTypedesc; -import io.ballerina.runtime.internal.types.semtype.RegexUtils; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.Set; import static io.ballerina.runtime.internal.utils.ValueUtils.getTypedescValue; @@ -46,11 +41,9 @@ public class RegExpValue implements BRegexpValue, RefValue { private final RegExpDisjunction regExpDisjunction; private BTypedesc typedesc; private static final Type type = PredefinedTypes.TYPE_READONLY_ANYDATA; - private final SemType shape; public RegExpValue(RegExpDisjunction regExpDisjunction) { this.regExpDisjunction = regExpDisjunction; - this.shape = RegexUtils.regexShape(regExpDisjunction.stringValue(null)); } @Override @@ -83,6 +76,11 @@ public int hashCode() { return Objects.hash(this.regExpDisjunction); } + @Override + public boolean equals(Object obj) { + return this == obj; + } + @Override public BTypedesc getTypedesc() { if (this.typedesc == null) { @@ -125,19 +123,4 @@ public boolean equals(Object o, Set visitedValues) { } return this.stringValue(null).equals(rhsRegExpValue.stringValue(null)); } - - @Override - public SemType widenedType() { - return Builder.getRegexType(); - } - - @Override - public Optional shapeOf() { - return Optional.of(this.shape); - } - - @Override - public Optional inherentTypeOf(Context cx) { - return shapeOf(); - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/StringValue.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/StringValue.java index d553b300f4a8..3898b3aa8ca4 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/StringValue.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/StringValue.java @@ -17,16 +17,12 @@ */ package io.ballerina.runtime.internal.values; +import io.ballerina.runtime.api.types.PredefinedTypes; import io.ballerina.runtime.api.types.Type; -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SemType; import io.ballerina.runtime.api.values.BLink; import io.ballerina.runtime.api.values.BString; -import io.ballerina.runtime.internal.types.BStringType; import java.util.Map; -import java.util.Optional; /** * Class representing ballerina strings. @@ -37,19 +33,15 @@ public abstract class StringValue implements BString, SimpleValue { final String value; final boolean isNonBmp; - private final Type type; - private final SemType shape; protected StringValue(String value, boolean isNonBmp) { this.value = value; this.isNonBmp = isNonBmp; - this.type = BStringType.singletonType(value); - this.shape = Builder.getStringConst(value); } @Override public Type getType() { - return type; + return PredefinedTypes.TYPE_STRING; } @Override @@ -108,8 +100,4 @@ public boolean equals(Object str) { return false; } - @Override - public Optional inherentTypeOf(Context cx) { - return Optional.of(shape); - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TableValueImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TableValueImpl.java index 5ce57d89f406..c027da267680 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TableValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TableValueImpl.java @@ -20,13 +20,9 @@ import io.ballerina.runtime.api.creators.ErrorCreator; import io.ballerina.runtime.api.creators.ValueCreator; import io.ballerina.runtime.api.types.Field; -import io.ballerina.runtime.api.types.MapType; import io.ballerina.runtime.api.types.TableType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.ShapeAnalyzer; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.utils.TypeUtils; import io.ballerina.runtime.api.values.BArray; @@ -41,12 +37,12 @@ import io.ballerina.runtime.internal.errors.ErrorCodes; import io.ballerina.runtime.internal.errors.ErrorHelper; import io.ballerina.runtime.internal.types.BIntersectionType; +import io.ballerina.runtime.internal.types.BMapType; import io.ballerina.runtime.internal.types.BRecordType; import io.ballerina.runtime.internal.types.BTableType; import io.ballerina.runtime.internal.types.BTupleType; import io.ballerina.runtime.internal.types.BTypeReferenceType; import io.ballerina.runtime.internal.types.BUnionType; -import io.ballerina.runtime.internal.types.TypeWithShape; import io.ballerina.runtime.internal.utils.CycleUtils; import io.ballerina.runtime.internal.utils.IteratorUtils; import io.ballerina.runtime.internal.utils.TableUtils; @@ -62,7 +58,6 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.StringJoiner; import java.util.TreeMap; @@ -435,7 +430,7 @@ private Type getTableConstraintField(Type constraintType, String fieldName) { Map fieldList = ((BRecordType) constraintType).getFields(); return fieldList.get(fieldName).getFieldType(); case TypeTags.MAP_TAG: - return ((MapType) constraintType).getConstrainedType(); + return ((BMapType) constraintType).getConstrainedType(); case TypeTags.INTERSECTION_TAG: Type effectiveType = ((BIntersectionType) constraintType).getEffectiveType(); return getTableConstraintField(effectiveType, fieldName); @@ -793,7 +788,7 @@ public MultiKeyWrapper() { Arrays.stream(fieldNames) .forEach(field -> keyTypes.add(recordType.getFields().get(field).getFieldType())); } else if (constraintType.getTag() == TypeTags.MAP_TAG) { - MapType mapType = (MapType) constraintType; + BMapType mapType = (BMapType) constraintType; Arrays.stream(fieldNames).forEach(field -> keyTypes.add(mapType.getConstrainedType())); } keyType = new BTupleType(keyTypes); @@ -909,10 +904,4 @@ public BObject getObjectValue(BString key) { public BArray getArrayValue(BString key) { return (BArray) get(key); } - - @Override - public Optional inherentTypeOf(Context cx) { - TypeWithShape typeWithShape = (TypeWithShape) type; - return typeWithShape.inherentTypeOf(cx, ShapeAnalyzer::inherentTypeOf, this); - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java index 6086c28633ad..b6db397f4617 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java @@ -21,7 +21,6 @@ import io.ballerina.runtime.api.types.TupleType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; -import io.ballerina.runtime.api.types.semtype.SemType; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.utils.TypeUtils; import io.ballerina.runtime.api.values.BArray; @@ -76,7 +75,6 @@ public class TupleValueImpl extends AbstractArrayValue { private final boolean hasRestElement; // cached value for ease of access private BTypedesc typedesc; private TypedescValueImpl inherentType; - private SemType shape; // ------------------------ Constructors ------------------------------------------------------------------- public TupleValueImpl(Object[] values, TupleType type) { @@ -873,14 +871,4 @@ private void validateInherentTypeOfExistingMembers(int index, int offset) { } } } - - @Override - public void cacheShape(SemType semType) { - shape = semType; - } - - @Override - public SemType shapeOf() { - return shape; - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/XmlValue.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/XmlValue.java index ea862ca298db..30c606d8c4b2 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/XmlValue.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/XmlValue.java @@ -20,9 +20,6 @@ import io.ballerina.runtime.api.types.PredefinedTypes; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.XmlNodeType; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.api.types.semtype.ShapeAnalyzer; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.values.BLink; import io.ballerina.runtime.api.values.BMap; @@ -30,14 +27,12 @@ import io.ballerina.runtime.api.values.BTypedesc; import io.ballerina.runtime.api.values.BXml; import io.ballerina.runtime.api.values.BXmlQName; -import io.ballerina.runtime.internal.types.TypeWithShape; import io.ballerina.runtime.internal.utils.IteratorUtils; import io.ballerina.runtime.internal.xml.BallerinaXmlSerializer; import java.io.OutputStream; import java.util.List; import java.util.Map; -import java.util.Optional; import javax.xml.namespace.QName; @@ -80,32 +75,30 @@ public BString getAttribute(BXmlQName attributeName) { } /** - * Set the value of a single attribute. If the attribute already exsists, then - * the value will be updated. + * Set the value of a single attribute. If the attribute already exsists, then the value will be updated. * Otherwise a new attribute will be added. * * @param attributeName Qualified name of the attribute - * @param value Value of the attribute + * @param value Value of the attribute */ @Override @Deprecated public void setAttribute(BXmlQName attributeName, String value) { setAttributeOnInitialization(attributeName.getLocalName(), attributeName.getUri(), attributeName.getPrefix(), - value); + value); } /** - * Set the value of a single attribute. If the attribute already exsists, then - * the value will be updated. + * Set the value of a single attribute. If the attribute already exsists, then the value will be updated. * Otherwise a new attribute will be added. * * @param attributeName Qualified name of the attribute - * @param value Value of the attribute + * @param value Value of the attribute */ @Deprecated public void setAttribute(BXmlQName attributeName, BString value) { setAttributeOnInitialization(attributeName.getLocalName(), attributeName.getUri(), attributeName.getPrefix(), - value.getValue()); + value.getValue()); } /** @@ -154,13 +147,12 @@ public Type getType() { protected abstract void setAttributesOnInitialization(BMap attributes); protected abstract void setAttributeOnInitialization(String localName, String namespace, String prefix, - String value); + String value); // private methods protected static void handleXmlException(String message, Throwable t) { - // Here local message of the cause is logged whenever possible, to avoid java - // class being logged + // Here local message of the cause is logged whenever possible, to avoid java class being logged // along with the error message. if (t.getCause() != null) { throw ErrorCreator.createError(StringUtils.fromString(message + t.getCause().getMessage())); @@ -192,12 +184,10 @@ protected QName getQname(String qname) { } /** - * Recursively traverse and add the descendant with the given name to the - * descendants list. - * - * @param descendants List to add descendants + * Recursively traverse and add the descendant with the given name to the descendants list. + * @param descendants List to add descendants * @param currentElement Current node - * @param qnames Qualified names of the descendants to search + * @param qnames Qualified names of the descendants to search */ protected void addDescendants(List descendants, XmlItem currentElement, List qnames) { for (BXml child : currentElement.getChildrenSeq().getChildrenList()) { @@ -283,9 +273,4 @@ public Type getIteratorNextReturnType() { return iteratorNextReturnType; } - @Override - public Optional inherentTypeOf(Context cx) { - TypeWithShape typeWithShape = (TypeWithShape) type; - return typeWithShape.inherentTypeOf(cx, ShapeAnalyzer::inherentTypeOf, this); - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/tracer/BSpan.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/tracer/BSpan.java index 50b9be5606fe..1b9ecc424ceb 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/tracer/BSpan.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/tracer/BSpan.java @@ -31,7 +31,6 @@ import io.opentelemetry.api.trace.SpanBuilder; import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.api.trace.SpanKind; -import io.opentelemetry.api.trace.StatusCode; import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.context.Context; import io.opentelemetry.context.propagation.TextMapGetter; @@ -150,10 +149,6 @@ public void addEvent(String eventName, Attributes attributes) { span.addEvent(eventName, attributes); } - public void setStatus(StatusCode statusCode) { - span.setStatus(statusCode); - } - public void addTags(Map tags) { for (Map.Entry entry : tags.entrySet()) { span.setAttribute(entry.getKey(), entry.getValue()); diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/tracer/TracingUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/tracer/TracingUtils.java index 944e804d333f..1747c16ac9b4 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/tracer/TracingUtils.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/observability/tracer/TracingUtils.java @@ -20,7 +20,6 @@ import io.ballerina.runtime.internal.values.ErrorValue; import io.ballerina.runtime.observability.ObserverContext; import io.ballerina.runtime.observability.metrics.Tag; -import io.opentelemetry.api.trace.StatusCode; import java.util.Collections; import java.util.Map; @@ -80,9 +79,6 @@ public static void stopObservation(ObserverContext observerContext) { ErrorValue bError = (ErrorValue) observerContext.getProperty(PROPERTY_ERROR_VALUE); if (bError != null) { span.addTag(TAG_KEY_STR_ERROR_MESSAGE, bError.getPrintableStackTrace()); - span.setStatus(StatusCode.ERROR); - } else { - span.setStatus(StatusCode.OK); } // Adding specific error code to Trace Span diff --git a/bvm/ballerina-runtime/src/main/java/module-info.java b/bvm/ballerina-runtime/src/main/java/module-info.java index fbb04210f3f4..d09fee04a70a 100644 --- a/bvm/ballerina-runtime/src/main/java/module-info.java +++ b/bvm/ballerina-runtime/src/main/java/module-info.java @@ -28,7 +28,6 @@ exports io.ballerina.runtime.api.types; exports io.ballerina.runtime.api.utils; exports io.ballerina.runtime.api.values; - exports io.ballerina.runtime.api.types.semtype; exports io.ballerina.runtime.observability; exports io.ballerina.runtime.observability.metrics; @@ -63,5 +62,4 @@ exports io.ballerina.runtime.internal to ballerina.debug.adapter.core, io.ballerina.cli, io.ballerina.cli.utils, io.ballerina.java, io.ballerina.lang, io.ballerina.lang.array, io.ballerina.lang.bool, io.ballerina.lang.decimal, io.ballerina.lang.error, io.ballerina.lang.floatingpoint, io.ballerina.lang.function, io.ballerina.lang.integer, io.ballerina.lang.internal, io.ballerina.lang.map, io.ballerina.lang.regexp, io.ballerina.lang.table, io.ballerina.lang.test, io.ballerina.lang.transaction, io.ballerina.lang.value, io.ballerina.lang.xml, io.ballerina.log.api, io.ballerina.runtime.profiler, io.ballerina.shell, io.ballerina.testerina.core, io.ballerina.testerina.runtime, org.ballerinalang.debugadapter.runtime; exports io.ballerina.runtime.api.repository; exports io.ballerina.runtime.internal.repository to ballerina.debug.adapter.core, io.ballerina.cli, io.ballerina.cli.utils, io.ballerina.java, io.ballerina.lang, io.ballerina.lang.array, io.ballerina.lang.bool, io.ballerina.lang.decimal, io.ballerina.lang.error, io.ballerina.lang.floatingpoint, io.ballerina.lang.function, io.ballerina.lang.integer, io.ballerina.lang.internal, io.ballerina.lang.map, io.ballerina.lang.regexp, io.ballerina.lang.table, io.ballerina.lang.test, io.ballerina.lang.transaction, io.ballerina.lang.value, io.ballerina.lang.xml, io.ballerina.log.api, io.ballerina.runtime.profiler, io.ballerina.shell, io.ballerina.testerina.core, io.ballerina.testerina.runtime, org.ballerinalang.debugadapter.runtime; - exports io.ballerina.runtime.internal.types.semtype to io.ballerina.runtime.api.types.semtype, io.ballerina.runtime.internal.types; } diff --git a/bvm/ballerina-runtime/src/test/java/io/ballerina/runtime/test/config/TomlProviderTest.java b/bvm/ballerina-runtime/src/test/java/io/ballerina/runtime/test/config/TomlProviderTest.java index e14146289491..8c4559c5a0dd 100644 --- a/bvm/ballerina-runtime/src/test/java/io/ballerina/runtime/test/config/TomlProviderTest.java +++ b/bvm/ballerina-runtime/src/test/java/io/ballerina/runtime/test/config/TomlProviderTest.java @@ -571,7 +571,7 @@ public void testTomlProviderWithString() { @Test(dataProvider = "map-data-provider") public void testTomlProviderMaps(String variableName, Type constraint, Map expectedValues) { - MapType type = TypeCreator.createMapType(variableName + "Type", constraint, ROOT_MODULE, false); + MapType type = TypeCreator.createMapType("MapType", constraint, ROOT_MODULE, false); IntersectionType mapType = new BIntersectionType(ROOT_MODULE, new Type[]{type, PredefinedTypes.TYPE_READONLY} , type, 1, true); VariableKey mapVar = new VariableKey(ROOT_MODULE, variableName, mapType, true); diff --git a/bvm/ballerina-runtime/src/test/java/io/ballerina/runtime/test/config/negative/TomlProviderNegativeTest.java b/bvm/ballerina-runtime/src/test/java/io/ballerina/runtime/test/config/negative/TomlProviderNegativeTest.java index 4a16435e7be8..a4d9fd911b17 100644 --- a/bvm/ballerina-runtime/src/test/java/io/ballerina/runtime/test/config/negative/TomlProviderNegativeTest.java +++ b/bvm/ballerina-runtime/src/test/java/io/ballerina/runtime/test/config/negative/TomlProviderNegativeTest.java @@ -283,7 +283,7 @@ public void testTableNegativeConfig(String tomlFileName, String[] errorMessages) Field age = TypeCreator.createField(PredefinedTypes.TYPE_INT, "age", SymbolFlags.OPTIONAL); Map fields = Map.ofEntries(Map.entry("name", name), Map.entry("age", age), Map.entry("id", id)); RecordType type = - TypeCreator.createRecordType("PersonTPNT", ROOT_MODULE, SymbolFlags.READONLY, fields, null, true, 6); + TypeCreator.createRecordType("Person", ROOT_MODULE, SymbolFlags.READONLY, fields, null, true, 6); TableType tableType = TypeCreator.createTableType(type, new String[]{"name"}, true); IntersectionType intersectionType = new BIntersectionType(ROOT_MODULE, new Type[]{tableType, PredefinedTypes.TYPE_READONLY}, tableType, 1, true); @@ -296,14 +296,16 @@ public void testTableNegativeConfig(String tomlFileName, String[] errorMessages) @DataProvider(name = "table-negative-tests") public Object[][] getTableNegativeTests() { - return new Object[][]{{"MissingTableKey", new String[]{ - "[MissingTableKey.toml:(6:1,8:9)] value required for key 'name' of type " + - "'table key(name) & readonly' in configurable variable 'tableVar'", - "[MissingTableKey.toml:(7:1,7:8)] unused configuration value 'tableVar.id'", - "[MissingTableKey.toml:(8:1,8:9)] unused configuration value 'tableVar.age'"}}, + return new Object[][]{ + {"MissingTableKey", new String[] { + "[MissingTableKey.toml:(6:1,8:9)] value required for key 'name' of type " + + "'table key(name) & readonly' in configurable variable 'tableVar'", + "[MissingTableKey.toml:(7:1,7:8)] unused configuration value 'tableVar.id'", + "[MissingTableKey.toml:(8:1,8:9)] unused configuration value 'tableVar.age'" + }}, {"TableTypeError", new String[] { "[TableTypeError.toml:(1:1,3:9)] configurable variable 'tableVar' is expected to be of type" + - " 'table key(name) & readonly', but found 'record'", + " 'table key(name) & readonly', but found 'record'", "[TableTypeError.toml:(2:1,2:14)] unused configuration value 'test_module.tableVar.name'", "[TableTypeError.toml:(3:1,3:9)] unused configuration value 'test_module.tableVar.age'" }}, @@ -319,11 +321,11 @@ public Object[][] getTableNegativeTests() { }}, {"AdditionalField", new String[] { "[AdditionalField.toml:(4:1,4:17)] undefined field 'city' provided for closed record " + - "'test_module:PersonTPNT'" + "'test_module:Person'" }}, {"MissingTableField", new String[] { "[MissingTableField.toml:(1:1,3:9)] value not provided for non-defaultable required field " + - "'id' of record 'test_module:PersonTPNT' in configurable variable 'tableVar'" + "'id' of record 'test_module:Person' in configurable variable 'tableVar'" }}, {"TableInlineTypeError1", new String[] { "[TableInlineTypeError1.toml:(1:34,1:37)] configurable variable 'tableVar.name' is expected " + @@ -335,7 +337,7 @@ public Object[][] getTableNegativeTests() { }}, {"TableInlineTypeError3", new String[] { "[TableInlineTypeError3.toml:(1:24,1:53)] configurable variable 'tableVar' is expected to be " + - "of type 'table key(name) & readonly', but found 'array'" + "of type 'table key(name) & readonly', but found 'array'" }}, }; } @@ -632,7 +634,7 @@ public void testInvalidIntersectionArray() { @Test public void testRestFieldInvalidType() { - RecordType recordType = TypeCreator.createRecordType("PersonTPNT2", ROOT_MODULE, SymbolFlags.READONLY, + RecordType recordType = TypeCreator.createRecordType("Person", ROOT_MODULE, SymbolFlags.READONLY, new HashMap<>(), PredefinedTypes.TYPE_INT, false, 6); VariableKey recordVar = new VariableKey(ROOT_MODULE, "person", recordType, true); String error = "[RestFieldNegative.toml:(3:8,3:14)] configurable variable 'person.name' is expected to be of " + diff --git a/bvm/ballerina-runtime/src/test/java/io/ballerina/runtime/test/semtype/CoreTests.java b/bvm/ballerina-runtime/src/test/java/io/ballerina/runtime/test/semtype/CoreTests.java deleted file mode 100644 index fba49fa5c9e2..000000000000 --- a/bvm/ballerina-runtime/src/test/java/io/ballerina/runtime/test/semtype/CoreTests.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.runtime.test.semtype; - -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.internal.types.semtype.CellAtomicType; -import io.ballerina.runtime.internal.types.semtype.ListDefinition; -import org.testng.annotations.Test; - -public class CoreTests { - - @Test - public void testCellTypes() { - Env env = Env.getInstance(); - Context cx = Context.from(env); - SemType intTy = Builder.getIntType(); - SemType readonlyInt = Builder.getCellContaining(env, intTy, CellAtomicType.CellMutability.CELL_MUT_NONE); - assert Core.isSubType(cx, readonlyInt, readonlyInt); - SemType mutableInt = Builder.getCellContaining(env, intTy, CellAtomicType.CellMutability.CELL_MUT_UNLIMITED); - assert Core.isSubType(cx, mutableInt, mutableInt); - assert Core.isSubType(cx, readonlyInt, mutableInt); - assert !Core.isSubType(cx, mutableInt, readonlyInt); - } - - @Test - public void testCellTypeCaching() { - Env env = Env.getInstance(); - SemType intTy = Builder.getIntType(); - SemType readonlyInt1 = Builder.getCellContaining(env, intTy, CellAtomicType.CellMutability.CELL_MUT_NONE); - SemType readonlyInt2 = Builder.getCellContaining(env, intTy, CellAtomicType.CellMutability.CELL_MUT_NONE); - assert readonlyInt1 == readonlyInt2; - } - - @Test - public void testSimpleList() { - Env env = Env.getInstance(); - SemType intTy = Builder.getIntType(); - // int[] - ListDefinition ld = new ListDefinition(); - SemType intListTy = - ld.defineListTypeWrapped(env, new SemType[0], 0, intTy, - CellAtomicType.CellMutability.CELL_MUT_UNLIMITED); - - // int[1] - ListDefinition ld1 = new ListDefinition(); - SemType[] members = {intTy}; - SemType intListTy1 = - ld1.defineListTypeWrapped(env, members, 1, Builder.getNeverType(), - CellAtomicType.CellMutability.CELL_MUT_UNLIMITED); - - Context cx = Context.from(env); - assert Core.isSubType(cx, intListTy1, intListTy); - } -} diff --git a/compiler/ballerina-lang/build.gradle b/compiler/ballerina-lang/build.gradle index 35fa4b1d947d..55f8b87b71ca 100644 --- a/compiler/ballerina-lang/build.gradle +++ b/compiler/ballerina-lang/build.gradle @@ -24,7 +24,6 @@ dependencies { implementation project(':ballerina-parser') implementation project(':ballerina-runtime') implementation project(':toml-parser') - implementation project(':semtypes') implementation project(':central-client') implementation project(':maven-resolver') implementation project(':identifier-util') diff --git a/compiler/ballerina-lang/spotbugs-exclude.xml b/compiler/ballerina-lang/spotbugs-exclude.xml index 5615cc897ee7..01f5d928a3e3 100644 --- a/compiler/ballerina-lang/spotbugs-exclude.xml +++ b/compiler/ballerina-lang/spotbugs-exclude.xml @@ -500,11 +500,4 @@ - - - - - - - diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/BallerinaSemanticModel.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/BallerinaSemanticModel.java index edd726b9b112..73bf9e881f9b 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/BallerinaSemanticModel.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/BallerinaSemanticModel.java @@ -38,7 +38,6 @@ import io.ballerina.tools.text.LineRange; import io.ballerina.tools.text.TextDocument; import io.ballerina.tools.text.TextRange; -import io.ballerina.types.Core; import org.ballerinalang.model.elements.Flag; import org.ballerinalang.model.symbols.SymbolKind; import org.ballerinalang.model.tree.NodeKind; @@ -54,6 +53,7 @@ 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.semantics.model.types.BFiniteType; import org.wso2.ballerinalang.compiler.semantics.model.types.BFutureType; import org.wso2.ballerinalang.compiler.semantics.model.types.BType; import org.wso2.ballerinalang.compiler.tree.BLangClassDefinition; @@ -537,12 +537,12 @@ private boolean isInlineSingletonType(BSymbol symbol) { // !(symbol.kind == SymbolKind.TYPE_DEF) is checked to exclude type defs BType type = org.wso2.ballerinalang.compiler.semantics.analyzer.Types.getImpliedType(symbol.type); return !(symbol.kind == SymbolKind.TYPE_DEF) && type.tag == TypeTags.FINITE && - Core.singleShape((symbol.type).semType()).isPresent(); + ((BFiniteType) type).getValueSpace().size() == 1; } private boolean isInlineErrorType(BSymbol symbol) { return getImpliedType(symbol.type).tag == TypeTags.ERROR && - Symbols.isFlagOn(symbol.type.getFlags(), Flags.ANONYMOUS); + Symbols.isFlagOn(symbol.type.flags, Flags.ANONYMOUS); } private boolean isTypeSymbol(BSymbol tSymbol) { diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/LangLibFunctionBinder.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/LangLibFunctionBinder.java index 5bb6b0339c2c..1118cbb37226 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/LangLibFunctionBinder.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/LangLibFunctionBinder.java @@ -130,8 +130,7 @@ private BInvokableType duplicateType(BInvokableType original, List n paramTypes.addAll(original.paramTypes); } - BInvokableType duplicate = - new BInvokableType(types.typeEnv(), paramTypes, original.restType, original.retType, null); + BInvokableType duplicate = new BInvokableType(paramTypes, original.restType, original.retType, null); BInvokableTypeSymbol originalSym = (BInvokableTypeSymbol) original.tsymbol; BInvokableTypeSymbol duplicateTSym = new BInvokableTypeSymbol(original.tag, originalSym.flags, originalSym.pkgID, duplicate, diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/SymbolFactory.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/SymbolFactory.java index 8ab3097ff9e8..b91b0c6824c4 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/SymbolFactory.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/SymbolFactory.java @@ -403,7 +403,7 @@ private boolean isReadonlyIntersectionArrayType(BType type) { type = Types.getReferredType(type); if (type.tag == TypeTags.INTERSECTION && type.tsymbol != null && type.tsymbol.getOrigin() == SymbolOrigin.VIRTUAL && - Symbols.isFlagOn(type.getFlags(), Flags.READONLY)) { + (type.flags & Flags.READONLY) == Flags.READONLY) { return true; } if (type.tag == TypeTags.ARRAY) { diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/TypeParamFinder.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/TypeParamFinder.java index d664cb2c237b..b11ed6ebfe97 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/TypeParamFinder.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/TypeParamFinder.java @@ -26,6 +26,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BAnyType; import org.wso2.ballerinalang.compiler.semantics.model.types.BAnydataType; import org.wso2.ballerinalang.compiler.semantics.model.types.BArrayType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BBuiltInRefType; import org.wso2.ballerinalang.compiler.semantics.model.types.BErrorType; import org.wso2.ballerinalang.compiler.semantics.model.types.BField; import org.wso2.ballerinalang.compiler.semantics.model.types.BFiniteType; @@ -36,6 +37,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BJSONType; import org.wso2.ballerinalang.compiler.semantics.model.types.BMapType; import org.wso2.ballerinalang.compiler.semantics.model.types.BNeverType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BNilType; import org.wso2.ballerinalang.compiler.semantics.model.types.BNoType; import org.wso2.ballerinalang.compiler.semantics.model.types.BObjectType; import org.wso2.ballerinalang.compiler.semantics.model.types.BPackageType; @@ -60,7 +62,7 @@ * * @since 2.0.0 */ -public class TypeParamFinder extends TypeVisitor { +public class TypeParamFinder implements TypeVisitor { private final Set visited = new HashSet<>(); private BType typeParam; @@ -97,6 +99,10 @@ public void visit(BArrayType bArrayType) { find(bArrayType.eType); } + @Override + public void visit(BBuiltInRefType bBuiltInRefType) { + } + @Override public void visit(BAnyType bAnyType) { } @@ -158,7 +164,7 @@ public void visit(BNeverType bNeverType) { } @Override - public void visitNilType(BType btype) { + public void visit(BNilType bNilType) { } @Override @@ -229,6 +235,10 @@ public void visit(BObjectType bObjectType) { } } + @Override + public void visit(BType bType) { + } + @Override public void visit(BFutureType bFutureType) { find(bFutureType.constraint); @@ -239,7 +249,7 @@ public void visit(BHandleType bHandleType) { } private void setContainsTypeParam(BType type) { - if (Symbols.isFlagOn(type.getFlags(), Flags.TYPE_PARAM)) { + if (Symbols.isFlagOn(type.flags, Flags.TYPE_PARAM)) { this.typeParam = type; } } diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/TypeParamResolver.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/TypeParamResolver.java index a15d5428db91..9deeb9007caf 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/TypeParamResolver.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/TypeParamResolver.java @@ -18,7 +18,6 @@ package io.ballerina.compiler.api.impl; -import io.ballerina.types.Env; import org.ballerinalang.model.symbols.AnnotationAttachmentSymbol; import org.ballerinalang.model.symbols.SymbolKind; import org.wso2.ballerinalang.compiler.semantics.analyzer.Types; @@ -31,6 +30,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BAnyType; import org.wso2.ballerinalang.compiler.semantics.model.types.BAnydataType; import org.wso2.ballerinalang.compiler.semantics.model.types.BArrayType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BBuiltInRefType; import org.wso2.ballerinalang.compiler.semantics.model.types.BErrorType; import org.wso2.ballerinalang.compiler.semantics.model.types.BField; import org.wso2.ballerinalang.compiler.semantics.model.types.BFiniteType; @@ -74,12 +74,9 @@ public class TypeParamResolver implements BTypeVisitor { private final Map boundTypes = new HashMap<>(); private final BType typeParam; private final Types types; - private final Env typeEnv; - public TypeParamResolver(BType typeParam, CompilerContext context) { this.typeParam = typeParam; types = Types.getInstance(context); - this.typeEnv = types.typeEnv(); } /** @@ -109,7 +106,7 @@ public BType resolve(BType typeParam, BType boundType) { @Override public BType visit(BType typeInSymbol, BType boundType) { - if (Symbols.isFlagOn(Flags.TYPE_PARAM, typeInSymbol.getFlags()) + if (Symbols.isFlagOn(Flags.TYPE_PARAM, typeInSymbol.flags) && types.isAssignable(typeInSymbol, this.typeParam)) { return boundType; } @@ -117,6 +114,11 @@ public BType visit(BType typeInSymbol, BType boundType) { return typeInSymbol; } + @Override + public BType visit(BBuiltInRefType typeInSymbol, BType boundType) { + return typeInSymbol; + } + @Override public BType visit(BAnyType typeInSymbol, BType boundType) { return typeInSymbol; @@ -135,8 +137,7 @@ public BType visit(BMapType typeInSymbol, BType boundType) { return typeInSymbol; } - return new BMapType(typeEnv, typeInSymbol.tag, boundConstraintType, typeInSymbol.tsymbol, - typeInSymbol.getFlags()); + return new BMapType(typeInSymbol.tag, boundConstraintType, typeInSymbol.tsymbol, typeInSymbol.flags); } @Override @@ -147,7 +148,7 @@ public BType visit(BXMLType typeInSymbol, BType boundType) { return typeInSymbol; } - return new BXMLType(boundConstraintType, typeInSymbol.tsymbol, typeInSymbol.getFlags()); + return new BXMLType(boundConstraintType, typeInSymbol.tsymbol, typeInSymbol.flags); } @Override @@ -163,9 +164,8 @@ public BType visit(BArrayType typeInSymbol, BType boundType) { return typeInSymbol; } - return new BArrayType(typeEnv, boundElemType, typeInSymbol.tsymbol, - typeInSymbol.getSize(), - typeInSymbol.state, typeInSymbol.getFlags()); + return new BArrayType(boundElemType, typeInSymbol.tsymbol, typeInSymbol.size, typeInSymbol.state, + typeInSymbol.flags); } @Override @@ -197,7 +197,7 @@ public BType visit(BObjectType typeInSymbol, BType boundType) { BObjectTypeSymbol newTypeSymbol = new BObjectTypeSymbol(objectTypeSymbol.tag, objectTypeSymbol.flags, objectTypeSymbol.name, objectTypeSymbol.pkgID, objectTypeSymbol.getType(), objectTypeSymbol.owner, objectTypeSymbol.pos, objectTypeSymbol.origin); - BObjectType newObjectType = new BObjectType(typeEnv, newTypeSymbol, typeInSymbol.getFlags()); + BObjectType newObjectType = new BObjectType(newTypeSymbol, typeInSymbol.flags); newObjectType.fields = newObjectFields; newTypeSymbol.attachedFuncs = newAttachedFuncs; @@ -217,7 +217,7 @@ public BType visit(BRecordType typeInSymbol, BType boundType) { } BType newRestType = resolve(typeInSymbol.restFieldType, boundType); - BRecordType newRecordType = new BRecordType(typeEnv, typeInSymbol.tsymbol, typeInSymbol.getFlags()); + BRecordType newRecordType = new BRecordType(typeInSymbol.tsymbol, typeInSymbol.flags); newRecordType.fields = newRecordFields; newRecordType.restFieldType = newRestType; @@ -244,8 +244,8 @@ public BType visit(BTupleType typeInSymbol, BType boundType) { return typeInSymbol; } - return new BTupleType(typeEnv, typeInSymbol.tsymbol, newTupleMembers, newRestType, - typeInSymbol.getFlags(), typeInSymbol.isCyclic); + return new BTupleType(typeInSymbol.tsymbol, newTupleMembers, newRestType, typeInSymbol.flags, + typeInSymbol.isCyclic); } @Override @@ -257,7 +257,7 @@ public BType visit(BStreamType typeInSymbol, BType boundType) { return typeInSymbol; } - return new BStreamType(typeEnv, typeInSymbol.tag, boundConstraintType, typeInSymbol.completionType, + return new BStreamType(typeInSymbol.tag, boundConstraintType, typeInSymbol.completionType, typeInSymbol.tsymbol); } @@ -270,9 +270,8 @@ public BType visit(BTableType typeInSymbol, BType boundType) { return typeInSymbol; } - BTableType bTableType = new BTableType(typeEnv, boundConstraintType, - typeInSymbol.tsymbol, - typeInSymbol.getFlags()); + BTableType bTableType = new BTableType(typeInSymbol.tag, boundConstraintType, typeInSymbol.tsymbol, + typeInSymbol.flags); bTableType.keyTypeConstraint = typeInSymbol.keyTypeConstraint; return bTableType; } @@ -312,8 +311,7 @@ public BType visit(BInvokableType typeInSymbol, BType boundType) { } invokableTypeSymbol.returnType = newReturnType; - BInvokableType type = new BInvokableType(typeEnv, newParamTypes, newRestParamType, newReturnType, - invokableTypeSymbol); + BInvokableType type = new BInvokableType(newParamTypes, newRestParamType, newReturnType, invokableTypeSymbol); invokableTypeSymbol.type = type; return type; @@ -338,7 +336,7 @@ public BType visit(BUnionType typeInSymbol, BType boundType) { return typeInSymbol; } - return BUnionType.create(typeEnv, typeInSymbol.tsymbol, newMembers); + return BUnionType.create(typeInSymbol.tsymbol, newMembers); } @Override diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/AbstractTypeSymbol.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/AbstractTypeSymbol.java index 95785eb48027..ff392b6d7f3d 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/AbstractTypeSymbol.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/AbstractTypeSymbol.java @@ -134,7 +134,7 @@ public boolean equals(Object obj) { } Types types = Types.getInstance(this.context); - return types.isSameTypeIncludingTags(this.bType, ((AbstractTypeSymbol) obj).getBType()); + return types.isSameType(this.bType, ((AbstractTypeSymbol) obj).getBType()); } @Override diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/BallerinaFunctionTypeSymbol.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/BallerinaFunctionTypeSymbol.java index 90efd9c580df..273d3f54142b 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/BallerinaFunctionTypeSymbol.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/BallerinaFunctionTypeSymbol.java @@ -179,7 +179,7 @@ public String signature() { return this.signature; } - if (Symbols.isFlagOn(getBType().getFlags(), Flags.ANY_FUNCTION)) { + if (Symbols.isFlagOn(getBType().flags, Flags.ANY_FUNCTION)) { this.signature = "function"; return this.signature; } diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/BallerinaNilTypeSymbol.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/BallerinaNilTypeSymbol.java index 021df64920bc..a692ca8493df 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/BallerinaNilTypeSymbol.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/BallerinaNilTypeSymbol.java @@ -20,7 +20,7 @@ import io.ballerina.compiler.api.SymbolVisitor; import io.ballerina.compiler.api.symbols.NilTypeSymbol; import io.ballerina.compiler.api.symbols.TypeDescKind; -import org.wso2.ballerinalang.compiler.semantics.model.types.BType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BNilType; import org.wso2.ballerinalang.compiler.util.CompilerContext; /** @@ -30,7 +30,7 @@ */ public class BallerinaNilTypeSymbol extends AbstractTypeSymbol implements NilTypeSymbol { - public BallerinaNilTypeSymbol(CompilerContext context, BType nilType) { + public BallerinaNilTypeSymbol(CompilerContext context, BNilType nilType) { super(context, TypeDescKind.NIL, nilType); } diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/BallerinaSingletonTypeSymbol.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/BallerinaSingletonTypeSymbol.java index c33968e035bf..6f9bda8b6dc4 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/BallerinaSingletonTypeSymbol.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/BallerinaSingletonTypeSymbol.java @@ -23,7 +23,9 @@ import io.ballerina.compiler.api.symbols.SingletonTypeSymbol; import io.ballerina.compiler.api.symbols.TypeDescKind; import io.ballerina.compiler.api.symbols.TypeSymbol; +import org.wso2.ballerinalang.compiler.semantics.model.types.BFiniteType; import org.wso2.ballerinalang.compiler.semantics.model.types.BType; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral; import org.wso2.ballerinalang.compiler.util.CompilerContext; import org.wso2.ballerinalang.compiler.util.TypeTags; @@ -37,26 +39,35 @@ public class BallerinaSingletonTypeSymbol extends AbstractTypeSymbol implements SingletonTypeSymbol { private final String typeName; - private final BType broadType; + private final BLangLiteral shape; private TypeSymbol originalType; - public BallerinaSingletonTypeSymbol(CompilerContext context, BType broadType, String value, BType bFiniteType) { - super(context, TypeDescKind.SINGLETON, bFiniteType); - if (TypeTags.STRING == broadType.tag) { - this.typeName = "\"" + value + "\""; + public BallerinaSingletonTypeSymbol(CompilerContext context, BLangLiteral shape, BType bType) { + super(context, TypeDescKind.SINGLETON, bType); + + if (shape.value == null && shape.originalValue == null) { + this.typeName = ""; + // Special case handling for `()` since in BLangLiteral, `null` is used to represent nil. + } else if (shape.getBType().tag == TypeTags.NIL) { + this.typeName = "()"; + // Special case handling for string type. + } else if (shape.getBType().tag == TypeTags.STRING) { + this.typeName = "\"" + shape + "\""; } else { - this.typeName = value; + this.typeName = shape.toString(); } - this.broadType = broadType; + this.shape = shape; } @Override public List langLibMethods() { if (this.langLibFunctions == null) { LangLibrary langLibrary = LangLibrary.getInstance(this.context); - List functions = langLibrary.getMethods(broadType); - this.langLibFunctions = filterLangLibMethods(functions, broadType); + BFiniteType internalType = (BFiniteType) this.getBType(); + BType valueType = internalType.getValueSpace().iterator().next().getBType(); + List functions = langLibrary.getMethods(valueType); + this.langLibFunctions = filterLangLibMethods(functions, valueType); } return this.langLibFunctions; @@ -84,7 +95,8 @@ public TypeSymbol originalType() { } TypesFactory typesFactory = TypesFactory.getInstance(this.context); - originalType = typesFactory.getTypeDescriptor(broadType); + originalType = typesFactory.getTypeDescriptor(shape.getBType()); + return originalType; } } diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/BallerinaUnionTypeSymbol.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/BallerinaUnionTypeSymbol.java index 85714fa67c5d..101f370bd464 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/BallerinaUnionTypeSymbol.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/BallerinaUnionTypeSymbol.java @@ -16,51 +16,35 @@ */ package io.ballerina.compiler.api.impl.symbols; +import io.ballerina.compiler.api.ModuleID; import io.ballerina.compiler.api.SymbolTransformer; import io.ballerina.compiler.api.SymbolVisitor; import io.ballerina.compiler.api.symbols.TypeDescKind; import io.ballerina.compiler.api.symbols.TypeSymbol; import io.ballerina.compiler.api.symbols.UnionTypeSymbol; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.ComplexSemType; -import io.ballerina.types.Core; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.subtypedata.BooleanSubtype; -import io.ballerina.types.subtypedata.DecimalSubtype; -import io.ballerina.types.subtypedata.FloatSubtype; -import io.ballerina.types.subtypedata.IntSubtype; -import io.ballerina.types.subtypedata.StringSubtype; import org.ballerinalang.model.types.TypeKind; -import org.wso2.ballerinalang.compiler.semantics.model.SymbolTable; import org.wso2.ballerinalang.compiler.semantics.model.symbols.Symbols; import org.wso2.ballerinalang.compiler.semantics.model.types.BFiniteType; import org.wso2.ballerinalang.compiler.semantics.model.types.BType; import org.wso2.ballerinalang.compiler.semantics.model.types.BUnionType; -import org.wso2.ballerinalang.compiler.semantics.model.types.SemNamedType; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangExpression; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral; import org.wso2.ballerinalang.compiler.util.CompilerContext; -import org.wso2.ballerinalang.compiler.util.Names; import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.util.Flags; -import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.StringJoiner; import java.util.regex.Pattern; import static io.ballerina.compiler.api.symbols.TypeDescKind.FUNCTION; import static io.ballerina.compiler.api.symbols.TypeDescKind.INTERSECTION; import static io.ballerina.compiler.api.symbols.TypeDescKind.NIL; -import static io.ballerina.types.BasicTypeCode.BT_BOOLEAN; -import static io.ballerina.types.BasicTypeCode.BT_DECIMAL; -import static io.ballerina.types.BasicTypeCode.BT_FLOAT; -import static io.ballerina.types.BasicTypeCode.BT_INT; -import static io.ballerina.types.BasicTypeCode.BT_STRING; -import static io.ballerina.types.Core.getComplexSubtypeData; -import static io.ballerina.types.SemTypes.isSubtypeSimple; /** * Represents an union type descriptor. @@ -76,16 +60,13 @@ public class BallerinaUnionTypeSymbol extends AbstractTypeSymbol implements Unio private List memberTypes; private List originalMemberTypes; private String signature; - private SymbolTable symTable; public BallerinaUnionTypeSymbol(CompilerContext context, BUnionType unionType) { super(context, TypeDescKind.UNION, unionType); - this.symTable = SymbolTable.getInstance(context); } public BallerinaUnionTypeSymbol(CompilerContext context, BFiniteType finiteType) { super(context, TypeDescKind.UNION, finiteType); - this.symTable = SymbolTable.getInstance(context); } @Override @@ -101,10 +82,22 @@ public List memberTypeDescriptors() { members.add(typesFactory.getTypeDescriptor(memberType)); continue; } - updateMembersForBFiniteType(members, (BFiniteType) memberType); + + BFiniteType finiteType = (BFiniteType) memberType; + for (BLangExpression value : finiteType.getValueSpace()) { + ModuleID moduleID = getModule().isPresent() ? getModule().get().id() : null; + BFiniteType bFiniteType = new BFiniteType(value.getBType().tsymbol, Set.of(value)); + members.add(new BallerinaSingletonTypeSymbol(this.context, (BLangLiteral) value, + bFiniteType)); + } } } else { - updateMembersForBFiniteType(members, (BFiniteType) this.getBType()); + for (BLangExpression value : ((BFiniteType) this.getBType()).getValueSpace()) { + ModuleID moduleID = getModule().isPresent() ? getModule().get().id() : null; + BFiniteType bFiniteType = new BFiniteType(value.getBType().tsymbol, Set.of(value)); + members.add(new BallerinaSingletonTypeSymbol(this.context, (BLangLiteral) value, + bFiniteType)); + } } this.memberTypes = Collections.unmodifiableList(members); @@ -113,46 +106,6 @@ public List memberTypeDescriptors() { return this.memberTypes; } - @SuppressWarnings("OptionalGetWithoutIsPresent") // xxxSubtypeSingleValue() are guaranteed to have a value - private void updateMembersForBFiniteType(List members, BFiniteType bFiniteType) { - for (SemNamedType semNamedType : bFiniteType.valueSpace) { - SemType s = semNamedType.semType(); - BFiniteType ft = BFiniteType.newSingletonBFiniteType(null, s); - if (PredefinedType.NIL.equals(s)) { - members.add(new BallerinaSingletonTypeSymbol(context, symTable.nilType, Names.NIL_VALUE.value, ft)); - continue; - } - - ComplexSemType cs = (ComplexSemType) s; - BType broadType; - String value; - if (isSubtypeSimple(s, PredefinedType.BOOLEAN)) { - broadType = symTable.booleanType; - boolean boolVal = BooleanSubtype.booleanSubtypeSingleValue(getComplexSubtypeData(cs, BT_BOOLEAN)).get(); - value = boolVal ? Names.TRUE.value : Names.FALSE.value; - } else if (isSubtypeSimple(s, PredefinedType.INT)) { - broadType = symTable.intType; - long longVal = IntSubtype.intSubtypeSingleValue(getComplexSubtypeData(cs, BT_INT)).get(); - value = Long.toString(longVal); - } else if (isSubtypeSimple(s, PredefinedType.FLOAT)) { - broadType = symTable.floatType; - double doubleVal = FloatSubtype.floatSubtypeSingleValue(getComplexSubtypeData(cs, BT_FLOAT)).get(); - value = Double.toString(doubleVal); - } else if (isSubtypeSimple(s, PredefinedType.DECIMAL)) { - broadType = symTable.decimalType; - BigDecimal bVal = DecimalSubtype.decimalSubtypeSingleValue(getComplexSubtypeData(cs, BT_DECIMAL)).get(); - value = bVal.toPlainString(); - } else if (isSubtypeSimple(s, PredefinedType.STRING)) { - broadType = symTable.stringType; - value = StringSubtype.stringSubtypeSingleValue(getComplexSubtypeData(cs, BT_STRING)).get(); - } else { - throw new IllegalStateException("Unexpected value space type: " + s); - } - - members.add(new BallerinaSingletonTypeSymbol(context, broadType, value, ft)); - } - } - @Override public List userSpecifiedMemberTypes() { if (this.originalMemberTypes == null) { @@ -165,7 +118,11 @@ public List userSpecifiedMemberTypes() { members.add(typesFactory.getTypeDescriptor(memberType)); } } else { - updateMembersForBFiniteType(members, (BFiniteType) this.getBType()); + for (BLangExpression value : ((BFiniteType) this.getBType()).getValueSpace()) { + ModuleID moduleID = getModule().isPresent() ? getModule().get().id() : null; + members.add(new BallerinaSingletonTypeSymbol(this.context, (BLangLiteral) value, + value.getBType())); + } } this.originalMemberTypes = Collections.unmodifiableList(members); @@ -207,7 +164,7 @@ private String getSignatureForUnion(BType type) { if (unionType.isCyclic && (unionType.tsymbol != null) && !unionType.tsymbol.getName().getValue().isEmpty()) { String typeStr; typeStr = unionType.tsymbol.getName().getValue(); - if (Symbols.isFlagOn(unionType.getFlags(), Flags.TYPE_PARAM) && pCloneableType.matcher(typeStr).matches()) { + if (Symbols.isFlagOn(unionType.flags, Flags.TYPE_PARAM) && pCloneableType.matcher(typeStr).matches()) { typeStr = CLONEABLE; } return typeStr; @@ -268,7 +225,7 @@ private boolean containsTwoElements(List types) { if (types.size() == 2) { for (TypeSymbol type : types) { BType internalType = ((AbstractTypeSymbol) type).getBType(); - if (internalType.tag == TypeTags.FINITE && Core.singleShape(internalType.semType()).isEmpty()) { + if (internalType.tag == TypeTags.FINITE && ((BFiniteType) internalType).getValueSpace().size() > 1) { return false; } } diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/TypesFactory.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/TypesFactory.java index 129b085a4ce3..3c0705554eda 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/TypesFactory.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/TypesFactory.java @@ -22,13 +22,9 @@ import io.ballerina.compiler.api.symbols.TypeDescKind; import io.ballerina.compiler.api.symbols.TypeSymbol; import io.ballerina.compiler.api.symbols.XMLTypeSymbol; -import io.ballerina.types.Core; -import io.ballerina.types.Value; import org.ballerinalang.model.symbols.SymbolKind; import org.ballerinalang.model.types.TypeKind; import org.wso2.ballerinalang.compiler.parser.BLangAnonymousModelHelper; -import org.wso2.ballerinalang.compiler.semantics.analyzer.SemTypeHelper; -import org.wso2.ballerinalang.compiler.semantics.model.SymbolTable; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BClassSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableTypeSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BSymbol; @@ -48,6 +44,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BJSONType; import org.wso2.ballerinalang.compiler.semantics.model.types.BMapType; import org.wso2.ballerinalang.compiler.semantics.model.types.BNeverType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BNilType; import org.wso2.ballerinalang.compiler.semantics.model.types.BNoType; import org.wso2.ballerinalang.compiler.semantics.model.types.BObjectType; import org.wso2.ballerinalang.compiler.semantics.model.types.BReadonlyType; @@ -62,12 +59,13 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BUnionType; import org.wso2.ballerinalang.compiler.semantics.model.types.BXMLSubType; import org.wso2.ballerinalang.compiler.semantics.model.types.BXMLType; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangExpression; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral; import org.wso2.ballerinalang.compiler.util.CompilerContext; import org.wso2.ballerinalang.compiler.util.Names; import org.wso2.ballerinalang.util.Flags; -import java.util.Objects; -import java.util.Optional; +import java.util.Set; import static org.ballerinalang.model.types.TypeKind.PARAMETERIZED; import static org.wso2.ballerinalang.compiler.util.TypeTags.ANY; @@ -114,7 +112,6 @@ public class TypesFactory { private final CompilerContext context; private final SymbolFactory symbolFactory; private final BLangAnonymousModelHelper anonymousModelHelper; - private SymbolTable symTable; private TypesFactory(CompilerContext context) { context.put(TYPES_FACTORY_KEY, this); @@ -122,7 +119,6 @@ private TypesFactory(CompilerContext context) { this.context = context; this.symbolFactory = SymbolFactory.getInstance(context); this.anonymousModelHelper = BLangAnonymousModelHelper.getInstance(context); - this.symTable = SymbolTable.getInstance(context); } public static TypesFactory getInstance(CompilerContext context) { @@ -235,16 +231,16 @@ private TypeSymbol createTypeDescriptor(BType bType, BTypeSymbol tSymbol) { case TYPEDESC: return new BallerinaTypeDescTypeSymbol(this.context, (BTypedescType) bType); case NIL: - return new BallerinaNilTypeSymbol(this.context, bType); + return new BallerinaNilTypeSymbol(this.context, (BNilType) bType); case FINITE: BFiniteType finiteType = (BFiniteType) bType; - Optional value = Core.singleShape(finiteType.semType()); - if (value.isPresent()) { - BType broadType = SemTypeHelper.broadTypes(finiteType, symTable).iterator() - .next(); - String valueString = Objects.toString(value.get().value, "()"); - return new BallerinaSingletonTypeSymbol(this.context, broadType, valueString, bType); + Set valueSpace = finiteType.getValueSpace(); + + if (valueSpace.size() == 1) { + BLangExpression shape = valueSpace.iterator().next(); + return new BallerinaSingletonTypeSymbol(this.context, (BLangLiteral) shape, bType); } + return new BallerinaUnionTypeSymbol(this.context, finiteType); case FUNCTION: return new BallerinaFunctionTypeSymbol(this.context, (BInvokableTypeSymbol) tSymbol, bType); diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaArrayTypeBuilder.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaArrayTypeBuilder.java index eb01b5ba9838..72702a3e9105 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaArrayTypeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaArrayTypeBuilder.java @@ -86,7 +86,7 @@ public ArrayTypeSymbol build() { BTypeSymbol arrayTSymbol = Symbols.createTypeSymbol(SymTag.ARRAY_TYPE, Flags.PUBLIC, Names.EMPTY, symTable.rootPkgSymbol.pkgID, null, symTable.rootPkgSymbol, symTable.builtinPos, COMPILED_SOURCE); - BArrayType arrayType = new BArrayType(symTable.typeEnv(), getBType(type), arrayTSymbol, size, state); + BArrayType arrayType = new BArrayType(getBType(type), arrayTSymbol, size, state); arrayTSymbol.type = arrayType; ArrayTypeSymbol arrayTypeSymbol = (ArrayTypeSymbol) typesFactory.getTypeDescriptor(arrayType); this.size = -1; diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaErrorTypeBuilder.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaErrorTypeBuilder.java index 04d1ffbd17af..179cb64da617 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaErrorTypeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaErrorTypeBuilder.java @@ -71,7 +71,7 @@ public ErrorTypeSymbol build() { symTable.rootPkgSymbol.pkgID, symTable.errorType, symTable.rootPkgSymbol, symTable.builtinPos, COMPILED_SOURCE); - BErrorType errorType = new BErrorType(symTable.typeEnv(), errorTSymbol, getBType(typeParam)); + BErrorType errorType = new BErrorType(errorTSymbol, getBType(typeParam)); errorTSymbol.type = errorType; ErrorTypeSymbol errorTypeSymbol = (ErrorTypeSymbol) typesFactory.getTypeDescriptor(errorType); this.typeParam = null; diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaFunctionTypeBuilder.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaFunctionTypeBuilder.java index c64d8c6cd2cc..178519d7121a 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaFunctionTypeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaFunctionTypeBuilder.java @@ -107,8 +107,7 @@ public FunctionTypeSymbol build() { tSymbol.returnType = returnType; tSymbol.params = getParamSymbols(parameterSymbols); tSymbol.restParam = getRestParamSymbol(restParam, restType); - BInvokableType bInvokableType = - new BInvokableType(symTable.typeEnv(), paramTypes, restType, returnType, tSymbol); + BInvokableType bInvokableType = new BInvokableType(paramTypes, restType, returnType, tSymbol); FunctionTypeSymbol functionTypeSymbol = (FunctionTypeSymbol) typesFactory.getTypeDescriptor(bInvokableType); parameterSymbols.clear(); restParam = null; @@ -140,7 +139,7 @@ private BType getRestType(ParameterSymbol restParam) { BTypeSymbol restArraySymbol = Symbols.createTypeSymbol(SymTag.ARRAY_TYPE, Flags.PUBLIC, Names.EMPTY, symTable.rootPkgSymbol.pkgID, null, symTable.rootPkgSymbol, symTable.builtinPos, COMPILED_SOURCE); - BArrayType restArrayType = new BArrayType(symTable.typeEnv(), bType, restArraySymbol, -1, BArrayState.OPEN); + BArrayType restArrayType = new BArrayType(bType, restArraySymbol, -1, BArrayState.OPEN); restArraySymbol.type = restArrayType; return restArrayType; diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaFutureTypeBuilder.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaFutureTypeBuilder.java index af0fcab472d5..073cf34788a8 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaFutureTypeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaFutureTypeBuilder.java @@ -31,6 +31,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BType; import org.wso2.ballerinalang.compiler.util.CompilerContext; import org.wso2.ballerinalang.compiler.util.Names; +import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.util.Flags; import static org.ballerinalang.model.symbols.SymbolOrigin.COMPILED_SOURCE; @@ -62,7 +63,7 @@ public FutureTypeSymbol build() { BTypeSymbol futureTSymbol = Symbols.createTypeSymbol(SymTag.TYPE, Flags.PUBLIC, Names.EMPTY, symTable.rootPkgSymbol.pkgID, null, symTable.rootPkgSymbol, symTable.builtinPos, COMPILED_SOURCE); - BFutureType futureType = new BFutureType(symTable.typeEnv(), getBType(typeParam), futureTSymbol); + BFutureType futureType = new BFutureType(TypeTags.FUTURE, getBType(typeParam), futureTSymbol); futureTSymbol.type = futureType; FutureTypeSymbol futureTypeSymbol = (FutureTypeSymbol) typesFactory.getTypeDescriptor(futureType); this.typeParam = null; diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaMapTypeBuilder.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaMapTypeBuilder.java index f0df782d7a48..a97976f1a1e8 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaMapTypeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaMapTypeBuilder.java @@ -63,7 +63,7 @@ public MapTypeSymbol build() { symTable.rootPkgSymbol.pkgID, null, symTable.rootPkgSymbol, symTable.builtinPos, symTable.rootPkgSymbol.origin); - BMapType mapType = new BMapType(symTable.typeEnv(), TypeTags.MAP, getBType(typeParam), mapTSymbol); + BMapType mapType = new BMapType(TypeTags.MAP, getBType(typeParam), mapTSymbol); mapTSymbol.type = mapType; MapTypeSymbol mapTypeSymbol = (MapTypeSymbol) typesFactory.getTypeDescriptor(mapType); this.typeParam = null; diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaObjectTypeBuilder.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaObjectTypeBuilder.java index 6dc6cfbce892..ed7387eab7c7 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaObjectTypeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaObjectTypeBuilder.java @@ -132,7 +132,7 @@ public ObjectTypeSymbol build() { BObjectTypeSymbol objectSymbol = Symbols.createObjectSymbol(Flags.asMask(flags), Names.EMPTY, symTable.rootPkgSymbol.pkgID, null, symTable.rootPkgSymbol.owner, symTable.builtinPos, COMPILED_SOURCE); - BObjectType objectType = new BObjectType(symTable.typeEnv(), objectSymbol, typeFlags); + BObjectType objectType = new BObjectType(objectSymbol, typeFlags); objectType.fields = getObjectFields(objectFieldList, objectSymbol); objectType.typeInclusions.addAll(getTypeInclusions(typeInclusions)); objectSymbol.type = objectType; diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaRecordTypeBuilder.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaRecordTypeBuilder.java index cb7d7d80e089..33c88117390f 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaRecordTypeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaRecordTypeBuilder.java @@ -95,7 +95,7 @@ public RecordTypeSymbol build() { symTable.rootPkgSymbol.pkgID, null, symTable.rootPkgSymbol, symTable.builtinPos, symTable.rootPkgSymbol.origin); - BRecordType recordType = new BRecordType(symTable.typeEnv(), recordSymbol); + BRecordType recordType = new BRecordType(recordSymbol); recordSymbol.type = recordType; recordType.typeInclusions = getTypeInclusions(typeInclusions); if (restField == null) { diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaSingletonTypeBuilder.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaSingletonTypeBuilder.java index fc0ab4dd8cbb..148ebbed813b 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaSingletonTypeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaSingletonTypeBuilder.java @@ -23,7 +23,6 @@ import io.ballerina.compiler.api.impl.symbols.TypesFactory; import io.ballerina.compiler.api.symbols.SingletonTypeSymbol; import io.ballerina.compiler.api.symbols.TypeSymbol; -import org.wso2.ballerinalang.compiler.semantics.analyzer.SemTypeHelper; import org.wso2.ballerinalang.compiler.semantics.model.SymbolTable; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BTypeSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.SymTag; @@ -35,6 +34,8 @@ import org.wso2.ballerinalang.compiler.util.Names; import org.wso2.ballerinalang.util.Flags; +import java.util.Set; + import static org.ballerinalang.model.symbols.SymbolOrigin.COMPILED_SOURCE; /** @@ -76,8 +77,7 @@ public SingletonTypeSymbol build() { Names.fromString(value.toString()), symTable.rootPkgSymbol.pkgID, null, symTable.rootPkgSymbol, symTable.builtinPos, COMPILED_SOURCE); - BFiniteType finiteType = BFiniteType.newSingletonBFiniteType(finiteTypeSymbol, - SemTypeHelper.resolveSingletonType(valueLiteral)); + BFiniteType finiteType = new BFiniteType(finiteTypeSymbol, Set.of(valueLiteral)); finiteTypeSymbol.type = finiteType; SingletonTypeSymbol singletonTypeSymbol = (SingletonTypeSymbol) typesFactory.getTypeDescriptor(finiteType, finiteTypeSymbol, true); diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaStreamTypeBuilder.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaStreamTypeBuilder.java index 2c06b0e2876a..e71fc54136c9 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaStreamTypeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaStreamTypeBuilder.java @@ -69,7 +69,7 @@ public StreamTypeSymbol build() { symTable.rootPkgSymbol.pkgID, null, symTable.rootPkgSymbol, symTable.builtinPos, symTable.rootPkgSymbol.origin); - BStreamType streamType = new BStreamType(symTable.typeEnv(), TypeTags.STREAM, getValueBType(this.valueType), + BStreamType streamType = new BStreamType(TypeTags.STREAM, getValueBType(this.valueType), getCompletionBType(this.completionType), streamSymbol); streamSymbol.type = streamType; diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaTableTypeBuilder.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaTableTypeBuilder.java index a749896d70ae..18af7c102770 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaTableTypeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaTableTypeBuilder.java @@ -43,6 +43,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BType; import org.wso2.ballerinalang.compiler.util.CompilerContext; import org.wso2.ballerinalang.compiler.util.Names; +import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.util.Flags; import java.util.ArrayList; @@ -104,7 +105,7 @@ public TableTypeSymbol build() { symTable.rootPkgSymbol.pkgID, null, symTable.rootPkgSymbol, symTable.builtinPos, symTable.rootPkgSymbol.origin); - BTableType tableType = new BTableType(symTable.typeEnv(), rowBType, tableSymbol); + BTableType tableType = new BTableType(TypeTags.TABLE, rowBType, tableSymbol); tableSymbol.type = tableType; if (!keyTypes.isEmpty()) { tableType.keyTypeConstraint = getKeyConstraintBType(keyTypes, rowType); @@ -146,7 +147,7 @@ private boolean isReadOnlyField(RecordFieldSymbol recordField) { if (typeDescriptor instanceof AbstractTypeSymbol abstractTypeSymbol) { BType bType = abstractTypeSymbol.getBType(); - return Symbols.isFlagOn(bType.getFlags(), Flags.READONLY); + return Symbols.isFlagOn(bType.flags, Flags.READONLY); } return false; @@ -164,7 +165,7 @@ private BType getKeyConstraintBType(List keyTypes, TypeSymbol rowTyp tupleMembers.add(new BTupleMember(constraintType, varSymbol)); } - return new BTupleType(symTable.typeEnv(), tupleMembers); + return new BTupleType(tupleMembers); } private BType checkKeyConstraintBType(TypeSymbol keyType, TypeSymbol rowType) { @@ -192,7 +193,7 @@ private BType checkKeyConstraintBType(TypeSymbol keyType, TypeSymbol rowType) { private boolean isValidKeyConstraintType(TypeSymbol fieldType, TypeSymbol keyType) { if ((fieldType.typeKind() == keyType.typeKind() || keyType.subtypeOf(fieldType)) && fieldType instanceof AbstractTypeSymbol abstractTypeSymbol) { - return Symbols.isFlagOn(abstractTypeSymbol.getBType().getFlags(), Flags.READONLY); + return Symbols.isFlagOn(abstractTypeSymbol.getBType().flags, Flags.READONLY); } return false; diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaTupleTypeBuilder.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaTupleTypeBuilder.java index c4dbda213ef4..9b401688b982 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaTupleTypeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaTupleTypeBuilder.java @@ -81,7 +81,7 @@ public TupleTypeSymbol build() { symTable.rootPkgSymbol.pkgID, null, symTable.rootPkgSymbol, symTable.builtinPos, SymbolOrigin.COMPILED_SOURCE); - BTupleType tupleType = new BTupleType(symTable.typeEnv(), tupleSymbol, memberTypes); + BTupleType tupleType = new BTupleType(tupleSymbol, memberTypes); tupleSymbol.type = tupleType; BType restBType = getRestType(restType); if (restBType != null) { diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaTypeDescTypeBuilder.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaTypeDescTypeBuilder.java index df8a1f09f4c3..d387090e8562 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaTypeDescTypeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaTypeDescTypeBuilder.java @@ -62,7 +62,7 @@ public TypeDescTypeSymbol build() { symTable.rootPkgSymbol.pkgID, null, symTable.rootPkgSymbol, symTable.builtinPos, SymbolOrigin.COMPILED_SOURCE); - BTypedescType typedescType = new BTypedescType(symTable.typeEnv(), getBType(typeParam), typedescSymbol); + BTypedescType typedescType = new BTypedescType(getBType(typeParam), typedescSymbol); typedescSymbol.type = typedescType; TypeDescTypeSymbol typeDescTypeSymbol = (TypeDescTypeSymbol) typesFactory.getTypeDescriptor(typedescType); this.typeParam = null; diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaUnionTypeBuilder.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaUnionTypeBuilder.java index a9572608685f..fd0d90aec70a 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaUnionTypeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/type/builders/BallerinaUnionTypeBuilder.java @@ -77,7 +77,7 @@ public TypeBuilder.UNION withMemberTypes(TypeSymbol... memberTypes) { public UnionTypeSymbol build() { BTypeSymbol unionSymbol = Symbols.createTypeSymbol(SymTag.UNION_TYPE, Flags.PUBLIC, Names.EMPTY, symTable.rootPkgSymbol.pkgID, null, symTable.rootPkgSymbol, symTable.builtinPos, COMPILED_SOURCE); - BUnionType unionType = BUnionType.create(symTable.typeEnv(), unionSymbol, getMemberBTypes()); + BUnionType unionType = BUnionType.create(unionSymbol, getMemberBTypes()); UnionTypeSymbol unionTypeSymbol = (UnionTypeSymbol) typesFactory.getTypeDescriptor(unionType); memberTypes.clear(); diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/projects/ModuleContext.java b/compiler/ballerina-lang/src/main/java/io/ballerina/projects/ModuleContext.java index 1bb02b26d59e..de2ec9c100ab 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/projects/ModuleContext.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/projects/ModuleContext.java @@ -35,8 +35,6 @@ import org.wso2.ballerinalang.compiler.bir.writer.BIRBinaryWriter; import org.wso2.ballerinalang.compiler.diagnostic.BLangDiagnosticLocation; import org.wso2.ballerinalang.compiler.semantics.analyzer.SymbolEnter; -import org.wso2.ballerinalang.compiler.semantics.analyzer.Types; -import org.wso2.ballerinalang.compiler.semantics.model.SymbolTable; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BPackageSymbol; import org.wso2.ballerinalang.compiler.tree.BLangPackage; import org.wso2.ballerinalang.compiler.tree.BLangTestablePackage; @@ -246,8 +244,7 @@ List diagnostics() { } private void parseTestSources(BLangPackage pkgNode, PackageID pkgId, CompilerContext compilerContext) { - Types types = Types.getInstance(compilerContext); - BLangTestablePackage testablePkg = TreeBuilder.createTestablePackageNode(types.typeEnv()); + BLangTestablePackage testablePkg = TreeBuilder.createTestablePackageNode(); // TODO Not sure why we need to do this. It is there in the current implementation testablePkg.packageID = pkgId; testablePkg.flagSet.add(Flag.TESTABLE); @@ -378,8 +375,7 @@ static void compileInternal(ModuleContext moduleContext, CompilerContext compile SymbolEnter symbolEnter = SymbolEnter.getInstance(compilerContext); CompilerPhaseRunner compilerPhaseRunner = CompilerPhaseRunner.getInstance(compilerContext); - Types types = Types.getInstance(compilerContext); - BLangPackage pkgNode = (BLangPackage) TreeBuilder.createPackageNode(types.typeEnv()); + BLangPackage pkgNode = (BLangPackage) TreeBuilder.createPackageNode(); pkgNode.moduleContextDataHolder = new ModuleContextDataHolder( moduleContext.isExported(), moduleContext.descriptor(), @@ -494,13 +490,11 @@ private static ByteArrayOutputStream generateBIR(ModuleContext moduleContext, Co } // Can we improve this logic ByteArrayOutputStream birContent = new ByteArrayOutputStream(); - SymbolTable symTable = SymbolTable.getInstance(compilerContext); try { CompiledBinaryFile.BIRPackageFile birPackageFile = moduleContext.bLangPackage.symbol.birPackageFile; if (birPackageFile == null) { birPackageFile = new CompiledBinaryFile - .BIRPackageFile( - new BIRBinaryWriter(moduleContext.bLangPackage.symbol.bir, symTable.typeEnv()).serialize()); + .BIRPackageFile(new BIRBinaryWriter(moduleContext.bLangPackage.symbol.bir).serialize()); moduleContext.bLangPackage.symbol.birPackageFile = birPackageFile; } byte[] pkgBirBinaryContent = PackageFileWriter.writePackage(birPackageFile); diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/projects/internal/configschema/TypeConverter.java b/compiler/ballerina-lang/src/main/java/io/ballerina/projects/internal/configschema/TypeConverter.java index 668b0989786f..17cdd218c171 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/projects/internal/configschema/TypeConverter.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/projects/internal/configschema/TypeConverter.java @@ -19,14 +19,6 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; -import io.ballerina.types.ComplexSemType; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.subtypedata.BooleanSubtype; -import io.ballerina.types.subtypedata.DecimalSubtype; -import io.ballerina.types.subtypedata.FloatSubtype; -import io.ballerina.types.subtypedata.IntSubtype; -import io.ballerina.types.subtypedata.StringSubtype; import org.wso2.ballerinalang.compiler.semantics.analyzer.Types; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BTypeSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.Symbols; @@ -40,23 +32,16 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BType; 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.SemNamedType; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangNumericLiteral; import org.wso2.ballerinalang.compiler.util.Names; import org.wso2.ballerinalang.compiler.util.TypeTags; -import java.math.BigDecimal; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; -import static io.ballerina.types.Core.getComplexSubtypeData; -import static io.ballerina.types.SemTypes.isSubtypeSimple; -import static io.ballerina.types.BasicTypeCode.BT_BOOLEAN; -import static io.ballerina.types.BasicTypeCode.BT_DECIMAL; -import static io.ballerina.types.BasicTypeCode.BT_FLOAT; -import static io.ballerina.types.BasicTypeCode.BT_INT; -import static io.ballerina.types.BasicTypeCode.BT_STRING; import static org.wso2.ballerinalang.compiler.util.TypeTags.BOOLEAN; import static org.wso2.ballerinalang.compiler.util.TypeTags.BYTE; import static org.wso2.ballerinalang.compiler.util.TypeTags.DECIMAL; @@ -112,7 +97,7 @@ JsonObject getType(BType type) { typeNode.addProperty(TYPE, typeVal); return typeNode; } - + VisitedType visitedType = getVisitedType(effectiveType.toString()); if (visitedType != null) { if (visitedType.isCompleted()) { @@ -282,33 +267,24 @@ private void updateUnionMembers(LinkedHashSet members, JsonArray memberAr * @param enumArray JSON array to add the enum values * @param finiteType BFiniteType to retrieve enum values from */ - @SuppressWarnings("OptionalGetWithoutIsPresent") // xxxSubtypeSingleValue() are guaranteed to have a value private static void getEnumArray(JsonArray enumArray, BFiniteType finiteType) { - for (SemNamedType semNamedType : finiteType.valueSpace) { - SemType s = semNamedType.semType(); - if (PredefinedType.NIL.equals(s)) { - enumArray.add(Names.NIL_VALUE.value); - continue; - } - - ComplexSemType cs = (ComplexSemType) s; - if (isSubtypeSimple(s, PredefinedType.BOOLEAN)) { - boolean boolVal = BooleanSubtype.booleanSubtypeSingleValue(getComplexSubtypeData(cs, BT_BOOLEAN)).get(); - enumArray.add(boolVal ? Names.TRUE.value : Names.FALSE.value); - } else if (isSubtypeSimple(s, PredefinedType.INT)) { - long longVal = IntSubtype.intSubtypeSingleValue(getComplexSubtypeData(cs, BT_INT)).get(); - enumArray.add(longVal); - } else if (isSubtypeSimple(s, PredefinedType.FLOAT)) { - double doubleVal = FloatSubtype.floatSubtypeSingleValue(getComplexSubtypeData(cs, BT_FLOAT)).get(); - enumArray.add(doubleVal); - } else if (isSubtypeSimple(s, PredefinedType.DECIMAL)) { - BigDecimal bVal = DecimalSubtype.decimalSubtypeSingleValue(getComplexSubtypeData(cs, BT_DECIMAL)).get(); - enumArray.add(bVal.toString()); - } else if (isSubtypeSimple(s, PredefinedType.STRING)) { - String stringVal = StringSubtype.stringSubtypeSingleValue(getComplexSubtypeData(cs, BT_STRING)).get(); - enumArray.add(stringVal); - } else { - throw new IllegalStateException("Unexpected value space type: " + s); + Object[] values = finiteType.getValueSpace().toArray(); + for (Object finiteValue : values) { + if (finiteValue instanceof BLangNumericLiteral numericLiteral) { + BType bType = numericLiteral.getBType(); + // In the BLangNumericLiteral the integer typed values are represented as numeric values + // while the decimal values are represented as String + Object value = numericLiteral.getValue(); + if (TypeTags.isIntegerTypeTag(bType.tag)) { + // Any integer can be considered as a long and added as a numeric value to the enum array + if (value instanceof Long l) { + enumArray.add(l); + } + } else { + enumArray.add(Double.parseDouble(value.toString())); + } + } else if (finiteValue instanceof BLangLiteral bLangLiteral) { + enumArray.add(bLangLiteral.getValue().toString()); } } } diff --git a/compiler/ballerina-lang/src/main/java/module-info.java b/compiler/ballerina-lang/src/main/java/module-info.java index 320ee6cc2817..bf773acd7296 100644 --- a/compiler/ballerina-lang/src/main/java/module-info.java +++ b/compiler/ballerina-lang/src/main/java/module-info.java @@ -16,7 +16,6 @@ requires org.apache.commons.io; requires io.ballerina.toml; requires io.ballerina.central.client; - requires io.ballerina.semtype; requires io.ballerina.identifier; requires java.semver; requires maven.resolver; diff --git a/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/TreeBuilder.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/TreeBuilder.java index 891927afecda..7e269184fa01 100644 --- a/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/TreeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/TreeBuilder.java @@ -17,7 +17,6 @@ */ package org.ballerinalang.model; -import io.ballerina.types.Env; import org.ballerinalang.model.clauses.CollectClauseNode; import org.ballerinalang.model.clauses.DoClauseNode; import org.ballerinalang.model.clauses.GroupByClauseNode; @@ -396,12 +395,12 @@ public static CompilationUnitNode createCompilationUnit() { return new BLangCompilationUnit(); } - public static PackageNode createPackageNode(Env typeEnv) { - return new BLangPackage(typeEnv); + public static PackageNode createPackageNode() { + return new BLangPackage(); } - public static BLangTestablePackage createTestablePackageNode(Env typeEnv) { - return new BLangTestablePackage(typeEnv); + public static BLangTestablePackage createTestablePackageNode() { + return new BLangTestablePackage(); } public static IdentifierNode createIdentifierNode() { diff --git a/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/types/ConnectorType.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/types/ConnectorType.java new file mode 100644 index 000000000000..c6f9a6e9212b --- /dev/null +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/types/ConnectorType.java @@ -0,0 +1,26 @@ +/* +* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. licenses this file to you under the Apache License, +* Version 2.0 (the "License"); you may not use this file except +* in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package org.ballerinalang.model.types; + +/** + * {@code ConnectorType} represents the type of a connector in Ballerina. + * + * @since 0.94 + */ +public interface ConnectorType extends ReferenceType { +} diff --git a/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/types/ConstrainedType.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/types/ConstrainedType.java index 8cd4c1a858d3..394001fbf8cc 100644 --- a/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/types/ConstrainedType.java +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/types/ConstrainedType.java @@ -20,7 +20,7 @@ /** * @since 0.94 */ -public interface ConstrainedType { +public interface ConstrainedType extends ReferenceType { Type getConstraint(); } diff --git a/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/types/FiniteType.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/types/FiniteType.java new file mode 100644 index 000000000000..165b6832a561 --- /dev/null +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/types/FiniteType.java @@ -0,0 +1,32 @@ +/* +* Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. licenses this file to you under the Apache License, +* Version 2.0 (the "License"); you may not use this file except +* in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package org.ballerinalang.model.types; + +import org.ballerinalang.model.tree.expressions.ExpressionNode; + +import java.util.Set; + +/** + * {@code FiniteType} represents the finite type interface. + * + */ +public interface FiniteType extends ReferenceType { + + Set getValueSpace(); + +} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/MayBeDependentType.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/types/NilType.java similarity index 58% rename from bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/MayBeDependentType.java rename to compiler/ballerina-lang/src/main/java/org/ballerinalang/model/types/NilType.java index 2a68601ce4bc..6f9667927726 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/MayBeDependentType.java +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/types/NilType.java @@ -1,7 +1,7 @@ /* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). + * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * - * WSO2 LLC. licenses this file to you under the Apache License, + * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at @@ -14,21 +14,14 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. - * */ - -package io.ballerina.runtime.internal.types; - -import java.util.Set; +package org.ballerinalang.model.types; /** - * Represents a type that may be dependently typed. + * {@code NilType} represents the singleton type returns by functions with no declared value. + * The value of the {@code NilType} is written as '()' * - * @since 2201.11.0 + * @since 0.970.0 */ -public interface MayBeDependentType { - - boolean isDependentlyTyped(); - - boolean isDependentlyTyped(Set visited); +public interface NilType extends ReferenceType { } diff --git a/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/types/NullType.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/types/NullType.java new file mode 100644 index 000000000000..144a5036682d --- /dev/null +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/types/NullType.java @@ -0,0 +1,26 @@ +/* +* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. licenses this file to you under the Apache License, +* Version 2.0 (the "License"); you may not use this file except +* in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package org.ballerinalang.model.types; + +/** + * {@code NullType} represents the type of the expression 'null'. + * + * @since 0.94 + */ +public interface NullType extends ReferenceType { +} diff --git a/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/types/ReferenceType.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/types/ReferenceType.java new file mode 100644 index 000000000000..ebe029307e5a --- /dev/null +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/types/ReferenceType.java @@ -0,0 +1,27 @@ +/* +* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. licenses this file to you under the Apache License, +* Version 2.0 (the "License"); you may not use this file except +* in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package org.ballerinalang.model.types; + +/** + * {@code ReferenceType} represents a reference type in Ballerina. + * These includes structs, connectors, array types, xml, json etc. + * + * @since 0.94 + */ +public interface ReferenceType extends Type { +} diff --git a/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java index 6f1037b9bb94..63b9648cd3bd 100644 --- a/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java @@ -778,7 +778,7 @@ public enum DiagnosticErrorCode implements DiagnosticCode { UNDEFINED_RESOURCE("BCE4028", "undefined.resource"), UNDEFINED_RESOURCE_METHOD("BCE4029", "undefined.resource.method"), AMBIGUOUS_RESOURCE_ACCESS_NOT_YET_SUPPORTED("BCE4030", "ambiguous.resource.access.not.yet.supported"), - UNSUPPORTED_COMPUTED_RESOURCE_ACCESS_PATH_SEGMENT_TYPE("BCE4031", + UNSUPPORTED_COMPUTED_RESOURCE_ACCESS_PATH_SEGMENT_TYPE("BCE4031", "unsupported.computed.resource.access.path.segment.type"), UNSUPPORTED_RESOURCE_ACCESS_REST_SEGMENT_TYPE("BCE4032", "unsupported.resource.access.rest.segment.type"), INVALID_RESOURCE_METHOD_RETURN_TYPE("BCE4033", "invalid.resource.method.return.type"), diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/BIRPackageSymbolEnter.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/BIRPackageSymbolEnter.java index 044548c34fde..97e943698e19 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/BIRPackageSymbolEnter.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/BIRPackageSymbolEnter.java @@ -18,40 +18,8 @@ package org.wso2.ballerinalang.compiler; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.Atom; -import io.ballerina.types.AtomicType; -import io.ballerina.types.BasicTypeBitSet; -import io.ballerina.types.Bdd; -import io.ballerina.types.CellAtomicType; -import io.ballerina.types.CellSemType; -import io.ballerina.types.ComplexSemType; -import io.ballerina.types.EnumerableCharString; -import io.ballerina.types.EnumerableDecimal; -import io.ballerina.types.EnumerableFloat; -import io.ballerina.types.EnumerableString; -import io.ballerina.types.Env; -import io.ballerina.types.FixedLengthArray; -import io.ballerina.types.FunctionAtomicType; -import io.ballerina.types.ListAtomicType; -import io.ballerina.types.MappingAtomicType; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.PredefinedTypeEnv; -import io.ballerina.types.ProperSubtypeData; -import io.ballerina.types.RecAtom; -import io.ballerina.types.SemType; -import io.ballerina.types.TypeAtom; -import io.ballerina.types.subtypedata.BddAllOrNothing; -import io.ballerina.types.subtypedata.BddNode; -import io.ballerina.types.subtypedata.BooleanSubtype; -import io.ballerina.types.subtypedata.CharStringSubtype; -import io.ballerina.types.subtypedata.DecimalSubtype; -import io.ballerina.types.subtypedata.FloatSubtype; -import io.ballerina.types.subtypedata.IntSubtype; -import io.ballerina.types.subtypedata.NonCharStringSubtype; -import io.ballerina.types.subtypedata.Range; -import io.ballerina.types.subtypedata.StringSubtype; -import io.ballerina.types.subtypedata.XmlSubtype; import org.ballerinalang.compiler.BLangCompilerException; +import org.ballerinalang.model.TreeBuilder; import org.ballerinalang.model.elements.AttachPoint; import org.ballerinalang.model.elements.Flag; import org.ballerinalang.model.elements.MarkdownDocAttachment; @@ -59,6 +27,7 @@ import org.ballerinalang.model.symbols.Annotatable; import org.ballerinalang.model.symbols.SymbolKind; import org.ballerinalang.model.symbols.SymbolOrigin; +import org.ballerinalang.model.tree.NodeKind; import org.ballerinalang.model.types.ConstrainedType; import org.wso2.ballerinalang.compiler.bir.writer.CPEntry; import org.wso2.ballerinalang.compiler.bir.writer.CPEntry.ByteCPEntry; @@ -96,7 +65,6 @@ import org.wso2.ballerinalang.compiler.semantics.model.symbols.SymTag; import org.wso2.ballerinalang.compiler.semantics.model.symbols.Symbols; import org.wso2.ballerinalang.compiler.semantics.model.types.BAnnotationType; -import org.wso2.ballerinalang.compiler.semantics.model.types.BAnyType; import org.wso2.ballerinalang.compiler.semantics.model.types.BArrayType; import org.wso2.ballerinalang.compiler.semantics.model.types.BErrorType; import org.wso2.ballerinalang.compiler.semantics.model.types.BField; @@ -118,8 +86,11 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BTypedescType; import org.wso2.ballerinalang.compiler.semantics.model.types.BUnionType; import org.wso2.ballerinalang.compiler.semantics.model.types.BXMLType; -import org.wso2.ballerinalang.compiler.semantics.model.types.SemNamedType; +import org.wso2.ballerinalang.compiler.semantics.model.types.TypeFlags; import org.wso2.ballerinalang.compiler.tree.BLangConstantValue; +import org.wso2.ballerinalang.compiler.tree.BLangPackage; +import org.wso2.ballerinalang.compiler.tree.BLangTypeDefinition; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral; import org.wso2.ballerinalang.compiler.util.BArrayState; import org.wso2.ballerinalang.compiler.util.CompilerContext; import org.wso2.ballerinalang.compiler.util.ImmutableTypeCloner; @@ -134,8 +105,6 @@ import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; -import java.math.BigDecimal; -import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; @@ -147,14 +116,13 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.Set; import java.util.function.Consumer; -import static io.ballerina.types.PredefinedType.BDD_REC_ATOM_READONLY; import static org.ballerinalang.model.symbols.SymbolOrigin.COMPILED_SOURCE; import static org.ballerinalang.model.symbols.SymbolOrigin.VIRTUAL; import static org.ballerinalang.model.symbols.SymbolOrigin.toOrigin; +import static org.wso2.ballerinalang.compiler.parser.BLangAnonymousModelHelper.ANON_PREFIX; import static org.wso2.ballerinalang.compiler.semantics.model.Scope.NOT_FOUND_ENTRY; import static org.wso2.ballerinalang.util.LambdaExceptionUtils.rethrow; @@ -164,7 +132,6 @@ * @since 0.995.0 */ public class BIRPackageSymbolEnter { - private final PackageCache packageCache; private final SymbolResolver symbolResolver; private final SymbolTable symTable; @@ -177,8 +144,6 @@ public class BIRPackageSymbolEnter { private List structureTypes; // TODO find a better way private BStructureTypeSymbol currentStructure = null; private final LinkedList compositeStack = new LinkedList<>(); - private final Env typeEnv; - private AtomOffsets offsets; private static final CompilerContext.Key COMPILED_PACKAGE_SYMBOL_ENTER_KEY = new CompilerContext.Key<>(); @@ -203,8 +168,6 @@ private BIRPackageSymbolEnter(CompilerContext context) { this.names = Names.getInstance(context); this.typeParamAnalyzer = TypeParamAnalyzer.getInstance(context); this.types = Types.getInstance(context); - this.typeEnv = symTable.typeEnv(); - this.offsets = null; } public BPackageSymbol definePackage(PackageID packageId, byte[] packageBinaryContent) { @@ -268,7 +231,6 @@ private BPackageSymbol definePackage(DataInputStream dataInStream, int pkgCpInde PackageID pkgId = createPackageID(orgName, pkgName, moduleName, pkgVersion); this.env.pkgSymbol = Symbols.createPackageSymbol(pkgId, this.symTable, COMPILED_SOURCE); - this.offsets = AtomOffsets.from(typeEnv); // TODO Validate this pkdID with the requestedPackageID available in the env. @@ -299,7 +261,6 @@ private BPackageSymbol definePackage(DataInputStream dataInStream, int pkgCpInde populateReferencedFunctions(); this.typeReader = null; - this.offsets = null; return this.env.pkgSymbol; } @@ -645,7 +606,7 @@ private void skipPosition(DataInputStream dataInStream) throws IOException { } private void setInvokableTypeSymbol(BInvokableType invokableType) { - if (Symbols.isFlagOn(invokableType.getFlags(), Flags.ANY_FUNCTION)) { + if (Symbols.isFlagOn(invokableType.flags, Flags.ANY_FUNCTION)) { return; } BInvokableTypeSymbol tsymbol = (BInvokableTypeSymbol) invokableType.tsymbol; @@ -971,7 +932,7 @@ private void setParamSymbols(BInvokableSymbol invokableSymbol, DataInputStream d defineAnnotAttachmentSymbols(dataInStream, restParam); } - if (Symbols.isFlagOn(invokableSymbol.retType.getFlags(), Flags.PARAMETERIZED)) { + if (Symbols.isFlagOn(invokableSymbol.retType.flags, Flags.PARAMETERIZED)) { Map paramsMap = new HashMap<>(); for (BVarSymbol param : invokableSymbol.params) { if (paramsMap.put(param.getName(), param) != null) { @@ -1073,7 +1034,7 @@ private void populateParameterizedType(BType type, final Map p break; case TypeTags.INVOKABLE: BInvokableType invokableType = (BInvokableType) type; - if (Symbols.isFlagOn(invokableType.getFlags(), Flags.ANY_FUNCTION)) { + if (Symbols.isFlagOn(invokableType.flags, Flags.ANY_FUNCTION)) { break; } for (BType t : invokableType.paramTypes) { @@ -1171,7 +1132,6 @@ private static class UnresolvedType { private class BIRTypeReader { private final DataInputStream inputStream; - private final PredefinedTypeEnv predefinedTypeEnv = PredefinedTypeEnv.getInstance(); public BIRTypeReader(DataInputStream inputStream) { this.inputStream = inputStream; @@ -1260,6 +1220,8 @@ public BType readType(int cpI) throws IOException { Name name = Names.fromString(getStringCPEntryValue(inputStream)); long flags = inputStream.readLong(); + // Read the type flags to identify if type reference types are nullable. + int typeFlags = inputStream.readInt(); switch (tag) { case TypeTags.INT: return typeParamAnalyzer.getNominalType(symTable.intType, name, flags); @@ -1280,7 +1242,7 @@ public BType readType(int cpI) throws IOException { BType constraintType = readTypeFromCp(); BXMLType mutableXmlType = new BXMLType(constraintType, symTable.xmlType.tsymbol); if (Symbols.isFlagOn(flags, Flags.PARAMETERIZED)) { - mutableXmlType.addFlags(Flags.PARAMETERIZED); + mutableXmlType.flags |= Flags.PARAMETERIZED; } return isImmutable(flags) ? getEffectiveImmutableType(mutableXmlType) : mutableXmlType; case TypeTags.NIL: @@ -1308,7 +1270,7 @@ public BType readType(int cpI) throws IOException { COMPILED_SOURCE); recordSymbol.scope = new Scope(recordSymbol); - BRecordType recordType = new BRecordType(symTable.typeEnv(), recordSymbol, flags); + BRecordType recordType = new BRecordType(recordSymbol, flags); recordSymbol.type = recordType; compositeStack.push(recordType); @@ -1357,11 +1319,11 @@ public BType readType(int cpI) throws IOException { } SymbolEnv pkgEnv = symTable.pkgEnvMap.get(packageCache.getSymbol(pkgId)); - return lookupSymbolInMainSpace(pkgEnv, Names.fromString(recordName)); + return getType(recordType, pkgEnv, Names.fromString(recordName)); case TypeTags.TYPEDESC: - BTypedescType typedescType = new BTypedescType(symTable.typeEnv(), null, symTable.typeDesc.tsymbol); + BTypedescType typedescType = new BTypedescType(null, symTable.typeDesc.tsymbol); typedescType.constraint = readTypeFromCp(); - typedescType.setFlags(flags); + typedescType.flags = flags; return typedescType; case TypeTags.TYPEREFDESC: int pkgIndex = inputStream.readInt(); @@ -1375,7 +1337,9 @@ public BType readType(int cpI) throws IOException { Names.fromString(typeDefName), pkg, null, pkgSymbol, symTable.builtinPos, COMPILED_SOURCE); - BTypeReferenceType typeReferenceType = new BTypeReferenceType(null, typeSymbol, flags); + boolean nullable = (typeFlags & TypeFlags.NILABLE) == TypeFlags.NILABLE; + + BTypeReferenceType typeReferenceType = new BTypeReferenceType(null, typeSymbol, flags, nullable); addShapeCP(typeReferenceType, cpI); compositeStack.push(typeReferenceType); typeReferenceType.referredType = readTypeFromCp(); @@ -1386,19 +1350,17 @@ public BType readType(int cpI) throws IOException { case TypeTags.PARAMETERIZED_TYPE: BParameterizedType type = new BParameterizedType(null, null, null, name, -1); type.paramValueType = readTypeFromCp(); - type.setFlags(flags); + type.flags = flags; type.paramIndex = inputStream.readInt(); return type; case TypeTags.STREAM: - BStreamType bStreamType = new BStreamType(symTable.typeEnv(), TypeTags.STREAM, null, null, - symTable.streamType.tsymbol); + BStreamType bStreamType = new BStreamType(TypeTags.STREAM, null, null, symTable.streamType.tsymbol); bStreamType.constraint = readTypeFromCp(); bStreamType.completionType = readTypeFromCp(); - bStreamType.setFlags(flags); + bStreamType.flags = flags; return bStreamType; case TypeTags.TABLE: - BTableType bTableType = new BTableType(symTable.typeEnv(), null, - symTable.tableType.tsymbol, flags); + BTableType bTableType = new BTableType(TypeTags.TABLE, null, symTable.tableType.tsymbol, flags); bTableType.constraint = readTypeFromCp(); boolean hasFieldNameList = inputStream.readByte() == 1; @@ -1424,17 +1386,16 @@ public BType readType(int cpI) throws IOException { } return bTableType; case TypeTags.MAP: - BMapType bMapType = new BMapType(symTable.typeEnv(), TypeTags.MAP, null, symTable.mapType.tsymbol, - flags); + BMapType bMapType = new BMapType(TypeTags.MAP, null, symTable.mapType.tsymbol, flags); bMapType.constraint = readTypeFromCp(); return bMapType; case TypeTags.INVOKABLE: - BInvokableType bInvokableType = new BInvokableType(typeEnv, List.of(), null, null, null); + BInvokableType bInvokableType = new BInvokableType(null, null, null, null); bInvokableType.tsymbol = Symbols.createInvokableTypeSymbol(SymTag.FUNCTION_TYPE, flags, env.pkgSymbol.pkgID, null, env.pkgSymbol.owner, symTable.builtinPos, COMPILED_SOURCE); - bInvokableType.setFlags(flags); + bInvokableType.flags = flags; if (inputStream.readBoolean()) { // Return if an any function return bInvokableType; @@ -1452,7 +1413,11 @@ public BType readType(int cpI) throws IOException { return setTSymbolForInvokableType(bInvokableType, bInvokableType.retType); // All the above types are branded types case TypeTags.ANY: - return isImmutable(flags) ? BAnyType.newImmutableBAnyType() : new BAnyType(name, flags); + BType anyNominalType = typeParamAnalyzer.getNominalType(symTable.anyType, name, flags); + return isImmutable(flags) ? getEffectiveImmutableType(anyNominalType, + symTable.anyType.tsymbol.pkgID, + symTable.anyType.tsymbol.owner) : + anyNominalType; case TypeTags.HANDLE: return symTable.handleType; case TypeTags.READONLY: @@ -1468,8 +1433,7 @@ public BType readType(int cpI) throws IOException { Names.EMPTY, env.pkgSymbol.pkgID, null, env.pkgSymbol.owner, symTable.builtinPos, COMPILED_SOURCE); - BArrayType bArrayType = - new BArrayType(symTable.typeEnv(), null, arrayTypeSymbol, size, BArrayState.valueOf(state), + BArrayType bArrayType = new BArrayType(null, arrayTypeSymbol, size, BArrayState.valueOf(state), flags); bArrayType.eType = readTypeFromCp(); return bArrayType; @@ -1489,14 +1453,13 @@ public BType readType(int cpI) throws IOException { null, env.pkgSymbol, symTable.builtinPos, COMPILED_SOURCE); int unionMemberCount = inputStream.readInt(); - BUnionType unionType = - BUnionType.create(types.typeEnv(), unionTypeSymbol, new LinkedHashSet<>(unionMemberCount)); + BUnionType unionType = BUnionType.create(unionTypeSymbol, new LinkedHashSet<>(unionMemberCount)); unionType.name = unionName; addShapeCP(unionType, cpI); compositeStack.push(unionType); - unionType.setFlags(flags); + unionType.flags = flags; unionType.isCyclic = isCyclic; for (int i = 0; i < unionMemberCount; i++) { unionType.add(readTypeFromCp()); @@ -1523,7 +1486,7 @@ public BType readType(int cpI) throws IOException { } else { pkgEnv = symTable.pkgEnvMap.get(packageCache.getSymbol(unionsPkgId)); if (pkgEnv != null) { - BType existingUnionType = lookupSymbolInMainSpace(pkgEnv, unionName); + BType existingUnionType = getType(unionType, pkgEnv, unionName); if (existingUnionType != symTable.noType) { return existingUnionType; } @@ -1575,13 +1538,13 @@ public BType readType(int cpI) throws IOException { errorSymbol = new BErrorTypeSymbol(SymTag.ERROR, Flags.PUBLIC, Names.EMPTY, env.pkgSymbol.pkgID, null, env.pkgSymbol, symTable.builtinPos, COMPILED_SOURCE); } - BErrorType errorType = new BErrorType(symTable.typeEnv(), errorSymbol); + BErrorType errorType = new BErrorType(errorSymbol); addShapeCP(errorType, cpI); compositeStack.push(errorType); String errorName = getStringCPEntryValue(inputStream); BType detailsType = readTypeFromCp(); errorType.detailType = detailsType; - errorType.setFlags(flags); + errorType.flags = flags; errorSymbol.type = errorType; errorSymbol.pkgID = pkgId; errorSymbol.originalName = errorSymbol.name = Names.fromString(errorName); @@ -1620,8 +1583,8 @@ public BType readType(int cpI) throws IOException { tupleMembers.add(new BTupleMember(memberType, varSymbol)); } - BTupleType bTupleType = new BTupleType(symTable.typeEnv(), tupleTypeSymbol, tupleMembers); - bTupleType.setFlags(flags); + BTupleType bTupleType = new BTupleType(tupleTypeSymbol, tupleMembers); + bTupleType.flags = flags; if (inputStream.readBoolean()) { bTupleType.restType = readTypeFromCp(); @@ -1629,9 +1592,9 @@ public BType readType(int cpI) throws IOException { return bTupleType; case TypeTags.FUTURE: - BFutureType bFutureType = new BFutureType(symTable.typeEnv(), null, symTable.futureType.tsymbol); + BFutureType bFutureType = new BFutureType(TypeTags.FUTURE, null, symTable.futureType.tsymbol); bFutureType.constraint = readTypeFromCp(); - bFutureType.setFlags(flags); + bFutureType.flags = flags; return bFutureType; case TypeTags.FINITE: String finiteTypeName = getStringCPEntryValue(inputStream); @@ -1641,14 +1604,13 @@ public BType readType(int cpI) throws IOException { null, env.pkgSymbol, symTable.builtinPos, COMPILED_SOURCE); symbol.scope = new Scope(symbol); - int valueSpaceLength = inputStream.readInt(); - SemNamedType[] valueSpace = new SemNamedType[valueSpaceLength]; - for (int i = 0; i < valueSpaceLength; i++) { - valueSpace[i] = readSemNamedType(); - } - BFiniteType finiteType = new BFiniteType(symbol, valueSpace); - finiteType.setFlags(flags); + BFiniteType finiteType = new BFiniteType(symbol); + finiteType.flags = flags; symbol.type = finiteType; + int valueSpaceSize = inputStream.readInt(); + for (int i = 0; i < valueSpaceSize; i++) { + defineValueSpace(inputStream, finiteType, this); + } return finiteType; case TypeTags.OBJECT: pkgCpIndex = inputStream.readInt(); @@ -1671,8 +1633,8 @@ public BType readType(int cpI) throws IOException { objectSymbol.scope = new Scope(objectSymbol); BObjectType objectType; // Below is a temporary fix, need to fix this properly by using the type tag - objectType = new BObjectType(symTable.typeEnv(), objectSymbol); - objectType.setFlags(flags); + objectType = new BObjectType(objectSymbol); + objectType.flags = flags; objectSymbol.type = objectType; addShapeCP(objectType, cpI); compositeStack.push(objectType); @@ -1725,7 +1687,7 @@ public BType readType(int cpI) throws IOException { } pkgEnv = symTable.pkgEnvMap.get(packageCache.getSymbol(pkgId)); - return lookupSymbolInMainSpace(pkgEnv, Names.fromString(objName)); + return getType(objectType, pkgEnv, Names.fromString(objName)); case TypeTags.BYTE_ARRAY: // TODO fix break; @@ -1852,7 +1814,7 @@ private void populateIntersectionTypeReferencedFunctions(DataInputStream inputSt setInvokableTypeSymbol(attachedFuncType); - if (!Symbols.isFlagOn(attachedFuncType.getFlags(), Flags.ANY_FUNCTION)) { + if (!Symbols.isFlagOn(attachedFuncType.flags, Flags.ANY_FUNCTION)) { BInvokableTypeSymbol tsymbol = (BInvokableTypeSymbol) attachedFuncType.tsymbol; attachedFuncSymbol.params = tsymbol.params; attachedFuncSymbol.restParam = tsymbol.restParam; @@ -1863,294 +1825,45 @@ private void populateIntersectionTypeReferencedFunctions(DataInputStream inputSt objectSymbol.attachedFuncs.add(attachedFunction); objectSymbol.scope.define(funcName, attachedFuncSymbol); } + } - private Optional readNullableString() throws IOException { - boolean hasNonNullString = inputStream.readBoolean(); - if (hasNonNullString) { - return Optional.of(getStringCPEntryValue(inputStream)); - } else { - return Optional.empty(); - } - } - - private SemNamedType readSemNamedType() throws IOException { - SemType semType = readSemType(); - Optional optName = readNullableString(); - return new SemNamedType(semType, optName); - } - - // --------------------------------------- Read SemType ---------------------------------------------- - - private SemType readSemType() throws IOException { - if (!inputStream.readBoolean()) { - return null; - } - - if (inputStream.readBoolean()) { - int bitset = inputStream.readInt(); - return BasicTypeBitSet.from(bitset); - } + private BType getType(BType readShape, SymbolEnv pkgEnv, Name name) { + BType type = symbolResolver.lookupSymbolInMainSpace(pkgEnv, name).type; - int all = inputStream.readInt(); - int some = inputStream.readInt(); - byte subtypeDataListLength = inputStream.readByte(); - ProperSubtypeData[] subtypeList = new ProperSubtypeData[subtypeDataListLength]; - for (int i = 0; i < subtypeDataListLength; i++) { - subtypeList[i] = readProperSubtypeData(); - } - return createSemType(all, some, subtypeList); + if (type != symTable.noType && (!name.value.contains(ANON_PREFIX) || types.isSameBIRShape(readShape, type))) { + return type; } - private ProperSubtypeData readProperSubtypeData() throws IOException { - switch (inputStream.readByte()) { - case 1: - return readBdd(); - case 2: - return readIntSubtype(); - case 3: - return BooleanSubtype.from(inputStream.readBoolean()); - case 4: - return readFloatSubtype(); - case 5: - return readDecimalSubType(); - case 6: - return readStringSubtype(); - case 7: - return readXmlSubtype(); - default: - throw new IllegalStateException("Unexpected ProperSubtypeData kind"); - } - } + if (pkgEnv.node != null) { + for (BLangTypeDefinition typeDefinition : ((BLangPackage) pkgEnv.node).typeDefinitions) { + BSymbol symbol = typeDefinition.symbol; - private Bdd readBdd() throws IOException { - boolean isBddNode = inputStream.readBoolean(); - if (isBddNode) { - return readBddNode(); - } else { - boolean isAll = inputStream.readBoolean(); - return isAll ? BddAllOrNothing.bddAll() : BddAllOrNothing.bddNothing(); - } - } - - enum AtomKind { - REC, - INLINED, - TYPE - } - - private AtomKind readAtomKind() throws IOException { - return switch (inputStream.readByte()) { - case 0 -> AtomKind.REC; - case 1 -> AtomKind.INLINED; - case 2 -> AtomKind.TYPE; - default -> throw new IllegalStateException("Unexpected AtomKind kind"); - }; - } + String typeDefName = typeDefinition.name.value; + if (typeDefName.contains(ANON_PREFIX)) { + BType anonType = symbol.type; - private BddNode readBddNode() throws IOException { - AtomKind atomKind = readAtomKind(); - Atom atom = switch (atomKind) { - case REC -> readRecAtom(); - case INLINED -> readInlinedAtom(); - case TYPE -> { - TypeAtom typeAtom = readTypeAtom(); - typeEnv.deserializeTypeAtom(typeAtom); - yield typeAtom; + if (types.isSameBIRShape(readShape, anonType)) { + return anonType; + } + } else if (typeDefName.equals(name.value)) { + return symbol.type; } - }; - - Bdd left = readBdd(); - Bdd middle = readBdd(); - Bdd right = readBdd(); - return BddNode.create(atom, left, middle, right); - } - - private Atom readInlinedAtom() throws IOException { - int recAtomIndex = inputStream.readInt(); - assert recAtomIndex != BDD_REC_ATOM_READONLY; - AtomicType atomicType = readTypeAtom().atomicType(); - Atom.Kind kind; - if (atomicType instanceof MappingAtomicType) { - recAtomIndex += offsets.mappingOffset(); - kind = Atom.Kind.MAPPING_ATOM; - } else if (atomicType instanceof ListAtomicType) { - recAtomIndex += offsets.listOffset(); - kind = Atom.Kind.LIST_ATOM; - } else if (atomicType instanceof FunctionAtomicType) { - recAtomIndex += offsets.functionOffset(); - kind = Atom.Kind.FUNCTION_ATOM; - } else { - throw new IllegalStateException("Unexpected inlined atomicType kind"); - } - typeEnv.insertRecAtomAtIndex(recAtomIndex, atomicType); - RecAtom recAtom = RecAtom.createRecAtom(recAtomIndex); - recAtom.setKind(kind); - return recAtom; - } - - private TypeAtom readTypeAtom() throws IOException { - int index = inputStream.readInt() + offsets.atomOffset(); - AtomicType atomicType = switch (inputStream.readByte()) { - case 1 -> readMappingAtomicType(); - case 2 -> readListAtomicType(); - case 3 -> readFunctionAtomicType(); - case 4 -> readCellAtomicType(); - default -> throw new IllegalStateException("Unexpected atomicType kind"); - }; - return TypeAtom.createTypeAtom(index, atomicType); - } - - private RecAtom readRecAtom() throws IOException { - int index = inputStream.readInt(); - Optional predefinedRecAtom = predefinedTypeEnv.getPredefinedRecAtom(index); - if (predefinedRecAtom.isPresent()) { - return predefinedRecAtom.get(); - } - int kindOrdinal = inputStream.readInt(); - Atom.Kind kind = Atom.Kind.values()[kindOrdinal]; - int offset = switch (kind) { - case LIST_ATOM -> offsets.listOffset(); - case FUNCTION_ATOM -> offsets.functionOffset(); - case MAPPING_ATOM -> offsets.mappingOffset(); - case DISTINCT_ATOM -> (-offsets.distinctOffset()); - case XML_ATOM -> 0; - case CELL_ATOM -> throw new IllegalStateException("Cell atom cannot be recursive"); - }; - index += offset; - RecAtom recAtom = RecAtom.createRecAtom(index); - recAtom.setKind(kind); - return recAtom; - - } - - private CellAtomicType readCellAtomicType() throws IOException { - SemType ty = readSemType(); - byte ordinal = inputStream.readByte(); - CellAtomicType.CellMutability mut = CellAtomicType.CellMutability.values()[ordinal]; - return CellAtomicType.from(ty, mut); - } - - private MappingAtomicType readMappingAtomicType() throws IOException { - int namesLength = inputStream.readInt(); - String[] names = new String[namesLength]; - for (int i = 0; i < namesLength; i++) { - names[i] = getStringCPEntryValue(inputStream); - } - - int typesLength = inputStream.readInt(); - CellSemType[] types = new CellSemType[typesLength]; - for (int i = 0; i < typesLength; i++) { - types[i] = (CellSemType) readSemType(); - } - - CellSemType rest = (CellSemType) readSemType(); - return MappingAtomicType.from(names, types, rest); - } - - private ListAtomicType readListAtomicType() throws IOException { - int initialLength = inputStream.readInt(); - List initial = new ArrayList<>(initialLength); - for (int i = 0; i < initialLength; i++) { - initial.add((CellSemType) readSemType()); - } - - int fixedLength = inputStream.readInt(); - FixedLengthArray members = FixedLengthArray.from(initial, fixedLength); - - CellSemType rest = (CellSemType) readSemType(); - return ListAtomicType.from(members, rest); - } - - private static ComplexSemType createSemType(int all, int some, ProperSubtypeData[] subtypeList) { - if (some == PredefinedType.CELL.bitset && all == 0) { - return CellSemType.from(subtypeList); } - return ComplexSemType.createComplexSemType(all, some, subtypeList); - } - - private FunctionAtomicType readFunctionAtomicType() throws IOException { - SemType paramType = readSemType(); - SemType retType = readSemType(); - SemType qualifiers = readSemType(); - boolean isGeneric = inputStream.readBoolean(); - return isGeneric ? FunctionAtomicType.genericFrom(paramType, retType, qualifiers) : - FunctionAtomicType.from(paramType, retType, qualifiers); - } - - private IntSubtype readIntSubtype() throws IOException { - int rangesLength = inputStream.readInt(); - Range[] ranges = new Range[rangesLength]; - for (int i = 0; i < rangesLength; i++) { - long min = inputStream.readLong(); - long max = inputStream.readLong(); - ranges[i] = new Range(min, max); - - } - return IntSubtype.createIntSubtype(ranges); - } - - private FloatSubtype readFloatSubtype() throws IOException { - boolean allowed = inputStream.readBoolean(); - int valuesLength = inputStream.readInt(); - EnumerableFloat[] values = new EnumerableFloat[valuesLength]; - for (int i = 0; i < valuesLength; i++) { - values[i] = EnumerableFloat.from(inputStream.readDouble()); - } - - return (FloatSubtype) FloatSubtype.createFloatSubtype(allowed, values); - } - - private DecimalSubtype readDecimalSubType() throws IOException { - boolean allowed = inputStream.readBoolean(); - int valuesLength = inputStream.readInt(); - EnumerableDecimal[] values = new EnumerableDecimal[valuesLength]; - for (int i = 0; i < valuesLength; i++) { - int scale = inputStream.readInt(); - int byteLen = inputStream.readInt(); - byte[] unscaleValueBytes = inputStream.readNBytes(byteLen); - BigDecimal bigDecimal = new BigDecimal(new BigInteger(unscaleValueBytes), scale); - values[i] = EnumerableDecimal.from(bigDecimal); - } - return (DecimalSubtype) DecimalSubtype.createDecimalSubtype(allowed, values); - } + } else { + for (Map.Entry value : pkgEnv.scope.entries.entrySet()) { + BSymbol symbol = value.getValue().symbol; - private StringSubtype readStringSubtype() throws IOException { - CharStringSubtype charStringSubtype = readCharStringSubtype(); - NonCharStringSubtype nonCharStringSubtype = readNonCharStringSubtype(); - return StringSubtype.from(charStringSubtype, nonCharStringSubtype); - } + if (value.getKey().value.contains(ANON_PREFIX)) { + BType anonType = symbol.type; - private CharStringSubtype readCharStringSubtype() throws IOException { - boolean allowed = inputStream.readBoolean(); - int valuesLength = inputStream.readInt(); - EnumerableCharString[] values = new EnumerableCharString[valuesLength]; - for (int i = 0; i < valuesLength; i++) { - values[i] = EnumerableCharString.from(getStringCPEntryValue(inputStream)); - } - return CharStringSubtype.from(allowed, values); - } - - private NonCharStringSubtype readNonCharStringSubtype() throws IOException { - boolean allowed = inputStream.readBoolean(); - int valuesLength = inputStream.readInt(); - EnumerableString[] values = new EnumerableString[valuesLength]; - for (int i = 0; i < valuesLength; i++) { - values[i] = EnumerableString.from(getStringCPEntryValue(inputStream)); + if (types.isSameBIRShape(readShape, anonType)) { + return anonType; + } + } } - return NonCharStringSubtype.from(allowed, values); } - private XmlSubtype readXmlSubtype() throws IOException { - int primitives = inputStream.readInt(); - Bdd sequence = readBdd(); - return XmlSubtype.from(primitives, sequence); - } - - // --------------------------------------- End of SemType ----------------------------------------------- - } - - private BType lookupSymbolInMainSpace(SymbolEnv pkgEnv, Name name) { - return symbolResolver.lookupSymbolInMainSpace(pkgEnv, name).type; + return type; } private byte[] readDocBytes(DataInputStream inputStream) throws IOException { @@ -2173,6 +1886,54 @@ private PackageID getPackageId(int pkgCPIndex) { Names.fromString(moduleName), Names.fromString(version), null); } + private void defineValueSpace(DataInputStream dataInStream, BFiniteType finiteType, BIRTypeReader typeReader) + throws IOException { + BType valueType = typeReader.readTypeFromCp(); + + dataInStream.readInt(); // read and ignore value length + + BLangLiteral litExpr = createLiteralBasedOnType(valueType); + switch (valueType.tag) { + case TypeTags.INT: + int integerCpIndex = dataInStream.readInt(); + IntegerCPEntry integerCPEntry = (IntegerCPEntry) this.env.constantPool[integerCpIndex]; + litExpr.value = integerCPEntry.value; + break; + case TypeTags.BYTE: + int byteCpIndex = dataInStream.readInt(); + ByteCPEntry byteCPEntry = (ByteCPEntry) this.env.constantPool[byteCpIndex]; + litExpr.value = byteCPEntry.value; + break; + case TypeTags.FLOAT: + int floatCpIndex = dataInStream.readInt(); + FloatCPEntry floatCPEntry = (FloatCPEntry) this.env.constantPool[floatCpIndex]; + litExpr.value = Double.toString(floatCPEntry.value); + break; + case TypeTags.STRING: + case TypeTags.DECIMAL: + litExpr.value = getStringCPEntryValue(dataInStream); + break; + case TypeTags.BOOLEAN: + litExpr.value = dataInStream.readBoolean(); + break; + case TypeTags.NIL: + litExpr.originalValue = "null"; + break; + default: + throw new UnsupportedOperationException("finite type value is not supported for type: " + valueType); + } + + litExpr.setBType(valueType); + + finiteType.addValue(litExpr); + } + + private BLangLiteral createLiteralBasedOnType(BType valueType) { + NodeKind nodeKind = valueType.tag <= TypeTags.DECIMAL ? NodeKind.NUMERIC_LITERAL : NodeKind.LITERAL; + return nodeKind == NodeKind.LITERAL ? (BLangLiteral) TreeBuilder.createLiteralExpression() : + (BLangLiteral) TreeBuilder.createNumericLiteralExpression(); + } + private boolean isImmutable(long flags) { return Symbols.isFlagOn(flags, Flags.READONLY); } @@ -2187,18 +1948,4 @@ private BType getEffectiveImmutableType(BType type, PackageID pkgID, BSymbol own return ImmutableTypeCloner.getEffectiveImmutableType(null, types, type, pkgID, owner, symTable, null, names); } - - private record AtomOffsets(int atomOffset, int listOffset, int functionOffset, int mappingOffset, - int distinctOffset) { - - static AtomOffsets from(Env env) { - PredefinedTypeEnv predefinedTypeEnv = PredefinedTypeEnv.getInstance(); - int recAtomOffset = predefinedTypeEnv.reservedRecAtomCount(); - return new AtomOffsets(env.atomCount(), - env.recListAtomCount() - recAtomOffset, - env.recFunctionAtomCount(), - env.recMappingAtomCount() - recAtomOffset, - env.distinctAtomCount()); - } - } } 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 21665336fe6b..b834de6199f8 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 @@ -22,7 +22,6 @@ import io.ballerina.tools.diagnostics.Location; import io.ballerina.tools.text.LinePosition; import io.ballerina.tools.text.LineRange; -import io.ballerina.types.PredefinedType; import org.ballerinalang.model.TreeBuilder; import org.ballerinalang.model.elements.Flag; import org.ballerinalang.model.elements.PackageID; @@ -60,7 +59,6 @@ import org.wso2.ballerinalang.compiler.bir.model.VarScope; import org.wso2.ballerinalang.compiler.bir.optimizer.BIROptimizer; import org.wso2.ballerinalang.compiler.diagnostic.BLangDiagnosticLocation; -import org.wso2.ballerinalang.compiler.semantics.analyzer.SemTypeHelper; import org.wso2.ballerinalang.compiler.semantics.analyzer.Types; import org.wso2.ballerinalang.compiler.semantics.model.SymbolTable; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BAnnotationSymbol; @@ -636,7 +634,7 @@ public void visit(BLangFunction astFunc) { // TODO: Return variable with NIL type should be written to BIR // Special %0 location for storing return values - BType retType = unifier.build(symTable.typeEnv(), astFunc.symbol.type.getReturnType()); + BType retType = unifier.build(astFunc.symbol.type.getReturnType()); birFunc.returnVariable = new BIRVariableDcl(astFunc.pos, retType, this.env.nextLocalVarId(names), VarScope.FUNCTION, VarKind.RETURN, null); birFunc.localVars.add(0, birFunc.returnVariable); @@ -2121,7 +2119,7 @@ public void visit(BLangXMLElementLiteral xmlElementLiteral) { BIRNonTerminator.NewXMLElement newXMLElement = new BIRNonTerminator.NewXMLElement(xmlElementLiteral.pos, toVarRef, startTagNameIndex, defaultNsURIVarRef, - Symbols.isFlagOn(xmlElementLiteral.getBType().getFlags(), + Symbols.isFlagOn(xmlElementLiteral.getBType().flags, Flags.READONLY)); setScopeAndEmit(newXMLElement); @@ -2187,7 +2185,7 @@ public void visit(BLangXMLCommentLiteral xmlCommentLiteral) { BIRNonTerminator.NewXMLComment newXMLComment = new BIRNonTerminator.NewXMLComment(xmlCommentLiteral.pos, toVarRef, xmlCommentIndex, - Symbols.isFlagOn(xmlCommentLiteral.getBType().getFlags(), + Symbols.isFlagOn(xmlCommentLiteral.getBType().flags, Flags.READONLY)); setScopeAndEmit(newXMLComment); this.env.targetOperand = toVarRef; @@ -2208,7 +2206,7 @@ public void visit(BLangXMLProcInsLiteral xmlProcInsLiteral) { BIRNonTerminator.NewXMLProcIns newXMLProcIns = new BIRNonTerminator.NewXMLProcIns(xmlProcInsLiteral.pos, toVarRef, dataIndex, targetIndex, - Symbols.isFlagOn(xmlProcInsLiteral.getBType().getFlags(), + Symbols.isFlagOn(xmlProcInsLiteral.getBType().flags, Flags.READONLY)); setScopeAndEmit(newXMLProcIns); this.env.targetOperand = toVarRef; @@ -2286,8 +2284,7 @@ public void visit(BLangTableConstructorExpr tableConstructorExpr) { BLangArrayLiteral dataLiteral = new BLangArrayLiteral(); dataLiteral.pos = tableConstructorExpr.pos; dataLiteral.setBType( - new BArrayType(symTable.typeEnv(), - ((BTableType) Types.getImpliedType(tableConstructorExpr.getBType())).constraint)); + new BArrayType(((BTableType) Types.getImpliedType(tableConstructorExpr.getBType())).constraint)); dataLiteral.exprs = new ArrayList<>(tableConstructorExpr.recordLiteralList); dataLiteral.accept(this); BIROperand dataOp = this.env.targetOperand; @@ -2726,7 +2723,7 @@ private void generateListConstructorExpr(BLangListConstructorExpr listConstructo BType referredType = Types.getImpliedType(listConstructorExprType); if (referredType.tag == TypeTags.ARRAY && ((BArrayType) referredType).state != BArrayState.OPEN) { - size = ((BArrayType) referredType).getSize(); + size = ((BArrayType) referredType).size; } else if (referredType.tag == TypeTags.TUPLE) { typedescOp = this.env.targetOperand; size = exprs.size(); @@ -2812,7 +2809,10 @@ private void generateMappingAccess(BLangIndexBasedAccess astIndexBasedAccessExpr if (astIndexBasedAccessExpr.getKind() == NodeKind.XML_ATTRIBUTE_ACCESS_EXPR) { insKind = InstructionKind.XML_ATTRIBUTE_STORE; keyRegIndex = getQNameOP(astIndexBasedAccessExpr.indexExpr, keyRegIndex); - } else if (SemTypeHelper.isSubtypeSimple(astAccessExprExprType, PredefinedType.OBJECT)) { + } else if (astAccessExprExprType.tag == TypeTags.OBJECT || + (astAccessExprExprType.tag == TypeTags.UNION && + Types.getImpliedType(((BUnionType) astAccessExprExprType).getMemberTypes().iterator() + .next()).tag == TypeTags.OBJECT)) { insKind = InstructionKind.OBJECT_STORE; } else { insKind = InstructionKind.MAP_STORE; @@ -2841,7 +2841,10 @@ private void generateMappingAccess(BLangIndexBasedAccess astIndexBasedAccessExpr keyRegIndex); this.varAssignment = false; return; - } else if (SemTypeHelper.isSubtypeSimple(astAccessExprExprType, PredefinedType.OBJECT)) { + } else if (astAccessExprExprType.tag == TypeTags.OBJECT || + (astAccessExprExprType.tag == TypeTags.UNION && + Types.getImpliedType(((BUnionType) astAccessExprExprType).getMemberTypes().iterator() + .next()).tag == TypeTags.OBJECT)) { insKind = InstructionKind.OBJECT_LOAD; } else { insKind = InstructionKind.MAP_LOAD; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmCastGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmCastGen.java index d24945da2fc8..d9a5a619fb5d 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmCastGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmCastGen.java @@ -17,7 +17,6 @@ */ package org.wso2.ballerinalang.compiler.bir.codegen; -import io.ballerina.types.Env; import org.ballerinalang.compiler.BLangCompilerException; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; @@ -634,7 +633,7 @@ private void generateJCastToBAny(MethodVisitor mv, BIRVarToJVMIndexMap indexMap, mv.visitTypeInsn(INSTANCEOF, SIMPLE_VALUE); mv.visitJumpInsn(IFNE, afterHandle); } - if (targetType.isNullable()) { + if (isNillable(targetType)) { mv.visitInsn(DUP); mv.visitJumpInsn(IFNULL, afterHandle); } @@ -655,6 +654,15 @@ private void generateJCastToBAny(MethodVisitor mv, BIRVarToJVMIndexMap indexMap, } } + private static boolean isNillable(BType targetType) { + return switch (targetType.tag) { + case TypeTags.NIL, TypeTags.NEVER, TypeTags.JSON, TypeTags.ANY, TypeTags.ANYDATA, TypeTags.READONLY -> true; + case TypeTags.UNION, TypeTags.INTERSECTION, TypeTags.FINITE -> targetType.isNullable(); + case TypeTags.TYPEREFDESC -> isNillable(JvmCodeGenUtil.getImpliedType(targetType)); + default -> false; + }; + } + private void generateCheckCastJToBJSON(MethodVisitor mv, BIRVarToJVMIndexMap indexMap, JType sourceType) { if (sourceType.jTag == JTypeTags.JREF || sourceType.jTag == JTypeTags.JARRAY) { return; @@ -1122,7 +1130,7 @@ void generateCheckCastToByte(MethodVisitor mv, BType sourceType) { public void generateCheckCastToAnyData(MethodVisitor mv, BType type) { BType sourceType = JvmCodeGenUtil.getImpliedType(type); if (sourceType.tag == TypeTags.UNION || (types.isAssignable(sourceType, symbolTable.anyType) && - !Symbols.isFlagOn(sourceType.getFlags(), Flags.READONLY))) { + !Symbols.isFlagOn(sourceType.flags, Flags.READONLY))) { checkCast(mv, symbolTable.anydataType); } else { // if value types, then ad box instruction @@ -1399,9 +1407,4 @@ private void generateCastToAny(MethodVisitor mv, BType type) { private void generateXMLToAttributesMap(MethodVisitor mv) { mv.visitMethodInsn(INVOKEVIRTUAL, XML_VALUE, "getAttributesMap", GET_ATTRAIBUTE_MAP, false); } - - public Env typeEnv() { - assert types.typeEnv() != null; - return types.typeEnv(); - } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmCodeGenUtil.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmCodeGenUtil.java index 379aef0495af..64d8c77249d9 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmCodeGenUtil.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmCodeGenUtil.java @@ -20,7 +20,6 @@ import io.ballerina.identifier.Utils; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.Env; import org.apache.commons.lang3.StringUtils; import org.ballerinalang.compiler.BLangCompilerException; import org.ballerinalang.model.elements.PackageID; @@ -231,7 +230,8 @@ public static String getFieldTypeSignature(BType bType) { case TypeTags.DECIMAL -> GET_BDECIMAL; case TypeTags.BOOLEAN -> "Z"; case TypeTags.NIL, TypeTags.NEVER, TypeTags.ANY, TypeTags.ANYDATA, TypeTags.UNION, TypeTags.JSON, - TypeTags.FINITE, TypeTags.READONLY -> GET_OBJECT; + TypeTags.FINITE, TypeTags.READONLY -> + GET_OBJECT; case TypeTags.MAP, TypeTags.RECORD -> GET_MAP_VALUE; case TypeTags.STREAM -> GET_STREAM_VALUE; case TypeTags.TABLE -> GET_TABLE_VALUE; @@ -334,19 +334,18 @@ private static String cleanupSourceFileName(String name) { return name.replace(".", FILE_NAME_PERIOD_SEPERATOR); } - public static String getMethodDesc(Env typeEnv, List paramTypes, BType retType) { - return INITIAL_METHOD_DESC + getMethodDescParams(paramTypes) + generateReturnType(retType, typeEnv); + public static String getMethodDesc(List paramTypes, BType retType) { + return INITIAL_METHOD_DESC + getMethodDescParams(paramTypes) + generateReturnType(retType); } - public static String getMethodDesc(Env typeEnv, List paramTypes, BType retType, BType attachedType) { + public static String getMethodDesc(List paramTypes, BType retType, BType attachedType) { return INITIAL_METHOD_DESC + getArgTypeSignature(attachedType) + getMethodDescParams(paramTypes) + - generateReturnType(retType, typeEnv); + generateReturnType(retType); } - public static String getMethodDesc(Env typeEnv, List paramTypes, BType retType, - String attachedTypeClassName) { + public static String getMethodDesc(List paramTypes, BType retType, String attachedTypeClassName) { return INITIAL_METHOD_DESC + "L" + attachedTypeClassName + ";" + getMethodDescParams(paramTypes) + - generateReturnType(retType, typeEnv); + generateReturnType(retType); } public static String getMethodDescParams(List paramTypes) { @@ -373,7 +372,8 @@ public static String getArgTypeSignature(BType bType) { case TypeTags.DECIMAL -> GET_BDECIMAL; case TypeTags.BOOLEAN -> "Z"; case TypeTags.NIL, TypeTags.NEVER, TypeTags.ANYDATA, TypeTags.UNION, TypeTags.JSON, TypeTags.FINITE, - TypeTags.ANY, TypeTags.READONLY -> GET_OBJECT; + TypeTags.ANY, TypeTags.READONLY -> + GET_OBJECT; case TypeTags.ARRAY, TypeTags.TUPLE -> GET_ARRAY_VALUE; case TypeTags.ERROR -> GET_ERROR_VALUE; case TypeTags.MAP, TypeTags.RECORD -> GET_MAP_VALUE; @@ -389,13 +389,13 @@ public static String getArgTypeSignature(BType bType) { }; } - public static String generateReturnType(BType bType, Env typeEnv) { + public static String generateReturnType(BType bType) { bType = JvmCodeGenUtil.getImpliedType(bType); if (bType == null) { return RETURN_JOBJECT; } - bType = JvmCodeGenUtil.UNIFIER.build(typeEnv, bType); + bType = JvmCodeGenUtil.UNIFIER.build(bType); if (bType == null || bType.tag == TypeTags.NIL || bType.tag == TypeTags.NEVER) { return RETURN_JOBJECT; } else if (TypeTags.isIntegerTypeTag(bType.tag)) { @@ -419,7 +419,8 @@ public static String generateReturnType(BType bType, Env typeEnv) { case TypeTags.FUTURE -> RETURN_FUTURE_VALUE; case TypeTags.TYPEDESC -> RETURN_TYPEDESC_VALUE; case TypeTags.ANY, TypeTags.ANYDATA, TypeTags.UNION, TypeTags.INTERSECTION, TypeTags.JSON, - TypeTags.FINITE, TypeTags.READONLY -> RETURN_JOBJECT; + TypeTags.FINITE, TypeTags.READONLY -> + RETURN_JOBJECT; case TypeTags.OBJECT -> RETURN_B_OBJECT; case TypeTags.INVOKABLE -> RETURN_FUNCTION_POINTER; case TypeTags.HANDLE -> RETURN_HANDLE_VALUE; @@ -628,12 +629,12 @@ public static void loadConstantValue(BType bType, Object constVal, MethodVisitor } } - static String getStringConstantsClass(int varIndex, JvmConstantsGen jvmConstantsGen) { + private static String getStringConstantsClass(int varIndex, JvmConstantsGen jvmConstantsGen) { int classIndex = varIndex / MAX_STRINGS_PER_METHOD; return jvmConstantsGen.getStringConstantsClass() + UNDERSCORE + classIndex; } - static String removeDecimalDiscriminator(String value) { + private static String removeDecimalDiscriminator(String value) { int length = value.length(); if (length < 2) { return value; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmDesugarPhase.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmDesugarPhase.java index 909ab80efe84..8f5a0f31cbc3 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmDesugarPhase.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmDesugarPhase.java @@ -19,7 +19,6 @@ package org.wso2.ballerinalang.compiler.bir.codegen; import io.ballerina.identifier.Utils; -import io.ballerina.types.Env; import org.ballerinalang.model.elements.PackageID; import org.wso2.ballerinalang.compiler.bir.codegen.methodgen.InitMethodGen; import org.wso2.ballerinalang.compiler.bir.model.BIRNode; @@ -62,9 +61,9 @@ public final class JvmDesugarPhase { private JvmDesugarPhase() { } - public static void addDefaultableBooleanVarsToSignature(Env env, BIRFunction func) { - func.type = - new BInvokableType(env, func.type.paramTypes, func.type.restType, func.type.retType, func.type.tsymbol); + public static void addDefaultableBooleanVarsToSignature(BIRFunction func) { + func.type = new BInvokableType(func.type.paramTypes, func.type.restType, + func.type.retType, func.type.tsymbol); BInvokableType type = func.type; func.type.paramTypes = updateParamTypesWithDefaultableBooleanVar(func.type.paramTypes, type.restType); @@ -95,7 +94,7 @@ private static List updateParamTypesWithDefaultableBooleanVar(List return paramTypes; } - static void rewriteRecordInits(Env env, List typeDefs) { + static void rewriteRecordInits(List typeDefs) { for (BIRTypeDefinition typeDef : typeDefs) { BType recordType = JvmCodeGenUtil.getImpliedType(typeDef.type); if (recordType.tag != TypeTags.RECORD) { @@ -103,12 +102,12 @@ static void rewriteRecordInits(Env env, List typeDefs) { } List attachFuncs = typeDef.attachedFuncs; for (BIRFunction func : attachFuncs) { - rewriteRecordInitFunction(env, func, (BRecordType) recordType); + rewriteRecordInitFunction(func, (BRecordType) recordType); } } } - private static void rewriteRecordInitFunction(Env env, BIRFunction func, BRecordType recordType) { + private static void rewriteRecordInitFunction(BIRFunction func, BRecordType recordType) { BIRVariableDcl receiver = func.receiver; @@ -130,7 +129,7 @@ private static void rewriteRecordInitFunction(Env env, BIRFunction func, BRecord List updatedParamTypes = Lists.of(receiver.type); updatedParamTypes.addAll(func.type.paramTypes); - func.type = new BInvokableType(env, updatedParamTypes, func.type.restType, func.type.retType, null); + func.type = new BInvokableType(updatedParamTypes, func.type.restType, func.type.retType, null); List localVars = func.localVars; List updatedLocalVars = new ArrayList<>(); 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 9f30abec25f5..7ba8024a01db 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 @@ -1620,7 +1620,7 @@ void generateObjectNewIns(BIRNonTerminator.NewInstance objectNewIns, int strandI } private void reloadObjectCtorAnnots(BType type, int strandIndex) { - if ((type.getFlags() & Flags.OBJECT_CTOR) == Flags.OBJECT_CTOR) { + if ((type.flags & Flags.OBJECT_CTOR) == Flags.OBJECT_CTOR) { this.mv.visitTypeInsn(CHECKCAST, OBJECT_TYPE_IMPL); mv.visitMethodInsn(INVOKEVIRTUAL, OBJECT_TYPE_IMPL, "duplicate", OBJECT_TYPE_DUPLICATE, false); this.mv.visitInsn(DUP); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmObservabilityGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmObservabilityGen.java index d655f0f47495..11231092bd9e 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmObservabilityGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmObservabilityGen.java @@ -19,7 +19,6 @@ import io.ballerina.identifier.Utils; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.PredefinedType; import org.ballerinalang.compiler.BLangCompilerException; import org.ballerinalang.model.elements.Flag; import org.ballerinalang.model.elements.PackageID; @@ -54,7 +53,6 @@ import org.wso2.ballerinalang.compiler.bir.model.VarKind; import org.wso2.ballerinalang.compiler.bir.model.VarScope; import org.wso2.ballerinalang.compiler.diagnostic.BLangDiagnosticLocation; -import org.wso2.ballerinalang.compiler.semantics.analyzer.SemTypeHelper; import org.wso2.ballerinalang.compiler.semantics.model.Scope; import org.wso2.ballerinalang.compiler.semantics.model.SymbolTable; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BAttachedFunction; @@ -65,9 +63,11 @@ 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.semantics.model.types.BErrorType; import org.wso2.ballerinalang.compiler.semantics.model.types.BFutureType; import org.wso2.ballerinalang.compiler.semantics.model.types.BInvokableType; import org.wso2.ballerinalang.compiler.semantics.model.types.BType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BUnionType; import org.wso2.ballerinalang.compiler.util.Name; import org.wso2.ballerinalang.compiler.util.Names; import org.wso2.ballerinalang.compiler.util.TypeTags; @@ -181,7 +181,7 @@ public void instrumentPackage(BIRPackage pkg) { if ((typeDef.flags & Flags.CLASS) != Flags.CLASS && bType.tag == TypeTags.OBJECT) { continue; } - boolean isService = (bType.getFlags() & Flags.SERVICE) == Flags.SERVICE; + boolean isService = (bType.flags & Flags.SERVICE) == Flags.SERVICE; String serviceName = null; if (isService) { for (BIRNode.BIRAnnotationAttachment annotationAttachment : typeDef.annotAttachments) { @@ -360,7 +360,7 @@ private void rewriteAsyncInvocations(BIRFunction func, BIRTypeDefinition attache } Name lambdaName = new Name(LAMBDA_PREFIX + "observability" + lambdaIndex++ + "$" + asyncCallIns.name.getValue().replace(".", "_")); - BInvokableType bInvokableType = new BInvokableType(symbolTable.typeEnv(), argTypes, null, + BInvokableType bInvokableType = new BInvokableType(argTypes, null, returnType, null); BIRFunction desugaredFunc = new BIRFunction(asyncCallIns.pos, lambdaName, 0, bInvokableType, func.workerName, 0, VIRTUAL); @@ -986,7 +986,20 @@ private boolean isObservable(Call callIns) { * @return True if an error can be assigned and false otherwise */ private boolean isErrorAssignable(BIRVariableDcl variableDcl) { - return SemTypeHelper.containsBasicType(variableDcl.type, PredefinedType.ERROR); + boolean isErrorAssignable = false; + if (variableDcl.type instanceof BUnionType returnUnionType) { + boolean b = false; + for (BType type : returnUnionType.getMemberTypes()) { + if (type instanceof BErrorType) { + b = true; + break; + } + } + isErrorAssignable = b; + } else if (variableDcl.type instanceof BErrorType) { + isErrorAssignable = true; + } + return isErrorAssignable; } /** diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmPackageGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmPackageGen.java index f5066bc4f697..65643e45ef72 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmPackageGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmPackageGen.java @@ -19,7 +19,6 @@ package org.wso2.ballerinalang.compiler.bir.codegen; import io.ballerina.identifier.Utils; -import io.ballerina.types.Env; import org.ballerinalang.compiler.BLangCompilerException; import org.ballerinalang.model.elements.PackageID; import org.ballerinalang.model.symbols.SymbolKind; @@ -62,6 +61,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.symbols.BSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.Symbols; import org.wso2.ballerinalang.compiler.semantics.model.types.BInvokableType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BNilType; import org.wso2.ballerinalang.compiler.semantics.model.types.BType; import org.wso2.ballerinalang.compiler.util.Name; import org.wso2.ballerinalang.compiler.util.Names; @@ -149,7 +149,6 @@ public class JvmPackageGen { private final BLangDiagnosticLog dlog; private final Types types; private final boolean isRemoteMgtEnabled; - private final Env typeEnv; JvmPackageGen(SymbolTable symbolTable, PackageCache packageCache, BLangDiagnosticLog dlog, Types types, boolean isRemoteMgtEnabled) { @@ -164,7 +163,6 @@ public class JvmPackageGen { initMethodGen = new InitMethodGen(symbolTable); configMethodGen = new ConfigMethodGen(); JvmInstructionGen.anyType = symbolTable.anyType; - this.typeEnv = symbolTable.typeEnv(); } private static String getBvmAlias(String orgName, String moduleName) { @@ -317,21 +315,20 @@ private static void setCurrentModuleField(ClassWriter cw, MethodVisitor mv, JvmC mv.visitFieldInsn(PUTSTATIC, moduleInitClass, CURRENT_MODULE_VAR_NAME, GET_MODULE); } - public static BIRFunctionWrapper getFunctionWrapper(Env typeEnv, BIRFunction currentFunc, PackageID packageID, + public static BIRFunctionWrapper getFunctionWrapper(BIRFunction currentFunc, PackageID packageID, String moduleClass) { BInvokableType functionTypeDesc = currentFunc.type; BIRVariableDcl receiver = currentFunc.receiver; BType retType = functionTypeDesc.retType; - if (isExternFunc(currentFunc) && Symbols.isFlagOn(retType.getFlags(), Flags.PARAMETERIZED)) { - retType = unifier.build(typeEnv, retType); + if (isExternFunc(currentFunc) && Symbols.isFlagOn(retType.flags, Flags.PARAMETERIZED)) { + retType = unifier.build(retType); } String jvmMethodDescription; if (receiver == null) { - jvmMethodDescription = JvmCodeGenUtil.getMethodDesc(typeEnv, functionTypeDesc.paramTypes, retType); + jvmMethodDescription = JvmCodeGenUtil.getMethodDesc(functionTypeDesc.paramTypes, retType); } else { - jvmMethodDescription = JvmCodeGenUtil.getMethodDesc(typeEnv, functionTypeDesc.paramTypes, retType, - receiver.type); + jvmMethodDescription = JvmCodeGenUtil.getMethodDesc(functionTypeDesc.paramTypes, retType, receiver.type); } return new BIRFunctionWrapper(packageID, currentFunc, moduleClass, jvmMethodDescription); } @@ -490,12 +487,11 @@ private void linkTypeDefinitions(BIRPackage module, boolean isEntry) { } private void linkModuleFunction(PackageID packageID, String initClass, String funcName) { - BInvokableType funcType = - new BInvokableType(typeEnv, Collections.emptyList(), null, symbolTable.nilType, null); + BInvokableType funcType = new BInvokableType(Collections.emptyList(), null, new BNilType(), null); BIRFunction moduleStopFunction = new BIRFunction(null, new Name(funcName), 0, funcType, new Name(""), 0, VIRTUAL); birFunctionMap.put(JvmCodeGenUtil.getPackageName(packageID) + funcName, - getFunctionWrapper(typeEnv, moduleStopFunction, packageID, initClass)); + getFunctionWrapper(moduleStopFunction, packageID, initClass)); } private void linkModuleFunctions(BIRPackage birPackage, String initClass, boolean isEntry, @@ -517,20 +513,20 @@ private void linkModuleFunctions(BIRPackage birPackage, String initClass, boolea PackageID packageID = birPackage.packageID; jvmClassMap.put(initClass, klass); String pkgName = JvmCodeGenUtil.getPackageName(packageID); - birFunctionMap.put(pkgName + functionName, getFunctionWrapper(typeEnv, initFunc, packageID, initClass)); + birFunctionMap.put(pkgName + functionName, getFunctionWrapper(initFunc, packageID, initClass)); count += 1; // Add start function BIRFunction startFunc = functions.get(1); functionName = Utils.encodeFunctionIdentifier(startFunc.name.value); - birFunctionMap.put(pkgName + functionName, getFunctionWrapper(typeEnv, startFunc, packageID, initClass)); + birFunctionMap.put(pkgName + functionName, getFunctionWrapper(startFunc, packageID, initClass)); klass.functions.add(1, startFunc); count += 1; // Add stop function BIRFunction stopFunc = functions.get(2); functionName = Utils.encodeFunctionIdentifier(stopFunc.name.value); - birFunctionMap.put(pkgName + functionName, getFunctionWrapper(typeEnv, stopFunc, packageID, initClass)); + birFunctionMap.put(pkgName + functionName, getFunctionWrapper(stopFunc, packageID, initClass)); klass.functions.add(2, stopFunc); count += 1; int genMethodsCount = 0; @@ -589,13 +585,12 @@ private BIRFunctionWrapper getBirFunctionWrapper(boolean isEntry, PackageID pack BIRFunction birFunc, String birModuleClassName) { BIRFunctionWrapper birFuncWrapperOrError; if (isExternFunc(birFunc) && isEntry) { - birFuncWrapperOrError = createExternalFunctionWrapper(typeEnv, true, birFunc, packageID, - birModuleClassName); + birFuncWrapperOrError = createExternalFunctionWrapper(true, birFunc, packageID, birModuleClassName); } else { if (isEntry && birFunc.receiver == null) { - addDefaultableBooleanVarsToSignature(typeEnv, birFunc); + addDefaultableBooleanVarsToSignature(birFunc); } - birFuncWrapperOrError = getFunctionWrapper(typeEnv, birFunc, packageID, birModuleClassName); + birFuncWrapperOrError = getFunctionWrapper(birFunc, packageID, birModuleClassName); } return birFuncWrapperOrError; } @@ -690,8 +685,8 @@ CompiledJarFile generate(BIRPackage module) { // use a ByteArrayOutputStream to store class byte values final JarEntries jarEntries = compiledJarFile.jarEntries; // desugar parameter initialization - injectDefaultParamInits(typeEnv, module, initMethodGen); - injectDefaultParamInitsToAttachedFuncs(typeEnv, module, initMethodGen); + injectDefaultParamInits(module, initMethodGen); + injectDefaultParamInitsToAttachedFuncs(module, initMethodGen); BIRFunction mainFunc = getMainFunction(module); BIRFunction testExecuteFunc = getTestExecuteFunction(module); @@ -722,7 +717,7 @@ CompiledJarFile generate(BIRPackage module) { removeSourceAnnotationTypeDefs(module.typeDefs); // desugar the record init function - rewriteRecordInits(typeEnv, module.typeDefs); + rewriteRecordInits(module.typeDefs); // generate object/record value classes JvmValueGen valueGen = new JvmValueGen(module, this, methodGen, typeHashVisitor, types); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java index 42097b0a202c..088e937ba560 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java @@ -297,7 +297,7 @@ private void genGoToTerm(BIRTerminator.GOTO gotoIns, String funcName) { public void genReturnTerm(int returnVarRefIndex, BIRNode.BIRFunction func, int channelMapVarIndex, int sendWorkerChannelNamesVar, int receiveWorkerChannelNamesVar, int localVarOffset) { - BType bType = unifier.build(symbolTable.typeEnv(), func.type.retType); + BType bType = unifier.build(func.type.retType); generateReturnTermFromType(bType, func, returnVarRefIndex, channelMapVarIndex, sendWorkerChannelNamesVar, receiveWorkerChannelNamesVar, localVarOffset); } @@ -606,8 +606,8 @@ private void genStaticCall(BIRTerminator.Call callIns, PackageID packageID, int jvmClass = JvmCodeGenUtil.getModuleLevelClassName(packageID, JvmCodeGenUtil.cleanupPathSeparators(balFileName)); //TODO: add receiver: BType attachedType = type.r != null ? receiver.type : null; - BType retType = unifier.build(symbolTable.typeEnv(), type.retType); - methodDesc = JvmCodeGenUtil.getMethodDesc(symbolTable.typeEnv(), params, retType); + BType retType = unifier.build(type.retType); + methodDesc = JvmCodeGenUtil.getMethodDesc(params, retType); } this.mv.visitMethodInsn(INVOKESTATIC, jvmClass, encodedMethodName, methodDesc, false); } 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 d5ed32a31e04..491a1fa6b564 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 @@ -18,16 +18,6 @@ package org.wso2.ballerinalang.compiler.bir.codegen; import io.ballerina.identifier.Utils; -import io.ballerina.types.ComplexSemType; -import io.ballerina.types.Context; -import io.ballerina.types.Core; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.subtypedata.BooleanSubtype; -import io.ballerina.types.subtypedata.DecimalSubtype; -import io.ballerina.types.subtypedata.FloatSubtype; -import io.ballerina.types.subtypedata.IntSubtype; -import io.ballerina.types.subtypedata.StringSubtype; import org.ballerinalang.compiler.BLangCompilerException; import org.ballerinalang.model.elements.PackageID; import org.ballerinalang.model.symbols.SymbolKind; @@ -37,7 +27,8 @@ import org.objectweb.asm.MethodVisitor; import org.wso2.ballerinalang.compiler.bir.codegen.split.JvmConstantsGen; import org.wso2.ballerinalang.compiler.bir.model.BIRNode.BIRTypeDefinition; -import org.wso2.ballerinalang.compiler.semantics.analyzer.SemTypeHelper; +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.model.SymbolTable; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableSymbol; @@ -61,23 +52,16 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BTypedescType; import org.wso2.ballerinalang.compiler.semantics.model.types.BUnionType; import org.wso2.ballerinalang.compiler.semantics.model.types.BXMLType; -import org.wso2.ballerinalang.compiler.semantics.model.types.SemNamedType; import org.wso2.ballerinalang.compiler.semantics.model.types.TypeFlags; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangExpression; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral; import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.util.Flags; -import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.Set; -import static io.ballerina.types.BasicTypeCode.BT_BOOLEAN; -import static io.ballerina.types.BasicTypeCode.BT_DECIMAL; -import static io.ballerina.types.BasicTypeCode.BT_FLOAT; -import static io.ballerina.types.BasicTypeCode.BT_INT; -import static io.ballerina.types.BasicTypeCode.BT_STRING; -import static io.ballerina.types.Core.getComplexSubtypeData; -import static io.ballerina.types.SemTypes.isSubtypeSimple; import static org.objectweb.asm.Opcodes.AASTORE; import static org.objectweb.asm.Opcodes.ACC_PUBLIC; import static org.objectweb.asm.Opcodes.ACC_STATIC; @@ -100,17 +84,13 @@ import static org.objectweb.asm.Opcodes.POP; import static org.objectweb.asm.Opcodes.RETURN; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmCodeGenUtil.getModuleLevelClassName; -import static org.wso2.ballerinalang.compiler.bir.codegen.JvmCodeGenUtil.getStringConstantsClass; -import static org.wso2.ballerinalang.compiler.bir.codegen.JvmCodeGenUtil.removeDecimalDiscriminator; 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.BOOLEAN_VALUE; -import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.B_STRING_VAR_PREFIX; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.CALL_FUNCTION; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.CREATE_ERROR_VALUE; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.CREATE_OBJECT_VALUE; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.CREATE_RECORD_VALUE; -import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.DECIMAL_VALUE; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.DOUBLE_VALUE; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.FINITE_TYPE_IMPL; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.FUNCTION_PARAMETER; @@ -182,7 +162,6 @@ import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INIT_TABLE_TYPE_IMPL; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INIT_TABLE_TYPE_WITH_FIELD_NAME_LIST; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INIT_WITH_BOOLEAN; -import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INIT_WITH_STRING; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INT_VALUE_OF_METHOD; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.LOAD_ANYDATA_TYPE; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.LOAD_ANY_TYPE; @@ -214,6 +193,8 @@ */ public class JvmTypeGen { + private final IsPureTypeUniqueVisitor isPureTypeUniqueVisitor; + private final IsAnydataUniqueVisitor isAnydataUniqueVisitor; private final JvmConstantsGen jvmConstantsGen; private final TypeHashVisitor typeHashVisitor; private final SymbolTable symbolTable; @@ -224,12 +205,13 @@ public class JvmTypeGen { private final String objectsClass; private final String errorsClass; private final String functionCallsClass; - private final Context semTypeCtx; public JvmTypeGen(JvmConstantsGen jvmConstantsGen, PackageID packageID, TypeHashVisitor typeHashVisitor, SymbolTable symbolTable) { this.jvmConstantsGen = jvmConstantsGen; this.packageID = packageID; + isPureTypeUniqueVisitor = new IsPureTypeUniqueVisitor(); + isAnydataUniqueVisitor = new IsAnydataUniqueVisitor(); this.typeHashVisitor = typeHashVisitor; this.symbolTable = symbolTable; this.anonTypesClass = getModuleLevelClassName(packageID, MODULE_ANON_TYPES_CLASS_NAME); @@ -238,7 +220,6 @@ public JvmTypeGen(JvmConstantsGen jvmConstantsGen, PackageID packageID, TypeHash this.objectsClass = getModuleLevelClassName(packageID, MODULE_OBJECTS_CREATOR_CLASS_NAME); this.errorsClass = getModuleLevelClassName(packageID, MODULE_ERRORS_CREATOR_CLASS_NAME); this.functionCallsClass = getModuleLevelClassName(packageID, MODULE_FUNCTION_CALLS_CLASS_NAME); - this.semTypeCtx = Context.from(symbolTable.typeEnv()); } /** @@ -369,10 +350,10 @@ private void generateFunctionCallMethod(ClassWriter cw, String moduleClass) { } public int typeFlag(BType type) { - boolean isAnydata = SemTypeHelper.isSubtype(semTypeCtx, type, Core.createAnydata(semTypeCtx)); - boolean isPureType = isAnydata || SemTypeHelper.isSubtype(semTypeCtx, type, - Core.union(Core.createAnydata(semTypeCtx), PredefinedType.ERROR)); - return TypeFlags.asMask(type.isNullable(), isAnydata, isPureType); + isAnydataUniqueVisitor.reset(); + isPureTypeUniqueVisitor.reset(); + return TypeFlags.asMask(type.isNullable(), isAnydataUniqueVisitor.visit(type), + isPureTypeUniqueVisitor.visit(type)); } // ------------------------------------------------------- @@ -407,27 +388,25 @@ public void loadType(MethodVisitor mv, BType bType) { case TypeTags.BOOLEAN -> typeFieldName = "TYPE_BOOLEAN"; case TypeTags.BYTE -> typeFieldName = "TYPE_BYTE"; case TypeTags.ANY -> - typeFieldName = Symbols.isFlagOn(bType.getFlags(), Flags.READONLY) ? "TYPE_READONLY_ANY" : - + typeFieldName = Symbols.isFlagOn(bType.flags, Flags.READONLY) ? "TYPE_READONLY_ANY" : "TYPE_ANY"; case TypeTags.ANYDATA, TypeTags.REGEXP -> - typeFieldName = Symbols.isFlagOn(bType.getFlags(), Flags.READONLY) ? "TYPE_READONLY_ANYDATA" : + typeFieldName = Symbols.isFlagOn(bType.flags, Flags.READONLY) ? "TYPE_READONLY_ANYDATA" : "TYPE_ANYDATA"; case TypeTags.JSON -> - typeFieldName = Symbols.isFlagOn(bType.getFlags(), Flags.READONLY) ? "TYPE_READONLY_JSON" : - + typeFieldName = Symbols.isFlagOn(bType.flags, Flags.READONLY) ? "TYPE_READONLY_JSON" : "TYPE_JSON"; case TypeTags.XML -> { loadXmlType(mv, (BXMLType) bType); return; } case TypeTags.XML_ELEMENT -> - typeFieldName = Symbols.isFlagOn(bType.getFlags(), Flags.READONLY) ? "TYPE_READONLY_ELEMENT" : + typeFieldName = Symbols.isFlagOn(bType.flags, Flags.READONLY) ? "TYPE_READONLY_ELEMENT" : "TYPE_ELEMENT"; - case TypeTags.XML_PI -> typeFieldName = Symbols.isFlagOn(bType.getFlags(), Flags.READONLY) ? + case TypeTags.XML_PI -> typeFieldName = Symbols.isFlagOn(bType.flags, Flags.READONLY) ? "TYPE_READONLY_PROCESSING_INSTRUCTION" : "TYPE_PROCESSING_INSTRUCTION"; case TypeTags.XML_COMMENT -> - typeFieldName = Symbols.isFlagOn(bType.getFlags(), Flags.READONLY) ? "TYPE_READONLY_COMMENT" : + typeFieldName = Symbols.isFlagOn(bType.flags, Flags.READONLY) ? "TYPE_READONLY_COMMENT" : "TYPE_COMMENT"; case TypeTags.XML_TEXT -> typeFieldName = "TYPE_TEXT"; case TypeTags.TYPEDESC -> { @@ -528,7 +507,8 @@ private String loadTypeClass(BType bType) { return switch (bType.tag) { case TypeTags.NEVER -> LOAD_NEVER_TYPE; case TypeTags.INT, TypeTags.UNSIGNED8_INT, TypeTags.UNSIGNED16_INT, TypeTags.UNSIGNED32_INT, - TypeTags.SIGNED8_INT, TypeTags.SIGNED16_INT, TypeTags.SIGNED32_INT -> LOAD_INTEGER_TYPE; + TypeTags.SIGNED8_INT, TypeTags.SIGNED16_INT, TypeTags.SIGNED32_INT -> + LOAD_INTEGER_TYPE; case TypeTags.FLOAT -> LOAD_FLOAT_TYPE; case TypeTags.STRING, TypeTags.CHAR_STRING -> LOAD_STRING_TYPE; case TypeTags.DECIMAL -> LOAD_DECIMAL_TYPE; @@ -539,7 +519,7 @@ private String loadTypeClass(BType bType) { case TypeTags.JSON -> LOAD_JSON_TYPE; case TypeTags.XML, TypeTags.XML_TEXT -> LOAD_XML_TYPE; case TypeTags.XML_ELEMENT, TypeTags.XML_PI, TypeTags.XML_COMMENT -> - Symbols.isFlagOn(bType.getFlags(), Flags.READONLY) ? LOAD_TYPE : LOAD_XML_TYPE; + Symbols.isFlagOn(bType.flags, Flags.READONLY) ? LOAD_TYPE : LOAD_XML_TYPE; case TypeTags.OBJECT -> Symbols.isService(bType.tsymbol) ? LOAD_SERVICE_TYPE : LOAD_OBJECT_TYPE; case TypeTags.HANDLE -> LOAD_HANDLE_TYPE; case TypeTags.READONLY -> LOAD_READONLY_TYPE; @@ -590,7 +570,7 @@ private void loadMapType(MethodVisitor mv, BMapType bType) { } public void loadReadonlyFlag(MethodVisitor mv, BType bType) { - if (Symbols.isFlagOn(bType.getFlags(), Flags.READONLY)) { + if (Symbols.isFlagOn(bType.flags, Flags.READONLY)) { mv.visitInsn(ICONST_1); } else { mv.visitInsn(ICONST_0); @@ -690,7 +670,7 @@ private void loadErrorType(MethodVisitor mv, BErrorType errorType) { return; } - if (Symbols.isFlagOn(errorType.getFlags(), Flags.ANONYMOUS)) { + if (Symbols.isFlagOn(errorType.flags, Flags.ANONYMOUS)) { jvmConstantsGen.generateGetBErrorType(mv, jvmConstantsGen.getTypeConstantsVar(errorType, symbolTable)); } else { String typeOwner = JvmCodeGenUtil.getPackageName(pkgID) + MODULE_INIT_CLASS_NAME; @@ -835,7 +815,7 @@ private void loadUserDefinedType(MethodVisitor mv, BType bType) { boolean samePackage = JvmCodeGenUtil.isSameModule(this.packageID, pkgID); // if name contains $anon and doesn't belong to the same package, load type using getAnonType() method. - if (!samePackage && Symbols.isFlagOn(typeToLoad.getFlags(), Flags.ANONYMOUS)) { + if (!samePackage && Symbols.isFlagOn(typeToLoad.flags, Flags.ANONYMOUS)) { Integer hash = typeHashVisitor.visit(typeToLoad); String shape = typeToLoad.toString(); typeHashVisitor.reset(); @@ -896,8 +876,8 @@ public void loadInvokableType(MethodVisitor mv, BInvokableType bType) { mv.visitFieldInsn(GETSTATIC, jvmConstantsGen.getModuleConstantClass(), moduleName, GET_MODULE); } - if (Symbols.isFlagOn(bType.getFlags(), Flags.ANY_FUNCTION)) { - mv.visitLdcInsn(bType.getFlags()); + if (Symbols.isFlagOn(bType.flags, Flags.ANY_FUNCTION)) { + mv.visitLdcInsn(bType.flags); mv.visitMethodInsn(INVOKESPECIAL, FUNCTION_TYPE_IMPL, JVM_INIT_METHOD, INIT_FUNCTION_TYPE_IMPL, false); return; } @@ -914,7 +894,7 @@ public void loadInvokableType(MethodVisitor mv, BInvokableType bType) { // load return type loadType(mv, bType.retType); - mv.visitLdcInsn(bType.getFlags()); + mv.visitLdcInsn(bType.flags); mv.visitLdcInsn(bType.name.getValue()); // initialize the function type using the param types array and the return type mv.visitMethodInsn(INVOKESPECIAL, FUNCTION_TYPE_IMPL, JVM_INIT_METHOD, INIT_FUNCTION_TYPE_IMPL_WITH_PARAMS, @@ -1028,7 +1008,8 @@ public static String getTypeDesc(BType bType) { case TypeTags.FLOAT -> "D"; case TypeTags.BOOLEAN -> "Z"; case TypeTags.NIL, TypeTags.NEVER, TypeTags.ANY, TypeTags.ANYDATA, TypeTags.UNION, TypeTags.JSON, - TypeTags.FINITE, TypeTags.READONLY -> GET_OBJECT; + TypeTags.FINITE, TypeTags.READONLY -> + GET_OBJECT; case TypeTags.ARRAY, TypeTags.TUPLE -> GET_ARRAY_VALUE; case TypeTags.ERROR -> GET_ERROR_VALUE; case TypeTags.FUTURE -> GET_FUTURE_VALUE; @@ -1059,23 +1040,18 @@ private void loadFiniteType(MethodVisitor mv, BFiniteType finiteType) { mv.visitInsn(DUP); mv.visitMethodInsn(INVOKESPECIAL, LINKED_HASH_SET, JVM_INIT_METHOD, VOID_METHOD_DESC, false); - for (SemNamedType semNamedType : finiteType.valueSpace) { + for (BLangExpression valueTypePair : finiteType.getValueSpace()) { + Object value = ((BLangLiteral) valueTypePair).value; + BType valueType = valueTypePair.getBType(); mv.visitInsn(DUP); - SemType s = semNamedType.semType(); - if (PredefinedType.NIL.equals(s)) { - mv.visitInsn(ACONST_NULL); - } else if (isSubtypeSimple(s, PredefinedType.BOOLEAN)) { - loadConstBoolean(mv, (ComplexSemType) s); - } else if (isSubtypeSimple(s, PredefinedType.INT)) { - loadConstInteger(mv, (ComplexSemType) s); - } else if (isSubtypeSimple(s, PredefinedType.FLOAT)) { - loadConstFloat(mv, (ComplexSemType) s); - } else if (isSubtypeSimple(s, PredefinedType.DECIMAL)) { - loadConstDecimal(mv, (ComplexSemType) s); - } else if (isSubtypeSimple(s, PredefinedType.STRING)) { - loadConstString(mv, (ComplexSemType) s); + + JvmCodeGenUtil.loadConstantValue(valueType, value, mv, jvmConstantsGen); + + if (TypeTags.isIntegerTypeTag(JvmCodeGenUtil.getImpliedType(valueType).tag)) { + mv.visitMethodInsn(INVOKESTATIC, LONG_VALUE, VALUE_OF_METHOD, LONG_VALUE_OF, + false); } else { - throw new IllegalStateException("Unexpected value space type: " + s); + loadValueType(mv, valueType); } // Add the value to the set @@ -1090,42 +1066,16 @@ private void loadFiniteType(MethodVisitor mv, BFiniteType finiteType) { mv.visitMethodInsn(INVOKESPECIAL, FINITE_TYPE_IMPL, JVM_INIT_METHOD, INIT_FINITE_TYPE_IMPL, false); } - private void loadConstString(MethodVisitor mv, ComplexSemType s) { - String stringVal = StringSubtype.stringSubtypeSingleValue(getComplexSubtypeData(s, BT_STRING)).orElseThrow(); - int index = jvmConstantsGen.getBStringConstantVarIndex(stringVal); - String varName = B_STRING_VAR_PREFIX + index; - String stringConstantsClass = getStringConstantsClass(index, jvmConstantsGen); - mv.visitFieldInsn(GETSTATIC, stringConstantsClass, varName, GET_BSTRING); - } - - private static void loadConstDecimal(MethodVisitor mv, ComplexSemType s) { - BigDecimal bVal = DecimalSubtype.decimalSubtypeSingleValue(getComplexSubtypeData(s, BT_DECIMAL)).orElseThrow(); - mv.visitTypeInsn(NEW, DECIMAL_VALUE); - mv.visitInsn(DUP); - mv.visitLdcInsn(removeDecimalDiscriminator(String.valueOf(bVal))); - mv.visitMethodInsn(INVOKESPECIAL, DECIMAL_VALUE, JVM_INIT_METHOD, INIT_WITH_STRING, false); - } - - private static void loadConstFloat(MethodVisitor mv, ComplexSemType s) { - double doubleVal = FloatSubtype.floatSubtypeSingleValue(getComplexSubtypeData(s, BT_FLOAT)).orElseThrow(); - mv.visitLdcInsn(doubleVal); - mv.visitMethodInsn(INVOKESTATIC, DOUBLE_VALUE, VALUE_OF_METHOD, DOUBLE_VALUE_OF_METHOD, false); - } - - private static void loadConstInteger(MethodVisitor mv, ComplexSemType s) { - long longVal = IntSubtype.intSubtypeSingleValue(getComplexSubtypeData(s, BT_INT)).orElseThrow(); - if (0 <= longVal && longVal <= 255) { - mv.visitLdcInsn((int) longVal); - mv.visitMethodInsn(INVOKESTATIC, INT_VALUE, VALUE_OF_METHOD, INT_VALUE_OF_METHOD, false); - } else { - mv.visitLdcInsn(longVal); - mv.visitMethodInsn(INVOKESTATIC, LONG_VALUE, VALUE_OF_METHOD, LONG_VALUE_OF, false); + private void loadValueType(MethodVisitor mv, BType valueType) { + valueType = JvmCodeGenUtil.getImpliedType(valueType); + switch (valueType.tag) { + case TypeTags.BOOLEAN -> mv.visitMethodInsn(INVOKESTATIC, BOOLEAN_VALUE, VALUE_OF_METHOD, + BOOLEAN_VALUE_OF_METHOD, false); + case TypeTags.FLOAT -> mv.visitMethodInsn(INVOKESTATIC, DOUBLE_VALUE, VALUE_OF_METHOD, + DOUBLE_VALUE_OF_METHOD, false); + case TypeTags.BYTE -> mv.visitMethodInsn(INVOKESTATIC, INT_VALUE, VALUE_OF_METHOD, + INT_VALUE_OF_METHOD, false); } } - private static void loadConstBoolean(MethodVisitor mv, ComplexSemType s) { - boolean boolVal = BooleanSubtype.booleanSubtypeSingleValue(getComplexSubtypeData(s, BT_BOOLEAN)).orElseThrow(); - mv.visitLdcInsn(boolVal); - mv.visitMethodInsn(INVOKESTATIC, BOOLEAN_VALUE, VALUE_OF_METHOD, BOOLEAN_VALUE_OF_METHOD, false); - } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTypeTestGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTypeTestGen.java index 399b7cfea49b..cd3a61752802 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTypeTestGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTypeTestGen.java @@ -18,15 +18,13 @@ package org.wso2.ballerinalang.compiler.bir.codegen; -import io.ballerina.types.Core; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypes; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.wso2.ballerinalang.compiler.bir.model.BIRNonTerminator; import org.wso2.ballerinalang.compiler.semantics.analyzer.Types; import org.wso2.ballerinalang.compiler.semantics.model.types.BType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BUnionType; +import org.wso2.ballerinalang.compiler.util.TypeTags; import static org.objectweb.asm.Opcodes.GOTO; import static org.objectweb.asm.Opcodes.ICONST_0; @@ -88,92 +86,106 @@ void generateTypeTestIns(BIRNonTerminator.TypeTest typeTestIns) { } /** - * Checks if we have x is (). - *
- * In that case we can simplify is-check to a x instanceof null check. + * Checks if the type tested for is nil. That is the target type is nil. Example instructions include 'a is ()' + * where 'a' is a variable of type say any or a union with nil. * * @param sourceType the declared variable type * @param targetType the RHS type in the type check instruction. Type to be tested for * @return whether instruction could be optimized using 'instanceof` check */ private boolean canOptimizeNilCheck(BType sourceType, BType targetType) { - return PredefinedType.NIL.equals(targetType.semType()) && - SemTypes.containsBasicType(sourceType.semType(), PredefinedType.NIL); + return JvmCodeGenUtil.getImpliedType(targetType).tag == TypeTags.NIL && + types.isAssignable(targetType, sourceType); } /** - * Checks if we have x is T in which x's static type is T'=T|(). - *
- * In that case we can simplify is-check to a !(x instanceof null) check. + * This checks for any variable declaration containing a nil in a union of two types. Examples include string? or + * error? or int?. * * @param sourceType the declared variable type * @param targetType the RHS type in the type check instruction. Type to be tested for * @return whether instruction could be optimized using 'instanceof` check for null */ private boolean canOptimizeNilUnionCheck(BType sourceType, BType targetType) { - SemType sourceTy = sourceType.semType(); - if (!SemTypes.containsBasicType(sourceTy, PredefinedType.NIL)) { + sourceType = JvmCodeGenUtil.getImpliedType(sourceType); + if (isInValidUnionType(sourceType)) { return false; } - - SemType tyButNil = Core.diff(sourceTy, PredefinedType.NIL); - if (Core.isNever(tyButNil)) { - return false; + boolean foundNil = false; + BType otherType = null; + for (BType bType : ((BUnionType) sourceType).getMemberTypes()) { + if (JvmCodeGenUtil.getImpliedType(bType).tag == TypeTags.NIL) { + foundNil = true; + } else { + otherType = bType; + } } - return SemTypes.isSameType(types.typeCtx(), tyButNil, targetType.semType()); + return foundNil && targetType.equals(otherType); } /** - * Checks if we have x is E where E is a subtype of error and error part - * of x is a subtype of E. - *
- * In that case we can simplify is-check to a x instanceof BError check. + * Checks if the type tested for is error. That is the target type is error. Example instructions include 'a is + * error' where 'a' is a variable of type say any or a union with nil. * * @param sourceType the declared variable type * @param targetType the RHS type in the type check instruction. Type to be tested for * @return whether instruction could be optimized using 'instanceof` check for BError */ private boolean canOptimizeErrorCheck(BType sourceType, BType targetType) { - SemType targetTy = targetType.semType(); - if (!Core.isSubtypeSimple(targetTy, PredefinedType.ERROR)) { + sourceType = JvmCodeGenUtil.getImpliedType(sourceType); + targetType = JvmCodeGenUtil.getImpliedType(targetType); + if (targetType.tag != TypeTags.ERROR || sourceType.tag != TypeTags.UNION) { return false; } - - SemType errIntersect = SemTypes.intersect(sourceType.semType(), PredefinedType.ERROR); - if (Core.isNever(errIntersect)) { - return false; + BType errorType = null; + int foundError = 0; + for (BType bType : ((BUnionType) sourceType).getMemberTypes()) { + if (bType.tag == TypeTags.ERROR) { + foundError++; + errorType = bType; + } } - return SemTypes.isSubtype(types.typeCtx(), errIntersect, targetTy); + return (foundError == 1 && types.isAssignable(errorType, targetType)) || (foundError > 0 && "error".equals( + targetType.tsymbol.name.value)); } /** - * Checks if we have x is T in which x's static type is T'=T|E where - * E is a non-empty error type. - *
- * In that case we can simplify is-check to a !(x instanceof BError) check. + * This checks for any variable declaration containing a error in a union of two types. Examples include + * string|error or error|error or int|error. * * @param sourceType the declared variable type * @param targetType the RHS type in the type check instruction. Type to be tested for * @return whether instruction could be optimized using 'instanceof` check for BError */ private boolean canOptimizeErrorUnionCheck(BType sourceType, BType targetType) { - SemType sourceTy = sourceType.semType(); - if (!SemTypes.containsBasicType(sourceTy, PredefinedType.ERROR)) { + sourceType = JvmCodeGenUtil.getImpliedType(sourceType); + if (isInValidUnionType(sourceType)) { return false; } + BType otherType = null; + int foundError = 0; + for (BType bType : ((BUnionType) sourceType).getMemberTypes()) { + if (JvmCodeGenUtil.getImpliedType(bType).tag == TypeTags.ERROR) { + foundError++; + } else { + otherType = bType; + } + } + return foundError == 1 && targetType.equals(otherType); + } - SemType tyButError = Core.diff(sourceTy, PredefinedType.ERROR); - if (Core.isNever(tyButError)) { - return false; + private boolean isInValidUnionType(BType rhsType) { + if (rhsType.tag != TypeTags.UNION) { + return true; } - return SemTypes.isSameType(types.typeCtx(), tyButError, targetType.semType()); + return ((BUnionType) rhsType).getMemberTypes().size() != 2; } private void handleNilUnionType(BIRNonTerminator.TypeTest typeTestIns) { jvmInstructionGen.loadVar(typeTestIns.rhsOp.variableDcl); jvmCastGen.addBoxInsn(this.mv, typeTestIns.rhsOp.variableDcl.type); Label ifLabel = new Label(); - if (PredefinedType.NIL.equals(typeTestIns.type.semType())) { + if (JvmCodeGenUtil.getImpliedType(typeTestIns.type).tag == TypeTags.NIL) { mv.visitJumpInsn(IFNONNULL, ifLabel); } else { mv.visitJumpInsn(IFNULL, ifLabel); @@ -194,7 +206,7 @@ private void loadBoolean(Label ifLabel) { private void handleErrorUnionType(BIRNonTerminator.TypeTest typeTestIns) { jvmInstructionGen.loadVar(typeTestIns.rhsOp.variableDcl); mv.visitTypeInsn(INSTANCEOF, BERROR); - if (!Core.isSubtypeSimple(typeTestIns.type.semType(), PredefinedType.ERROR)) { + if (JvmCodeGenUtil.getImpliedType(typeTestIns.type).tag != TypeTags.ERROR) { generateNegateBoolean(); } jvmInstructionGen.storeToVar(typeTestIns.lhsOp.variableDcl); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmValueGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmValueGen.java index e8266b89bc75..7d97b9ab36c9 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmValueGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmValueGen.java @@ -17,7 +17,6 @@ */ package org.wso2.ballerinalang.compiler.bir.codegen; -import io.ballerina.types.Env; import org.ballerinalang.model.elements.PackageID; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.FieldVisitor; @@ -138,29 +137,28 @@ public class JvmValueGen { this.types = types; } - static void injectDefaultParamInitsToAttachedFuncs(Env env, BIRNode.BIRPackage module, - InitMethodGen initMethodGen) { + static void injectDefaultParamInitsToAttachedFuncs(BIRNode.BIRPackage module, InitMethodGen initMethodGen) { List typeDefs = module.typeDefs; for (BIRNode.BIRTypeDefinition optionalTypeDef : typeDefs) { BType bType = JvmCodeGenUtil.getImpliedType(optionalTypeDef.type); if ((bType.tag == TypeTags.OBJECT && Symbols.isFlagOn( bType.tsymbol.flags, Flags.CLASS)) || bType.tag == TypeTags.RECORD) { - desugarObjectMethods(env, optionalTypeDef.attachedFuncs, initMethodGen); + desugarObjectMethods(optionalTypeDef.attachedFuncs, initMethodGen); } } } - private static void desugarObjectMethods(Env env, List attachedFuncs, InitMethodGen initMethodGen) { + private static void desugarObjectMethods(List attachedFuncs, InitMethodGen initMethodGen) { for (BIRNode.BIRFunction birFunc : attachedFuncs) { if (JvmCodeGenUtil.isExternFunc(birFunc)) { if (birFunc instanceof JMethodBIRFunction jMethodBIRFunction) { - desugarInteropFuncs(env, jMethodBIRFunction, initMethodGen); + desugarInteropFuncs(jMethodBIRFunction, initMethodGen); initMethodGen.resetIds(); } else if (!(birFunc instanceof JFieldBIRFunction)) { initMethodGen.resetIds(); } } else { - addDefaultableBooleanVarsToSignature(env, birFunc); + addDefaultableBooleanVarsToSignature(birFunc); initMethodGen.resetIds(); } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/ExternalMethodGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/ExternalMethodGen.java index 65286884f9f3..5d25387eb63e 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/ExternalMethodGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/ExternalMethodGen.java @@ -18,7 +18,6 @@ package org.wso2.ballerinalang.compiler.bir.codegen.interop; -import io.ballerina.types.Env; import org.ballerinalang.model.elements.PackageID; import org.objectweb.asm.ClassWriter; import org.wso2.ballerinalang.compiler.bir.codegen.JvmCastGen; @@ -64,7 +63,7 @@ public static void genJMethodForBExternalFunc(BIRFunction birFunc, ClassWriter c } } - public static void injectDefaultParamInits(Env typeEnv, BIRPackage module, InitMethodGen initMethodGen) { + public static void injectDefaultParamInits(BIRPackage module, InitMethodGen initMethodGen) { // filter out functions. List functions = module.functions; if (!functions.isEmpty()) { @@ -75,7 +74,7 @@ public static void injectDefaultParamInits(Env typeEnv, BIRPackage module, InitM BIRFunction birFunc = functions.get(count); count = count + 1; if (birFunc instanceof JMethodBIRFunction jMethodBIRFunction) { - desugarInteropFuncs(typeEnv, jMethodBIRFunction, initMethodGen); + desugarInteropFuncs(jMethodBIRFunction, initMethodGen); initMethodGen.resetIds(); } else if (!(birFunc instanceof JFieldBIRFunction)) { initMethodGen.resetIds(); @@ -84,12 +83,12 @@ public static void injectDefaultParamInits(Env typeEnv, BIRPackage module, InitM } } - public static BIRFunctionWrapper createExternalFunctionWrapper(Env env, boolean isEntry, BIRFunction birFunc, + public static BIRFunctionWrapper createExternalFunctionWrapper(boolean isEntry, BIRFunction birFunc, PackageID packageID, String birModuleClassName) { if (isEntry) { - addDefaultableBooleanVarsToSignature(env, birFunc); + addDefaultableBooleanVarsToSignature(birFunc); } - return getFunctionWrapper(env, birFunc, packageID, birModuleClassName); + return getFunctionWrapper(birFunc, packageID, birModuleClassName); } private ExternalMethodGen() { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/InteropMethodGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/InteropMethodGen.java index 37c764a58496..0b2d373cf1e9 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/InteropMethodGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/InteropMethodGen.java @@ -18,7 +18,6 @@ package org.wso2.ballerinalang.compiler.bir.codegen.interop; -import io.ballerina.types.Env; import org.ballerinalang.compiler.BLangCompilerException; import org.ballerinalang.model.elements.PackageID; import org.objectweb.asm.ClassWriter; @@ -142,11 +141,11 @@ static void genJFieldForInteropField(JFieldBIRFunction birFunc, ClassWriter clas // Generate method desc BType retType = birFunc.type.retType; - if (Symbols.isFlagOn(retType.getFlags(), Flags.PARAMETERIZED)) { - retType = JvmCodeGenUtil.UNIFIER.build(types.typeEnv(), birFunc.type.retType); + if (Symbols.isFlagOn(retType.flags, Flags.PARAMETERIZED)) { + retType = JvmCodeGenUtil.UNIFIER.build(birFunc.type.retType); } - String desc = JvmCodeGenUtil.getMethodDesc(types.typeEnv(), birFunc.type.paramTypes, retType); + String desc = JvmCodeGenUtil.getMethodDesc(birFunc.type.paramTypes, retType); int access = birFunc.receiver != null ? ACC_PUBLIC : ACC_PUBLIC + ACC_STATIC; MethodVisitor mv = classWriter.visitMethod(access, birFunc.name.value, desc, null, null); JvmInstructionGen instGen = new JvmInstructionGen(mv, indexMap, birModule, jvmPackageGen, jvmTypeGen, @@ -258,11 +257,11 @@ static void genJFieldForInteropField(JFieldBIRFunction birFunc, ClassWriter clas mv.visitEnd(); } - public static void desugarInteropFuncs(Env typeEnv, JMethodBIRFunction birFunc, InitMethodGen initMethodGen) { + public static void desugarInteropFuncs(JMethodBIRFunction birFunc, InitMethodGen initMethodGen) { // resetting the variable generation index BType retType = birFunc.type.retType; - if (Symbols.isFlagOn(retType.getFlags(), Flags.PARAMETERIZED)) { - retType = JvmCodeGenUtil.UNIFIER.build(typeEnv, birFunc.type.retType); + if (Symbols.isFlagOn(retType.flags, Flags.PARAMETERIZED)) { + retType = JvmCodeGenUtil.UNIFIER.build(birFunc.type.retType); } JMethod jMethod = birFunc.jMethod; Class[] jMethodParamTypes = jMethod.getParamTypes(); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/InteropValidator.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/InteropValidator.java index f20f50ef2e2a..59be56de92d3 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/InteropValidator.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/InteropValidator.java @@ -204,8 +204,7 @@ private ClassLoader makeClassLoader(Set moduleDependencies) { JMethod validateAndGetJMethod(InteropValidationRequest.MethodValidationRequest methodValidationRequest, ClassLoader classLoader) { // Populate JMethodRequest from the BValue - JMethodRequest jMethodRequest = JMethodRequest.build(symbolTable.typeEnv(), methodValidationRequest, - classLoader); + JMethodRequest jMethodRequest = JMethodRequest.build(methodValidationRequest, classLoader); // Find the most specific Java method or constructor for the given request JMethodResolver methodResolver = new JMethodResolver(classLoader, symbolTable); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/JMethodRequest.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/JMethodRequest.java index c52cd1f4ab49..dfa5278a93e8 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/JMethodRequest.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/JMethodRequest.java @@ -17,15 +17,14 @@ */ package org.wso2.ballerinalang.compiler.bir.codegen.interop; -import io.ballerina.types.Env; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemTypes; import org.ballerinalang.model.symbols.SymbolKind; import org.wso2.ballerinalang.compiler.bir.codegen.model.JMethodKind; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableTypeSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BVarSymbol; import org.wso2.ballerinalang.compiler.semantics.model.types.BInvokableType; import org.wso2.ballerinalang.compiler.semantics.model.types.BType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BUnionType; +import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.compiler.util.Unifier; import java.util.ArrayList; @@ -60,7 +59,7 @@ private JMethodRequest() { } - static JMethodRequest build(Env typeEnv, InteropValidationRequest.MethodValidationRequest methodValidationRequest, + static JMethodRequest build(InteropValidationRequest.MethodValidationRequest methodValidationRequest, ClassLoader classLoader) { JMethodRequest jMethodReq = new JMethodRequest(); @@ -95,9 +94,18 @@ static JMethodRequest build(Env typeEnv, InteropValidationRequest.MethodValidati jMethodReq.bParamTypes = paramTypes.toArray(new BType[0]); jMethodReq.pathParamSymbols = pathParams; - BType returnType = unifier.build(typeEnv, bFuncType.retType); + BType returnType = unifier.build(bFuncType.retType); jMethodReq.bReturnType = returnType; - jMethodReq.returnsBErrorType = SemTypes.containsBasicType(returnType.semType(), PredefinedType.ERROR); + if (returnType.tag == TypeTags.UNION) { + for (BType bType : ((BUnionType) returnType).getMemberTypes()) { + if (bType.tag == TypeTags.ERROR) { + jMethodReq.returnsBErrorType = true; + break; + } + } + } else { + jMethodReq.returnsBErrorType = returnType.tag == TypeTags.ERROR; + } jMethodReq.restParamExist = methodValidationRequest.restParamExist; return jMethodReq; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/JMethodResolver.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/JMethodResolver.java index 8f695617002f..3289cfa31446 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/JMethodResolver.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/JMethodResolver.java @@ -37,7 +37,6 @@ import org.wso2.ballerinalang.compiler.bir.codegen.exceptions.JInteropException; import org.wso2.ballerinalang.compiler.bir.codegen.model.JMethod; import org.wso2.ballerinalang.compiler.bir.codegen.model.JMethodKind; -import org.wso2.ballerinalang.compiler.semantics.analyzer.SemTypeHelper; import org.wso2.ballerinalang.compiler.semantics.model.SymbolTable; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BVarSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.Symbols; @@ -46,6 +45,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BType; import org.wso2.ballerinalang.compiler.semantics.model.types.BTypeReferenceType; import org.wso2.ballerinalang.compiler.semantics.model.types.BUnionType; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangExpression; import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.util.Flags; @@ -253,7 +253,7 @@ private boolean hasEquivalentFunctionParamCount(JMethodRequest jMethodRequest, J // https://github.com/ballerina-platform/ballerina-lang/issues/42456. if (jMethodRequest.receiverType == null || functionParamCount < 1 || count < reducedParamCount || count > reducedParamCount + 2 - || Symbols.isFlagOn(jMethodRequest.bParamTypes[0].getFlags(), Flags.SERVICE)) { + || Symbols.isFlagOn(jMethodRequest.bParamTypes[0].flags, Flags.SERVICE)) { return false; } if (!isParamAssignableToBArray(paramTypes[count - 1]) @@ -387,6 +387,18 @@ private void validateExceptionTypes(JMethodRequest jMethodRequest, JMethod jMeth "Incompatible ballerina return type for Java method '" + jMethodRequest.methodName + "' which " + "throws checked exception found in class '" + jMethodRequest.declaringClass.getName() + "': expected '" + expectedRetTypeName + "', found '" + returnType + "'"); + } else if (jMethodRequest.returnsBErrorType && !throwsCheckedException && !returnsErrorValue) { + String errorMsgPart; + if (returnType instanceof BUnionType bUnionReturnType) { + BType modifiedRetType = BUnionType.create(null, getNonErrorMembers(bUnionReturnType)); + errorMsgPart = "expected '" + modifiedRetType + "', found '" + returnType + "'"; + } else { + errorMsgPart = "no return type expected but found '" + returnType + "'"; + } + throw new JInteropException(DiagnosticErrorCode.METHOD_SIGNATURE_DOES_NOT_MATCH, + "Incompatible ballerina return type for Java method '" + jMethodRequest.methodName + "' which " + + "throws 'java.lang.RuntimeException' found in class '" + + jMethodRequest.declaringClass.getName() + "': " + errorMsgPart); } } @@ -395,8 +407,7 @@ private String getExpectedReturnType(BType retType) { ((BTypeReferenceType) retType).referredType.tag == TypeTags.ERROR)) { return "error"; } else if (retType instanceof BUnionType bUnionReturnType) { - BType modifiedRetType = - BUnionType.create(symbolTable.typeEnv(), null, getNonErrorMembers(bUnionReturnType)); + BType modifiedRetType = BUnionType.create(null, getNonErrorMembers(bUnionReturnType)); return modifiedRetType + "|error"; } else { return retType + "|error"; @@ -499,7 +510,7 @@ private void bundlePathParams(JMethodRequest jMethodRequest, JMethod jMethod) { for (BVarSymbol param : pathParamSymbols) { paramTypes.remove(param.type); } - paramTypes.add(initialPathParamIndex, new BArrayType(symbolTable.typeEnv(), symbolTable.anydataType)); + paramTypes.add(initialPathParamIndex, new BArrayType(symbolTable.anydataType)); jMethodRequest.bParamTypes = paramTypes.toArray(new BType[0]); jMethodRequest.bFuncParamCount = jMethodRequest.bFuncParamCount - pathParamSymbols.size() + 1; jMethodRequest.pathParamCount = 1; @@ -511,7 +522,7 @@ private void bundleFunctionParams(JMethodRequest jMethodRequest, JMethod jMethod if (jMethodRequest.bFuncParamCount > jMethodRequest.pathParamCount) { paramTypes.subList(jMethodRequest.pathParamCount, jMethodRequest.bFuncParamCount).clear(); } - paramTypes.add(new BArrayType(symbolTable.typeEnv(), symbolTable.anyType)); + paramTypes.add(new BArrayType(symbolTable.anyType)); jMethodRequest.bParamTypes = paramTypes.toArray(new BType[0]); jMethodRequest.bFuncParamCount = jMethodRequest.pathParamCount + 1; jMethod.hasBundledFunctionParams = true; @@ -519,8 +530,8 @@ private void bundleFunctionParams(JMethodRequest jMethodRequest, JMethod jMethod private void bundleBothPathAndFunctionParameter(JMethodRequest jMethodRequest, JMethod jMethod) { List paramTypes = new ArrayList<>(); - paramTypes.add(new BArrayType(symbolTable.typeEnv(), symbolTable.anydataType)); - paramTypes.add(new BArrayType(symbolTable.typeEnv(), symbolTable.anyType)); + paramTypes.add(new BArrayType(symbolTable.anydataType)); + paramTypes.add(new BArrayType(symbolTable.anyType)); jMethodRequest.bParamTypes = paramTypes.toArray(new BType[0]); jMethodRequest.bFuncParamCount = 2; jMethodRequest.pathParamCount = 1; @@ -629,8 +640,9 @@ private boolean isInvalidParamBType(Class jType, BType bType, boolean isLastP if (jTypeName.equals(J_OBJECT_TNAME)) { return false; } - for (BType t : SemTypeHelper.broadTypes((BFiniteType) bType, symbolTable)) { - if (isInvalidParamBType(jType, t, isLastParam, restParamExist)) { + Set valueSpace = ((BFiniteType) bType).getValueSpace(); + for (BLangExpression value : valueSpace) { + if (isInvalidParamBType(jType, value.getBType(), isLastParam, restParamExist)) { return true; } } @@ -783,8 +795,9 @@ private boolean isValidReturnBType(Class jType, BType bType, JMethodRequest j if (jTypeName.equals(J_OBJECT_TNAME)) { return true; } - for (BType t : SemTypeHelper.broadTypes((BFiniteType) bType, symbolTable)) { - if (isValidReturnBType(jType, t, jMethodRequest, visitedSet)) { + Set valueSpace = ((BFiniteType) bType).getValueSpace(); + for (BLangExpression value : valueSpace) { + if (isValidReturnBType(jType, value.getBType(), jMethodRequest, visitedSet)) { return true; } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/methodgen/InitMethodGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/methodgen/InitMethodGen.java index 2dd4a90d648c..95692b46bd37 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/methodgen/InitMethodGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/methodgen/InitMethodGen.java @@ -131,8 +131,7 @@ public class InitMethodGen { public InitMethodGen(SymbolTable symbolTable) { this.symbolTable = symbolTable; - this.errorOrNilType = - BUnionType.create(symbolTable.typeEnv(), null, symbolTable.errorType, symbolTable.nilType); + this.errorOrNilType = BUnionType.create(null, symbolTable.errorType, symbolTable.nilType); } /** @@ -186,7 +185,7 @@ public void generateLambdaForModuleExecuteFunction(ClassWriter cw, String initCl jvmCastGen.addUnboxInsn(mv, paramType); paramIndex += 1; } - methodDesc = JvmCodeGenUtil.getMethodDesc(symbolTable.typeEnv(), paramTypes, returnType); + methodDesc = JvmCodeGenUtil.getMethodDesc(paramTypes, returnType); } mv.visitMethodInsn(INVOKESTATIC, initClass, MODULE_EXECUTE_METHOD, methodDesc, false); @@ -332,21 +331,21 @@ public void enrichPkgWithInitializers(Map birFunctio javaClass.functions.add(initFunc); pkg.functions.add(initFunc); birFunctionMap.put(JvmCodeGenUtil.getPackageName(pkg.packageID) + MODULE_INIT_METHOD, - JvmPackageGen.getFunctionWrapper(symbolTable.typeEnv(), initFunc, pkg.packageID, typeOwnerClass)); + JvmPackageGen.getFunctionWrapper(initFunc, pkg.packageID, typeOwnerClass)); BIRNode.BIRFunction startFunc = generateDefaultFunction(moduleImports, pkg, MODULE_START_METHOD, MethodGenUtils.START_FUNCTION_SUFFIX); javaClass.functions.add(startFunc); pkg.functions.add(startFunc); birFunctionMap.put(JvmCodeGenUtil.getPackageName(pkg.packageID) + MODULE_START_METHOD, - JvmPackageGen.getFunctionWrapper(symbolTable.typeEnv(), startFunc, pkg.packageID, typeOwnerClass)); + JvmPackageGen.getFunctionWrapper(startFunc, pkg.packageID, typeOwnerClass)); BIRNode.BIRFunction execFunc = generateExecuteFunction(pkg, mainFunc, testExecuteFunc ); javaClass.functions.add(execFunc); pkg.functions.add(execFunc); birFunctionMap.put(JvmCodeGenUtil.getPackageName(pkg.packageID) + MODULE_EXECUTE_METHOD, - JvmPackageGen.getFunctionWrapper(symbolTable.typeEnv(), execFunc, pkg.packageID, typeOwnerClass)); + JvmPackageGen.getFunctionWrapper(execFunc, pkg.packageID, typeOwnerClass)); } private BIRNode.BIRFunction generateExecuteFunction(BIRNode.BIRPackage pkg, @@ -356,8 +355,7 @@ private BIRNode.BIRFunction generateExecuteFunction(BIRNode.BIRPackage pkg, new Name("%ret"), VarScope.FUNCTION, VarKind.RETURN, null); BIROperand retVarRef = new BIROperand(retVar); List functionArgs = new ArrayList<>(); - BInvokableType funcType = - new BInvokableType(symbolTable.typeEnv(), Collections.emptyList(), null, errorOrNilType, null); + BInvokableType funcType = new BInvokableType(Collections.emptyList(), null, errorOrNilType, null); BIRNode.BIRFunction modExecFunc = new BIRNode.BIRFunction(null, new Name(MODULE_EXECUTE_METHOD), 0, funcType, null, 0, VIRTUAL); List paramTypes = new ArrayList<>(); @@ -513,8 +511,7 @@ private BIRNode.BIRFunction generateDefaultFunction(Set imprtMods, BI VarScope.FUNCTION, VarKind.RETURN, null); BIROperand retVarRef = new BIROperand(retVar); - BInvokableType funcType = - new BInvokableType(symbolTable.typeEnv(), Collections.emptyList(), null, errorOrNilType, null); + BInvokableType funcType = new BInvokableType(Collections.emptyList(), null, errorOrNilType, null); BIRNode.BIRFunction modInitFunc = new BIRNode.BIRFunction(symbolTable.builtinPos, new Name(funcName), 0, funcType, null, 0, VIRTUAL); modInitFunc.localVars.add(retVar); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/methodgen/LambdaGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/methodgen/LambdaGen.java index bf4aa7156b97..c20f64b0449d 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/methodgen/LambdaGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/methodgen/LambdaGen.java @@ -457,7 +457,7 @@ private String getLambdaMethodDesc(List paramTypes, BType retType, int cl StringBuilder desc = new StringBuilder(INITIAL_METHOD_DESC); appendClosureMaps(closureMapsCount, desc); appendParamTypes(paramTypes, desc); - desc.append(JvmCodeGenUtil.generateReturnType(retType, jvmCastGen.typeEnv())); + desc.append(JvmCodeGenUtil.generateReturnType(retType)); return desc.toString(); } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/methodgen/MethodGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/methodgen/MethodGen.java index d4ab30941346..fd6d717c40fc 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/methodgen/MethodGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/methodgen/MethodGen.java @@ -19,7 +19,6 @@ package org.wso2.ballerinalang.compiler.bir.codegen.methodgen; import io.ballerina.identifier.Utils; -import io.ballerina.types.Env; import org.ballerinalang.compiler.BLangCompilerException; import org.ballerinalang.model.elements.PackageID; import org.objectweb.asm.ClassWriter; @@ -148,13 +147,11 @@ public class MethodGen { private final JvmPackageGen jvmPackageGen; private final SymbolTable symbolTable; private final Types types; - private final Env typeEnv; public MethodGen(JvmPackageGen jvmPackageGen, Types types) { this.jvmPackageGen = jvmPackageGen; this.symbolTable = jvmPackageGen.symbolTable; this.types = types; - this.typeEnv = types.typeEnv(); } public void generateMethod(BIRFunction birFunc, ClassWriter cw, BIRPackage birModule, BType attachedType, @@ -180,7 +177,7 @@ public void genJMethodWithBObjectMethodCall(BIRFunction func, ClassWriter cw, BI indexMap.addIfNotExists(STRAND, symbolTable.stringType); String funcName = func.name.value; BType retType = getReturnType(func); - String desc = JvmCodeGenUtil.getMethodDesc(typeEnv, func.type.paramTypes, retType); + String desc = JvmCodeGenUtil.getMethodDesc(func.type.paramTypes, retType); MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, funcName, desc, null, null); mv.visitCode(); Label methodStartLabel = new Label(); @@ -193,7 +190,7 @@ public void genJMethodWithBObjectMethodCall(BIRFunction func, ClassWriter cw, BI for (BIRNode.BIRFunctionParameter parameter : func.parameters) { instGen.generateVarLoad(mv, parameter, indexMap.addIfNotExists(parameter.name.value, parameter.type)); } - String methodDesc = JvmCodeGenUtil.getMethodDesc(typeEnv, func.type.paramTypes, retType, moduleClassName); + String methodDesc = JvmCodeGenUtil.getMethodDesc(func.type.paramTypes, retType, moduleClassName); mv.visitMethodInsn(INVOKESTATIC, splitClassName, encodedMethodName, methodDesc, false); Label methodEndLabel = new Label(); mv.visitLabel(methodEndLabel); @@ -251,9 +248,9 @@ public void genJMethodForBFunc(BIRFunction func, ClassWriter cw, BIRPackage modu BType retType = getReturnType(func); String desc; if (isObjectMethodSplit) { - desc = JvmCodeGenUtil.getMethodDesc(typeEnv, func.type.paramTypes, retType, moduleClassName); + desc = JvmCodeGenUtil.getMethodDesc(func.type.paramTypes, retType, moduleClassName); } else { - desc = JvmCodeGenUtil.getMethodDesc(typeEnv, func.type.paramTypes, retType); + desc = JvmCodeGenUtil.getMethodDesc(func.type.paramTypes, retType); } MethodVisitor mv = cw.visitMethod(access, funcName, desc, null, null); mv.visitCode(); @@ -339,8 +336,8 @@ private void handleParentModuleStart(MethodVisitor mv, PackageID packageID, Stri private BType getReturnType(BIRFunction func) { BType retType = func.type.retType; - if (JvmCodeGenUtil.isExternFunc(func) && Symbols.isFlagOn(retType.getFlags(), Flags.PARAMETERIZED)) { - retType = JvmCodeGenUtil.UNIFIER.build(typeEnv, func.type.retType); + if (JvmCodeGenUtil.isExternFunc(func) && Symbols.isFlagOn(retType.flags, Flags.PARAMETERIZED)) { + retType = JvmCodeGenUtil.UNIFIER.build(func.type.retType); } return retType; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/methodgen/ModuleStopMethodGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/methodgen/ModuleStopMethodGen.java index 9789ce923cc1..4ce3e4d86dd5 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/methodgen/ModuleStopMethodGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/methodgen/ModuleStopMethodGen.java @@ -28,7 +28,7 @@ import org.wso2.ballerinalang.compiler.bir.codegen.internal.AsyncDataCollector; import org.wso2.ballerinalang.compiler.bir.codegen.split.JvmConstantsGen; import org.wso2.ballerinalang.compiler.bir.model.BIRNode; -import org.wso2.ballerinalang.compiler.semantics.model.types.BType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BNilType; import java.util.Set; @@ -120,7 +120,7 @@ private void generateMethodBody(MethodVisitor mv, String initClass, String stopF JvmCodeGenUtil.createFunctionPointer(mv, initClass, stopFuncName); // no parent strand mv.visitInsn(ACONST_NULL); - jvmTypeGen.loadType(mv, BType.createNilType()); + jvmTypeGen.loadType(mv, new BNilType()); mv.visitLdcInsn("stop"); mv.visitInsn(ACONST_NULL); mv.visitIntInsn(BIPUSH, 1); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/optimizer/LargeMethodOptimizer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/optimizer/LargeMethodOptimizer.java index 52c0079e930a..579e108d25eb 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/optimizer/LargeMethodOptimizer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/optimizer/LargeMethodOptimizer.java @@ -800,7 +800,7 @@ private void createNewFuncForPeriodicSplit(BIRFunction parentFunc, List memberTypes = new LinkedHashSet<>(2); memberTypes.add(newFuncReturnType); memberTypes.add(symbolTable.errorType); - return new BUnionType(symbolTable.typeEnv(), null, memberTypes, false); + return new BUnionType(null, memberTypes, false, false); } private BIRBasicBlock handleNewFuncReturnVal(BIRFunction function, BIROperand splitFuncCallResultOp, @@ -1666,7 +1666,7 @@ private BIRFunction createNewBIRFunctionAcrossBB(BIRFunction parentFunc, Name fu for (BIRVariableDcl funcArg : currSplit.funcArgs) { paramTypes.add(funcArg.type); } - BInvokableType type = new BInvokableType(symbolTable.typeEnv(), paramTypes, retType, null); + BInvokableType type = new BInvokableType(paramTypes, retType, null); BIRFunction birFunc = new BIRFunction(null, funcName, funcName, 0, type, DEFAULT_WORKER_NAME, 0, SymbolOrigin.VIRTUAL); @@ -1869,7 +1869,7 @@ private BIRFunction createNewBIRFuncForSplitInBB(Name funcName, BIRNonTerminator for (BIRVariableDcl funcArg : funcArgs) { paramTypes.add(funcArg.type); } - BInvokableType type = new BInvokableType(symbolTable.typeEnv(), paramTypes, retType, null); + BInvokableType type = new BInvokableType(paramTypes, retType, null); BIRFunction birFunc = new BIRFunction(null, funcName, funcName, 0, type, DEFAULT_WORKER_NAME, 0, SymbolOrigin.VIRTUAL); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/JvmAnnotationsGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/JvmAnnotationsGen.java index e2cda9df5aa3..fb1305081f4e 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/JvmAnnotationsGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/JvmAnnotationsGen.java @@ -28,7 +28,6 @@ import org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures; import org.wso2.ballerinalang.compiler.bir.codegen.JvmTypeGen; import org.wso2.ballerinalang.compiler.bir.model.BIRNode; -import org.wso2.ballerinalang.compiler.semantics.model.symbols.Symbols; import org.wso2.ballerinalang.compiler.semantics.model.types.BType; import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.util.Flags; @@ -110,7 +109,7 @@ private int generateAnnotationsLoad(ClassWriter cw, List typeDefSet = new TreeSet<>(typeDefHashComparator); for (BIRTypeDefinition t : typeDefinitions) { - if (Symbols.isFlagOn(t.type.getFlags(), Flags.ANONYMOUS)) { + if (Symbols.isFlagOn(t.type.flags, Flags.ANONYMOUS)) { typeDefSet.add(t); } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/types/JvmArrayTypeGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/types/JvmArrayTypeGen.java index cc67203f438c..f9e6631c66f9 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/types/JvmArrayTypeGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/types/JvmArrayTypeGen.java @@ -84,7 +84,7 @@ public void createArrayType(MethodVisitor mv, BArrayType arrayType, Types types) if (TypeTags.isSimpleBasicType(arrayType.eType.tag)) { // Load the element type jvmTypeGen.loadType(mv, arrayType.eType); - int arraySize = arrayType.getSize(); + int arraySize = arrayType.size; mv.visitLdcInsn((long) arraySize); mv.visitInsn(L2I); @@ -96,7 +96,7 @@ public void createArrayType(MethodVisitor mv, BArrayType arrayType, Types types) mv.visitLdcInsn(jvmTypeGen.typeFlag(arrayType.eType)); - int arraySize = arrayType.getSize(); + int arraySize = arrayType.size; mv.visitLdcInsn((long) arraySize); mv.visitInsn(L2I); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/types/JvmUnionTypeGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/types/JvmUnionTypeGen.java index 4c3bc12bcadb..27aa4abfa6d7 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/types/JvmUnionTypeGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/types/JvmUnionTypeGen.java @@ -109,7 +109,7 @@ public void createUnionType(MethodVisitor mv, BUnionType unionType) { jvmTypeGen.loadCyclicFlag(mv, unionType); - mv.visitLdcInsn(unionType.getFlags()); + mv.visitLdcInsn(unionType.flags); // initialize the union type without the members array if (nameLoaded) { mv.visitMethodInsn(INVOKESPECIAL, UNION_TYPE_IMPL, JVM_INIT_METHOD, diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/values/JvmObjectGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/values/JvmObjectGen.java index a87a368ecd65..de5e9592c1c2 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/values/JvmObjectGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/split/values/JvmObjectGen.java @@ -126,7 +126,7 @@ public void createAndSplitCallMethod(ClassWriter cw, List f String methodSig; // use index access, since retType can be nil. - methodSig = JvmCodeGenUtil.getMethodDesc(jvmCastGen.typeEnv(), paramTypes, retType); + methodSig = JvmCodeGenUtil.getMethodDesc(paramTypes, retType); // load self mv.visitVarInsn(ALOAD, 0); @@ -197,8 +197,8 @@ public void createAndSplitCallMethod(ClassWriter cw, List f } private boolean isListenerAttach(BIRNode.BIRFunction func) { - return func.name.value.equals("attach") && - Symbols.isFlagOn(func.parameters.getFirst().type.getFlags(), Flags.SERVICE); + return func.name.value.equals("attach") && Symbols.isFlagOn(func.parameters.getFirst().type.flags, + Flags.SERVICE); } public void createAndSplitGetMethod(ClassWriter cw, Map fields, String className, diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/emit/TypeEmitter.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/emit/TypeEmitter.java index d8090ed0d1fb..c1f634476a63 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/emit/TypeEmitter.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/emit/TypeEmitter.java @@ -126,7 +126,7 @@ private static String emitParameterizedType(BParameterizedType type, int tabs) { } private static String emitTableType(BTableType bType, int tabs) { - boolean readonly = Symbols.isFlagOn(bType.getFlags(), Flags.READONLY); + boolean readonly = Symbols.isFlagOn(bType.flags, Flags.READONLY); if (bType.constraint == null) { return readonly ? bType.toString().concat(" & readonly") : bType.toString(); } @@ -240,8 +240,8 @@ private static String emitBInvokableType(BInvokableType bType, int tabs) { private static String emitBArrayType(BArrayType bType, int tabs) { String arrStr = emitTypeRef(bType.eType, 0); arrStr += "["; - if (bType.getSize() > 0) { - arrStr += bType.getSize(); + if (bType.size > 0) { + arrStr += bType.size; } arrStr += "]"; return arrStr; @@ -256,7 +256,7 @@ private static String emitBRecordType(BRecordType bType, int tabs) { for (BField bField : bType.fields.values()) { if (bField != null) { recordStr.append(emitTabs(tabs + 1)); - String flags = emitFlags(bField.type.getFlags()); + String flags = emitFlags(bField.type.flags); recordStr.append(flags); if (!flags.isEmpty()) { recordStr.append(emitSpaces(1)); @@ -273,7 +273,7 @@ private static String emitBRecordType(BRecordType bType, int tabs) { } private static String emitBObjectType(BObjectType bType, int tabs) { - boolean isService = Symbols.isFlagOn(bType.getFlags(), Flags.SERVICE); + boolean isService = (bType.flags & Flags.SERVICE) == Flags.SERVICE; StringBuilder str = new StringBuilder(); str.append(isService ? "service object" : "object"); @@ -283,7 +283,7 @@ private static String emitBObjectType(BObjectType bType, int tabs) { for (BField bField : bType.fields.values()) { if (bField != null) { str.append(emitTabs(tabs + 1)); - String flags = emitFlags(bField.type.getFlags()); + String flags = emitFlags(bField.type.flags); str.append(flags); if (!flags.isEmpty()) { str.append(emitSpaces(1)); @@ -366,7 +366,21 @@ private static String emitBTypeDesc(BTypedescType bType, int tabs) { } private static String emitBFiniteType(BFiniteType bType, int tabs) { - return "[" + bType.toString() + "]"; + + StringBuilder str = new StringBuilder(); + str.append("["); + int i = 0; + int length = bType.getValueSpace().size(); + for (Object v : bType.getValueSpace()) { + str.append(v.toString()); + i += 1; + if (i < length) { + str.append(","); + str.append(emitSpaces(1)); + } + } + str.append("]"); + return str.toString(); } private static String emitBTypeHandle(BHandleType bType, int tabs) { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRBinaryWriter.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRBinaryWriter.java index 85d5593465c8..8df6c69efb68 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRBinaryWriter.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRBinaryWriter.java @@ -18,7 +18,6 @@ package org.wso2.ballerinalang.compiler.bir.writer; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.Env; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import org.ballerinalang.compiler.BLangCompilerException; @@ -50,19 +49,16 @@ */ public class BIRBinaryWriter { - private final ConstantPool cp; + private final ConstantPool cp = new ConstantPool(); private final BIRNode.BIRPackage birPackage; - private final Env typeEnv; - public BIRBinaryWriter(BIRNode.BIRPackage birPackage, Env typeEnv) { + public BIRBinaryWriter(BIRNode.BIRPackage birPackage) { this.birPackage = birPackage; - this.typeEnv = typeEnv; - cp = new ConstantPool(typeEnv); } public byte[] serialize() { ByteBuf birbuf = Unpooled.buffer(); - BIRTypeWriter typeWriter = new BIRTypeWriter(birbuf, cp, typeEnv); + BIRTypeWriter typeWriter = new BIRTypeWriter(birbuf, cp); // Write the package details in the form of constant pool entry @@ -395,7 +391,7 @@ private void writeAnnotation(ByteBuf buf, BIRTypeWriter typeWriter, BIRNode.BIRA } private void writeConstants(ByteBuf buf, List birConstList) { - BIRTypeWriter constTypeWriter = new BIRTypeWriter(buf, cp, typeEnv); + BIRTypeWriter constTypeWriter = new BIRTypeWriter(buf, cp); buf.writeInt(birConstList.size()); birConstList.forEach(constant -> writeConstant(buf, constTypeWriter, constant)); } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRTypeWriter.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRTypeWriter.java index 27beec2068be..c429eba1ff33 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRTypeWriter.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRTypeWriter.java @@ -17,43 +17,17 @@ */ package org.wso2.ballerinalang.compiler.bir.writer; -import io.ballerina.types.Atom; -import io.ballerina.types.AtomicType; -import io.ballerina.types.BasicTypeBitSet; -import io.ballerina.types.Bdd; -import io.ballerina.types.CellAtomicType; -import io.ballerina.types.CellSemType; -import io.ballerina.types.ComplexSemType; -import io.ballerina.types.EnumerableCharString; -import io.ballerina.types.EnumerableDecimal; -import io.ballerina.types.EnumerableFloat; -import io.ballerina.types.EnumerableString; -import io.ballerina.types.Env; -import io.ballerina.types.FixedLengthArray; -import io.ballerina.types.FunctionAtomicType; -import io.ballerina.types.ListAtomicType; -import io.ballerina.types.MappingAtomicType; -import io.ballerina.types.PredefinedTypeEnv; -import io.ballerina.types.ProperSubtypeData; -import io.ballerina.types.RecAtom; -import io.ballerina.types.SemType; -import io.ballerina.types.TypeAtom; -import io.ballerina.types.subtypedata.BddAllOrNothing; -import io.ballerina.types.subtypedata.BddNode; -import io.ballerina.types.subtypedata.BooleanSubtype; -import io.ballerina.types.subtypedata.CharStringSubtype; -import io.ballerina.types.subtypedata.DecimalSubtype; -import io.ballerina.types.subtypedata.FloatSubtype; -import io.ballerina.types.subtypedata.IntSubtype; -import io.ballerina.types.subtypedata.NonCharStringSubtype; -import io.ballerina.types.subtypedata.Range; -import io.ballerina.types.subtypedata.StringSubtype; -import io.ballerina.types.subtypedata.XmlSubtype; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import org.ballerinalang.model.elements.MarkdownDocAttachment; import org.ballerinalang.model.symbols.SymbolKind; +import org.wso2.ballerinalang.compiler.bir.writer.CPEntry.ByteCPEntry; +import org.wso2.ballerinalang.compiler.bir.writer.CPEntry.FloatCPEntry; +import org.wso2.ballerinalang.compiler.bir.writer.CPEntry.IntegerCPEntry; import org.wso2.ballerinalang.compiler.bir.writer.CPEntry.StringCPEntry; +import org.wso2.ballerinalang.compiler.semantics.analyzer.IsAnydataUniqueVisitor; +import org.wso2.ballerinalang.compiler.semantics.analyzer.IsPureTypeUniqueVisitor; +import org.wso2.ballerinalang.compiler.semantics.analyzer.Types; import org.wso2.ballerinalang.compiler.semantics.model.TypeVisitor; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BAttachedFunction; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BConstantSymbol; @@ -71,6 +45,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BAnyType; import org.wso2.ballerinalang.compiler.semantics.model.types.BAnydataType; import org.wso2.ballerinalang.compiler.semantics.model.types.BArrayType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BBuiltInRefType; import org.wso2.ballerinalang.compiler.semantics.model.types.BErrorType; import org.wso2.ballerinalang.compiler.semantics.model.types.BField; import org.wso2.ballerinalang.compiler.semantics.model.types.BFiniteType; @@ -81,6 +56,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BJSONType; import org.wso2.ballerinalang.compiler.semantics.model.types.BMapType; import org.wso2.ballerinalang.compiler.semantics.model.types.BNeverType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BNilType; import org.wso2.ballerinalang.compiler.semantics.model.types.BNoType; import org.wso2.ballerinalang.compiler.semantics.model.types.BObjectType; import org.wso2.ballerinalang.compiler.semantics.model.types.BPackageType; @@ -97,12 +73,13 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BTypedescType; import org.wso2.ballerinalang.compiler.semantics.model.types.BUnionType; import org.wso2.ballerinalang.compiler.semantics.model.types.BXMLType; -import org.wso2.ballerinalang.compiler.semantics.model.types.SemNamedType; +import org.wso2.ballerinalang.compiler.semantics.model.types.TypeFlags; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangExpression; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral; +import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.util.Flags; -import java.math.BigDecimal; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; @@ -112,27 +89,29 @@ /** * Writes bType to a Byte Buffer in binary format. * A ConstPool is used to store string typed information. - * + * * @since 0.995.0 */ -public class BIRTypeWriter extends TypeVisitor { +public class BIRTypeWriter implements TypeVisitor { private final ByteBuf buff; private final ConstantPool cp; - private final Set visitedAtoms = new HashSet<>(); - private final Env typeEnv; - private final PredefinedTypeEnv predefinedTypeEnv = PredefinedTypeEnv.getInstance(); + private static final IsPureTypeUniqueVisitor isPureTypeUniqueVisitor = new IsPureTypeUniqueVisitor(); + private static final IsAnydataUniqueVisitor isAnydataUniqueVisitor = new IsAnydataUniqueVisitor(); - public BIRTypeWriter(ByteBuf buff, ConstantPool cp, Env typeEnv) { + public BIRTypeWriter(ByteBuf buff, ConstantPool cp) { this.buff = buff; this.cp = cp; - this.typeEnv = typeEnv; } public void visitType(BType type) { buff.writeByte(type.tag); buff.writeInt(addStringCPEntry(type.name.getValue())); - buff.writeLong(type.getFlags()); + buff.writeLong(type.flags); + isPureTypeUniqueVisitor.reset(); + isAnydataUniqueVisitor.reset(); + buff.writeInt(TypeFlags.asMask(type.isNullable(), isAnydataUniqueVisitor.visit(type), + isPureTypeUniqueVisitor.visit(type))); type.accept(this); } @@ -148,10 +127,15 @@ public void visit(BAnnotationType bAnnotationType) { @Override public void visit(BArrayType bArrayType) { buff.writeByte(bArrayType.state.getValue()); - buff.writeInt(bArrayType.getSize()); + buff.writeInt(bArrayType.size); writeTypeCpIndex(bArrayType.getElementType()); } + @Override + public void visit(BBuiltInRefType bBuiltInRefType) { + throwUnimplementedError(bBuiltInRefType); + } + @Override public void visit(BAnyType bAnyType) { } @@ -190,15 +174,20 @@ public void visit(BFiniteType bFiniteType) { BTypeSymbol tsymbol = bFiniteType.tsymbol; buff.writeInt(addStringCPEntry(tsymbol.name.value)); buff.writeLong(tsymbol.flags); - buff.writeInt(bFiniteType.valueSpace.length); - for (SemNamedType semNamedType:bFiniteType.valueSpace) { - writeSemNamedType(semNamedType); + buff.writeInt(bFiniteType.getValueSpace().size()); + for (BLangExpression valueLiteral : bFiniteType.getValueSpace()) { + if (!(valueLiteral instanceof BLangLiteral bLangLiteral)) { + throw new AssertionError( + "Type serialization is not implemented for finite type with value: " + valueLiteral.getKind()); + } + writeTypeCpIndex(valueLiteral.getBType()); + writeValue(bLangLiteral.value, valueLiteral.getBType()); } } @Override public void visit(BInvokableType bInvokableType) { - boolean isAnyFunction = Symbols.isFlagOn(bInvokableType.getFlags(), Flags.ANY_FUNCTION); + boolean isAnyFunction = Symbols.isFlagOn(bInvokableType.flags, Flags.ANY_FUNCTION); buff.writeBoolean(isAnyFunction); // write 1 if it’s an any function if not write 0 if (isAnyFunction) { @@ -316,7 +305,7 @@ public void visit(BNeverType bNeverType) { } @Override - public void visitNilType(BType bType) { + public void visit(BNilType bNilType) { // Nothing to do } @@ -505,6 +494,11 @@ private void writeAttachFunction(BAttachedFunction attachedFunc) { writeTypeCpIndex(attachedFunc.type); } + @Override + public void visit(BType bType) { + // Nothing to do + } + @Override public void visit(BXMLType bxmlType) { writeTypeCpIndex(bxmlType.constraint); @@ -568,251 +562,63 @@ private int addStringCPEntry(String value) { return cp.addCPEntry(new StringCPEntry(value)); } + private int addIntCPEntry(long value) { + return cp.addCPEntry(new IntegerCPEntry(value)); + } + + private int addFloatCPEntry(double value) { + return cp.addCPEntry(new FloatCPEntry(value)); + } + + private int addByteCPEntry(int value) { + return cp.addCPEntry(new ByteCPEntry(value)); + } + + private void writeValue(Object value, BType typeOfValue) { + ByteBuf byteBuf = Unpooled.buffer(); + switch (Types.getImpliedType(typeOfValue).tag) { + case TypeTags.INT: + case TypeTags.SIGNED32_INT: + case TypeTags.SIGNED16_INT: + case TypeTags.SIGNED8_INT: + case TypeTags.UNSIGNED32_INT: + case TypeTags.UNSIGNED16_INT: + case TypeTags.UNSIGNED8_INT: + byteBuf.writeInt(addIntCPEntry((Long) value)); + break; + case TypeTags.BYTE: + int byteValue = ((Number) value).intValue(); + byteBuf.writeInt(addByteCPEntry(byteValue)); + break; + case TypeTags.FLOAT: + // TODO:Remove the instanceof check by converting the float literal instance in Semantic analysis phase + double doubleVal = + value instanceof String ? Double.parseDouble((String) value) : ((Number) value).doubleValue(); + byteBuf.writeInt(addFloatCPEntry(doubleVal)); + break; + case TypeTags.STRING: + case TypeTags.CHAR_STRING: + case TypeTags.DECIMAL: + byteBuf.writeInt(addStringCPEntry(String.valueOf(value))); + break; + case TypeTags.BOOLEAN: + byteBuf.writeBoolean((Boolean) value); + break; + case TypeTags.NIL: + break; + default: + throw new UnsupportedOperationException("finite type value is not supported for type: " + typeOfValue); + } + + int length = byteBuf.nioBuffer().limit(); + buff.writeInt(length); + buff.writeBytes(byteBuf.nioBuffer().array(), 0, length); + } + private void writeTypeInclusions(List inclusions) { buff.writeInt(inclusions.size()); for (BType inclusion : inclusions) { writeTypeCpIndex(inclusion); } } - - private void writeNullableString(String nullableString) { - boolean hasNonNullString = nullableString != null; - buff.writeBoolean(hasNonNullString); - if (hasNonNullString) { - buff.writeInt(addStringCPEntry(nullableString)); - } - } - - private void writeSemNamedType(SemNamedType semNamedType) { - writeSemType(semNamedType.semType()); - writeNullableString(semNamedType.optName().orElse(null)); - } - - // --------------------------------------- Writing SemType ---------------------------------------------- - - private void writeSemType(SemType semType) { - boolean hasSemType = semType != null; - buff.writeBoolean(hasSemType); - if (!hasSemType) { - return; - } - - boolean isUniformTypeBitSet = semType instanceof BasicTypeBitSet; - buff.writeBoolean(isUniformTypeBitSet); - - buff.writeInt(semType.all()); - if (isUniformTypeBitSet) { - return; - } - - ComplexSemType complexSemType = (ComplexSemType) semType; - buff.writeInt(complexSemType.some()); - - ProperSubtypeData[] subtypeDataList = complexSemType.subtypeDataList(); - buff.writeByte(subtypeDataList.length); - for (ProperSubtypeData psd : subtypeDataList) { - writeProperSubtypeData(psd); - } - } - - private void writeProperSubtypeData(ProperSubtypeData psd) { - if (psd instanceof Bdd bdd) { - buff.writeByte(1); - writeBdd(bdd); - } else if (psd instanceof IntSubtype intSubtype) { - buff.writeByte(2); - writeIntSubtype(intSubtype); - } else if (psd instanceof BooleanSubtype booleanSubtype) { - buff.writeByte(3); - buff.writeBoolean(booleanSubtype.value); - } else if (psd instanceof FloatSubtype floatSubtype) { - buff.writeByte(4); - writeFloatSubtype(floatSubtype); - } else if (psd instanceof DecimalSubtype decimalSubtype) { - buff.writeByte(5); - writeDecimalSubtype(decimalSubtype); - } else if (psd instanceof StringSubtype stringSubtype) { - buff.writeByte(6); - writeStringSubtype(stringSubtype); - } else if (psd instanceof XmlSubtype xmlSubtype) { - buff.writeByte(7); - buff.writeInt(xmlSubtype.primitives); - writeBdd(xmlSubtype.sequence); - } else { - throw new IllegalStateException("Unknown ProperSubtypeData"); - } - } - - private void writeBdd(Bdd bdd) { - buff.writeBoolean(bdd instanceof BddNode); - if (bdd instanceof BddNode bddNode) { - writeBddNode(bddNode); - } else { - BddAllOrNothing bddAllOrNothing = (BddAllOrNothing) bdd; - buff.writeBoolean(bddAllOrNothing.isAll()); - } - } - - private static final byte REC_ATOM_KIND = 0; - private static final byte INLINED_ATOM_KIND = 1; - private static final byte TYPE_ATOM_KIND = 2; - - private void writeBddNode(BddNode bddNode) { - Atom atom = bddNode.atom(); - if (atom instanceof RecAtom recAtom) { - writeRecAtom(recAtom); - } else { - buff.writeByte(TYPE_ATOM_KIND); - TypeAtom typeAtom = (TypeAtom) atom; - visitedAtoms.add(typeAtom.getIdentifier()); - writeTypeAtom(typeAtom); - } - writeBdd(bddNode.left()); - writeBdd(bddNode.middle()); - writeBdd(bddNode.right()); - } - - private void writeRecAtom(RecAtom recAtom) { - if (shouldInline(recAtom)) { - writeInlinedRecAtom(recAtom); - } else { - buff.writeByte(REC_ATOM_KIND); - int index = typeEnv.compactRecIndex(recAtom); - buff.writeInt(index); - if (!predefinedTypeEnv.isPredefinedRecAtom(index)) { - buff.writeInt(recAtom.kind().ordinal()); - } - } - } - - private void writeInlinedRecAtom(RecAtom recAtom) { - visitedAtoms.add(recAtom.getIdentifier()); - buff.writeByte(INLINED_ATOM_KIND); - buff.writeInt(typeEnv.compactRecIndex(recAtom)); - TypeAtom typeAtom = switch (recAtom.kind()) { - case LIST_ATOM -> typeEnv.listAtom(typeEnv.listAtomType(recAtom)); - case FUNCTION_ATOM -> typeEnv.functionAtom(typeEnv.functionAtomType(recAtom)); - case MAPPING_ATOM -> typeEnv.mappingAtom(typeEnv.mappingAtomType(recAtom)); - case XML_ATOM, DISTINCT_ATOM -> - throw new IllegalStateException("Should not happen. Handled before reaching here"); - case CELL_ATOM -> throw new IllegalStateException("Cell atom cannot be recursive"); - }; - writeTypeAtom(typeAtom); - } - - private boolean shouldInline(RecAtom recAtom) { - // We can have cases where none of the BDDs have the actual BDD node in them just reference to it using - // RecAtoms. But when we deserialize the nodes we need to get the actual BDD node somehow. Currently, we - // "inline" the actual node first time we see it in the tree. Exceptions to this rule are predefined rec atoms - // which are unique and every environment has the same atoms and XML atoms - if (predefinedTypeEnv.isPredefinedRecAtom(recAtom.index) || recAtom.kind() == Atom.Kind.XML_ATOM || - recAtom.kind() == Atom.Kind.DISTINCT_ATOM) { - return false; - } - return !visitedAtoms.contains(recAtom.getIdentifier()); - } - - private void writeTypeAtom(TypeAtom typeAtom) { - buff.writeInt(typeAtom.index()); - writeAtomicType(typeAtom.atomicType()); - } - - private void writeAtomicType(AtomicType atomicType) { - if (atomicType instanceof MappingAtomicType mappingAtomicType) { - buff.writeByte(1); - writeMappingAtomicType(mappingAtomicType); - } else if (atomicType instanceof ListAtomicType listAtomicType) { - buff.writeByte(2); - writeListAtomicType(listAtomicType); - } else if (atomicType instanceof FunctionAtomicType functionAtomicType) { - buff.writeByte(3); - writeFunctionAtomicType(functionAtomicType); - } else if (atomicType instanceof CellAtomicType cellAtomicType) { - buff.writeByte(4); - writeSemType(cellAtomicType.ty()); - buff.writeByte(cellAtomicType.mut().ordinal()); - } else { - throw new UnsupportedOperationException("Unexpected atomic type " + atomicType); - } - } - - private void writeFunctionAtomicType(FunctionAtomicType functionAtomicType) { - writeSemType(functionAtomicType.paramType()); - writeSemType(functionAtomicType.retType()); - writeSemType(functionAtomicType.qualifiers()); - buff.writeBoolean(functionAtomicType.isGeneric()); - } - - private void writeMappingAtomicType(MappingAtomicType mat) { - String[] names = mat.names(); - buff.writeInt(names.length); - for (String name : names) { - buff.writeInt(addStringCPEntry(name)); - } - CellSemType[] types = mat.types(); - buff.writeInt(types.length); - for (CellSemType type : types) { - writeSemType(type); - } - writeSemType(mat.rest()); - } - - private void writeListAtomicType(ListAtomicType lat) { - FixedLengthArray fla = lat.members(); - List initial = fla.initial(); - buff.writeInt(initial.size()); - for (SemType type : initial) { - writeSemType(type); - } - buff.writeInt(fla.fixedLength()); - writeSemType(lat.rest()); - } - - private void writeIntSubtype(IntSubtype intSubtype) { - Range[] ranges = intSubtype.ranges; - buff.writeInt(ranges.length); - for (Range range : ranges) { - buff.writeLong(range.min); - buff.writeLong(range.max); - } - } - - private void writeFloatSubtype(FloatSubtype floatSubtype) { - buff.writeBoolean(floatSubtype.allowed); - buff.writeInt(floatSubtype.values.length); - for (EnumerableFloat ef : floatSubtype.values) { - buff.writeDouble(ef.value); - } - } - - private void writeDecimalSubtype(DecimalSubtype decimalSubtype) { - buff.writeBoolean(decimalSubtype.allowed); - buff.writeInt(decimalSubtype.values.length); - for (EnumerableDecimal ed : decimalSubtype.values) { - BigDecimal bigDecimal = ed.value; - buff.writeInt(bigDecimal.scale()); - byte[] unscaledValueBytes = bigDecimal.unscaledValue().toByteArray(); - buff.writeInt(unscaledValueBytes.length); - buff.writeBytes(unscaledValueBytes); - } - } - - private void writeStringSubtype(StringSubtype stringSubtype) { - CharStringSubtype charData = stringSubtype.getChar(); - buff.writeBoolean(charData.allowed); - EnumerableCharString[] charValues = charData.values; - buff.writeInt(charValues.length); - for (EnumerableCharString ecs : charValues) { - buff.writeInt(addStringCPEntry(ecs.value)); - } - NonCharStringSubtype nonCharData = stringSubtype.getNonChar(); - buff.writeBoolean(nonCharData.allowed); - EnumerableString[] nonCharValues = nonCharData.values; - buff.writeInt(nonCharValues.length); - for (EnumerableString ecs : nonCharValues) { - buff.writeInt(addStringCPEntry(ecs.value)); - } - } - - // --------------------------------------- End of SemType ----------------------------------------------- } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/ConstantPool.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/ConstantPool.java index edb6d2e08fc1..bba3434f9d2a 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/ConstantPool.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/ConstantPool.java @@ -17,7 +17,7 @@ */ package org.wso2.ballerinalang.compiler.bir.writer; -import io.ballerina.types.Env; + import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import org.ballerinalang.compiler.BLangCompilerException; @@ -45,11 +45,6 @@ public class ConstantPool { private final Map cpEntriesMap = new HashMap<>(); private final List cpEntries = new ArrayList<>(); - private final Env typeEnv; - - public ConstantPool(Env typeEnv) { - this.typeEnv = typeEnv; - } public int addCPEntry(CPEntry cpEntry) { int size = cpEntries.size(); @@ -123,7 +118,7 @@ private void writeToStream(DataOutputStream stream) throws IOException { case CP_ENTRY_SHAPE -> { CPEntry.ShapeCPEntry shapeCPEntry = (CPEntry.ShapeCPEntry) cpEntry; ByteBuf typeBuf = Unpooled.buffer(); - BIRTypeWriter birTypeWriter = new BIRTypeWriter(typeBuf, this, typeEnv); + BIRTypeWriter birTypeWriter = new BIRTypeWriter(typeBuf, this); birTypeWriter.visitType(shapeCPEntry.shape); byte[] bytes = Arrays.copyOfRange(typeBuf.array(), 0, typeBuf.writerIndex()); stream.writeInt(bytes.length); 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 205071c02a21..d36bb7fe379e 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 @@ -17,7 +17,6 @@ package org.wso2.ballerinalang.compiler.desugar; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.Env; import org.ballerinalang.model.TreeBuilder; import org.ballerinalang.model.elements.Flag; import org.ballerinalang.model.elements.PackageID; @@ -181,7 +180,7 @@ private static boolean isValueType(BType type) { static BLangExpression wrapToConversionExpr(BType sourceType, BLangExpression exprToWrap, SymbolTable symTable, Types types) { - if (types.isSameTypeIncludingTags(sourceType, exprToWrap.getBType()) || !isValueType(exprToWrap.getBType())) { + if (types.isSameType(sourceType, exprToWrap.getBType()) || !isValueType(exprToWrap.getBType())) { // No conversion needed. return exprToWrap; } @@ -330,7 +329,7 @@ static BLangReturn createReturnStmt(Location pos, BlockNode target) { public static BLangReturn createNilReturnStmt(Location pos, BType nilType) { final BLangReturn returnStmt = (BLangReturn) TreeBuilder.createReturnNode(); returnStmt.pos = pos; - returnStmt.expr = createLiteral(pos, nilType, Names.NIL_VALUE.value); + returnStmt.expr = createLiteral(pos, nilType, Names.NIL_VALUE); return returnStmt; } @@ -845,7 +844,7 @@ private static IdentifierNode createIdentifier(String value) { return node; } - public static BInvokableSymbol duplicateInvokableSymbol(Env typeEnv, BInvokableSymbol invokableSymbol) { + public static BInvokableSymbol duplicateInvokableSymbol(BInvokableSymbol invokableSymbol) { BInvokableSymbol dupFuncSymbol = Symbols.createFunctionSymbol(invokableSymbol.flags, invokableSymbol.name, invokableSymbol.originalName, invokableSymbol.pkgID, invokableSymbol.type, invokableSymbol.owner, @@ -865,18 +864,18 @@ public static BInvokableSymbol duplicateInvokableSymbol(Env typeEnv, BInvokableS new ArrayList<>((List) invokableSymbol.getAnnotations())); BInvokableType prevFuncType = (BInvokableType) invokableSymbol.type; - BInvokableType dupInvokableType = - new BInvokableType(typeEnv, List.copyOf(prevFuncType.paramTypes), - prevFuncType.restType, prevFuncType.retType, prevFuncType.tsymbol); + BInvokableType dupInvokableType = new BInvokableType(new ArrayList<>(prevFuncType.paramTypes), + prevFuncType.restType, prevFuncType.retType, + prevFuncType.tsymbol); if (Symbols.isFlagOn(invokableSymbol.flags, Flags.ISOLATED)) { dupFuncSymbol.flags |= Flags.ISOLATED; - dupInvokableType.addFlags(Flags.ISOLATED); + dupInvokableType.flags |= Flags.ISOLATED; } if (Symbols.isFlagOn(invokableSymbol.flags, Flags.TRANSACTIONAL)) { dupFuncSymbol.flags |= Flags.TRANSACTIONAL; - dupInvokableType.addFlags(Flags.TRANSACTIONAL); + dupInvokableType.flags |= Flags.TRANSACTIONAL; } dupFuncSymbol.type = dupInvokableType; @@ -885,8 +884,7 @@ public static BInvokableSymbol duplicateInvokableSymbol(Env typeEnv, BInvokableS return dupFuncSymbol; } - public static BInvokableSymbol duplicateFunctionDeclarationSymbol(Env typeEnv, - BInvokableSymbol invokableSymbol, + public static BInvokableSymbol duplicateFunctionDeclarationSymbol(BInvokableSymbol invokableSymbol, BSymbol owner, Name newName, PackageID newPkgID, @@ -916,9 +914,9 @@ public static BInvokableSymbol duplicateFunctionDeclarationSymbol(Env typeEnv, dupFuncSymbol.markdownDocumentation = invokableSymbol.markdownDocumentation; BInvokableType prevFuncType = (BInvokableType) invokableSymbol.type; - BType newFuncType = new BInvokableType(typeEnv, List.copyOf(prevFuncType.paramTypes), - prevFuncType.restType, prevFuncType.retType, prevFuncType.tsymbol); - newFuncType.addFlags(prevFuncType.getFlags()); + BType newFuncType = new BInvokableType(new ArrayList<>(prevFuncType.paramTypes), prevFuncType.restType, + prevFuncType.retType, prevFuncType.tsymbol); + newFuncType.flags |= prevFuncType.flags; dupFuncSymbol.type = newFuncType; return dupFuncSymbol; } 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 28098fb1cee5..79b4af59f064 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 @@ -223,7 +223,7 @@ private void defineClassAnnotations(BLangPackage pkgNode, SymbolEnv env2, BLangF owner); if (lambdaFunction != null) { BType type = classDef.getBType(); - if (Symbols.isFlagOn(type.getFlags(), Flags.OBJECT_CTOR)) { + if (Symbols.isFlagOn(type.flags, Flags.OBJECT_CTOR)) { if (normalMode) { // Add the lambda/invocation in a temporary block. BLangBlockStmt target = (BLangBlockStmt) TreeBuilder.createBlockNode(); @@ -503,7 +503,7 @@ private void defineFunctionAnnotations(BLangPackage pkgNode, SymbolEnv env, BLan int index; if (function.attachedFunction - && Symbols.isFlagOn(function.receiver.getBType().getFlags(), Flags.OBJECT_CTOR)) { + && Symbols.isFlagOn(function.receiver.getBType().flags, Flags.OBJECT_CTOR)) { addLambdaToGlobalAnnotMap(identifier, lambdaFunction, target); index = calculateIndex(initFnBody.stmts, function.receiver.getBType().tsymbol); } else { @@ -759,7 +759,7 @@ private void addVarArgsAnnotation(BLangFunction mainFunc, SymbolEnv env) { BLangListConstructorExpr.BLangArrayLiteral valueLiteral = (BLangListConstructorExpr.BLangArrayLiteral) TreeBuilder.createArrayLiteralExpressionNode(); - valueLiteral.setBType(new BArrayType(symTable.typeEnv(), symTable.stringType)); + valueLiteral.setBType(new BArrayType(symTable.stringType)); valueLiteral.typeChecked = true; valueLiteral.pos = pos; @@ -794,7 +794,7 @@ private void addVarArgsAnnotation(BLangFunction mainFunc, SymbolEnv env) { private BLangFunction defineFunction(Location pos, PackageID pkgID, BSymbol owner) { String funcName = ANNOT_FUNC + UNDERSCORE + annotFuncCount++; BLangFunction function = ASTBuilderUtil.createFunction(pos, funcName); - function.setBType(new BInvokableType(symTable.typeEnv(), Collections.emptyList(), symTable.mapType, null)); + function.setBType(new BInvokableType(Collections.emptyList(), symTable.mapType, null)); BLangBuiltInRefTypeNode anyMapType = (BLangBuiltInRefTypeNode) TreeBuilder.createBuiltInReferenceTypeNode(); anyMapType.typeKind = TypeKind.MAP; anyMapType.pos = pos; @@ -904,9 +904,9 @@ private BInvokableSymbol createInvokableSymbol(BLangFunction function, PackageID .toList(); functionSymbol.scope = new Scope(functionSymbol); functionSymbol.restParam = function.restParam != null ? function.restParam.symbol : null; - functionSymbol.type = new BInvokableType(symTable.typeEnv(), Collections.emptyList(), + functionSymbol.type = new BInvokableType(Collections.emptyList(), function.restParam != null ? function.restParam.getBType() : null, - new BMapType(symTable.typeEnv(), TypeTags.MAP, symTable.anyType, null), + new BMapType(TypeTags.MAP, symTable.anyType, null), null); function.symbol = functionSymbol; return functionSymbol; 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 b83ce79d4df1..36c7f958a3b5 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 @@ -18,7 +18,6 @@ package org.wso2.ballerinalang.compiler.desugar; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.Env; import org.ballerinalang.model.TreeBuilder; import org.ballerinalang.model.elements.Flag; import org.ballerinalang.model.symbols.SymbolKind; @@ -267,7 +266,7 @@ public void visit(BLangPackage pkgNode) { // Update function parameters. for (BLangFunction function : pkgNode.functions) { - updateFunctionParams(types.typeEnv(), function); + updateFunctionParams(function); } result = pkgNode; } @@ -370,10 +369,10 @@ private void addClosureMapToInit(BLangClassDefinition classDef, BVarSymbol mapSy initFunction.symbol.scope.define(paramSym.name, paramSym); initFunction.symbol.params.add(paramSym); BInvokableType initFuncSymbolType = (BInvokableType) initFunction.symbol.type; - initFuncSymbolType.addParamType(mapSymbol.type); + initFuncSymbolType.paramTypes.add(mapSymbol.type); BInvokableType initFnType = (BInvokableType) initFunction.getBType(); - initFnType.addParamType(mapSymbol.type); + initFnType.paramTypes.add(mapSymbol.type); BAttachedFunction attachedFunction = ((BObjectTypeSymbol) classDef.getBType().tsymbol).generatedInitializerFunc; attachedFunction.symbol.params.add(paramSym); @@ -645,24 +644,21 @@ private void createFunctionMap(BLangFunction funcNode, SymbolEnv funcEnv) { /** * Update the function parameters with closure parameter maps passed. * - * @param typeEnv type environment * @param funcNode function node */ - private static void updateFunctionParams(Env typeEnv, BLangFunction funcNode) { + private static void updateFunctionParams(BLangFunction funcNode) { // Add closure params to the required param list if there are any. - BInvokableSymbol dupFuncSymbol = ASTBuilderUtil.duplicateInvokableSymbol(typeEnv, funcNode.symbol); + BInvokableSymbol dupFuncSymbol = ASTBuilderUtil.duplicateInvokableSymbol(funcNode.symbol); funcNode.symbol = dupFuncSymbol; BInvokableType dupFuncType = (BInvokableType) dupFuncSymbol.type; int i = 0; - List newParamTypes = new ArrayList<>(dupFuncType.paramTypes); for (Map.Entry entry : funcNode.paramClosureMap.entrySet()) { BVarSymbol mapSymbol = entry.getValue(); dupFuncSymbol.params.add(i, mapSymbol); - newParamTypes.add(i, mapSymbol.type); + dupFuncType.paramTypes.add(i, mapSymbol.type); i++; } - dupFuncType.setParamTypes(newParamTypes); } /** 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 26aff82289b0..5d091d631269 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 @@ -655,10 +655,9 @@ private void updateFunctionParams(BLangFunction funcNode, List param VIRTUAL); funcSymbol.scope.define(symbolName, varSymbol); funcSymbol.params.add(varSymbol); - BInvokableType funcType = (BInvokableType) funcSymbol.type; - funcType.addParamType(varSymbol.type); + ((BInvokableType) funcSymbol.type).paramTypes.add(type); funcNode.requiredParams.add(ASTBuilderUtil.createVariable(pos, symbolName.value, type, null, - varSymbol)); + varSymbol)); } } @@ -729,7 +728,7 @@ private BLangFunction createFunction(String funcName, Location pos, PackageID pk function.flagSet.add(Flag.PUBLIC); BInvokableTypeSymbol invokableTypeSymbol = Symbols.createInvokableTypeSymbol(SymTag.FUNCTION_TYPE, Flags.PUBLIC, pkgID, bType, owner, pos, VIRTUAL); - function.setBType(new BInvokableType(symTable.typeEnv(), List.of(), bType, invokableTypeSymbol)); + function.setBType(new BInvokableType(new ArrayList<>(), bType, invokableTypeSymbol)); BLangBuiltInRefTypeNode typeNode = (BLangBuiltInRefTypeNode) TreeBuilder.createBuiltInReferenceTypeNode(); typeNode.setBType(bType); 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 4b166c7b7b1a..049701b1cd49 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 @@ -723,9 +723,8 @@ protected void createInvokableSymbol(BLangFunction bLangFunction, SymbolEnv env) BType returnType = bLangFunction.returnTypeNode.getBType() == null ? symResolver.resolveTypeNode(bLangFunction.returnTypeNode, env) : bLangFunction.returnTypeNode.getBType(); - BInvokableType invokableType = - new BInvokableType(symTable.typeEnv(), List.of(), getRestType(bLangFunction), - returnType, null); + BInvokableType invokableType = new BInvokableType(new ArrayList<>(), getRestType(bLangFunction), + returnType, null); BInvokableSymbol functionSymbol = Symbols.createFunctionSymbol(Flags.asMask(bLangFunction.flagSet), new Name(bLangFunction.name.value), new Name(bLangFunction.name.originalValue), @@ -965,7 +964,7 @@ private List getConfigurableLangLibInvocationParam(BLangSimpleV BLangLiteral configNameLiteral = ASTBuilderUtil.createLiteral(configurableVar.pos, symTable.stringType, configVarName); BType type = configurableVar.getBType(); - BType typedescType = new BTypedescType(symTable.typeEnv(), type, symTable.typeDesc.tsymbol); + BType typedescType = new BTypedescType(type, symTable.typeDesc.tsymbol); BLangTypedescExpr typedescExpr = new BLangTypedescExpr(); typedescExpr.resolvedType = type; @@ -1380,7 +1379,7 @@ public void visit(BLangFunction funcNode) { // Duplicate the invokable symbol and the invokable type. funcNode.originalFuncSymbol = funcNode.symbol; - funcNode.symbol = ASTBuilderUtil.duplicateInvokableSymbol(types.typeEnv(), funcNode.symbol); + funcNode.symbol = ASTBuilderUtil.duplicateInvokableSymbol(funcNode.symbol); funcNode.requiredParams = rewrite(funcNode.requiredParams, funcEnv); funcNode.restParam = rewrite(funcNode.restParam, funcEnv); @@ -1716,7 +1715,7 @@ private void createVarDefStmts(BLangTupleVariable parentTupleVariable, BLangBloc if (variable.getKind() == NodeKind.TUPLE_VARIABLE) { // Else recursively create the var def statements. BLangTupleVariable tupleVariable = (BLangTupleVariable) variable; BLangIndexBasedAccess arrayAccessExpr = ASTBuilderUtil.createIndexBasesAccessExpr(tupleVariable.pos, - new BArrayType(symTable.typeEnv(), symTable.anyType), tupleVarSymbol, indexExpr); + new BArrayType(symTable.anyType), tupleVarSymbol, indexExpr); if (parentIndexAccessExpr != null) { arrayAccessExpr.expr = parentIndexAccessExpr; } @@ -1792,7 +1791,7 @@ private void createVarDefStmts(BLangRecordVariable parentRecordVariable, BLangBl if (recordFieldKeyValue.valueBindingPattern.getKind() == NodeKind.TUPLE_VARIABLE) { BLangTupleVariable tupleVariable = (BLangTupleVariable) recordFieldKeyValue.valueBindingPattern; BLangIndexBasedAccess arrayAccessExpr = ASTBuilderUtil.createIndexBasesAccessExpr(tupleVariable.pos, - new BArrayType(symTable.typeEnv(), symTable.anyType), recordVarSymbol, indexExpr); + new BArrayType(symTable.anyType), recordVarSymbol, indexExpr); if (parentIndexAccessExpr != null) { arrayAccessExpr.expr = parentIndexAccessExpr; } @@ -2025,12 +2024,12 @@ private BLangSimpleVariable generateRestFilter(BLangSimpleVarRef mapVarRef, Loca ASTBuilderUtil.createVariableRef(pos, mapVariable.symbol), typeCastExpr.getBType()); String entriesVarName = "$map$ref$entries$" + UNDERSCORE + restNum; BType constraintType = getRestFilterConstraintType(targetType); - BVarSymbol varSymbol = new BVarSymbol(constraintType.getFlags(), null, null, constraintType, null, + BVarSymbol varSymbol = new BVarSymbol(constraintType.flags, null, null, constraintType, null, null, null); BVarSymbol stringVarSymbol = new BVarSymbol(0, null, null, symTable.stringType, null, symTable.builtinPos, SymbolOrigin.VIRTUAL); - BType entriesType = new BMapType(symTable.typeEnv(), TypeTags.MAP, - new BTupleType(symTable.typeEnv(), Arrays.asList(new BTupleMember(symTable.stringType, stringVarSymbol), + BType entriesType = new BMapType(TypeTags.MAP, + new BTupleType(Arrays.asList(new BTupleMember(symTable.stringType, stringVarSymbol), new BTupleMember(constraintType, varSymbol))), null); BLangSimpleVariable entriesInvocationVar = defVariable(pos, entriesType, parentBlockStmt, types.addConversionExprIfRequired(entriesInvocation, entriesType), @@ -2132,9 +2131,7 @@ private BLangLambdaFunction generateEntriesToMapLambda(Location pos, BType const .map(param -> param.symbol) .toList(); functionSymbol.scope = env.scope; - functionSymbol.type = - new BInvokableType(symTable.typeEnv(), Collections.singletonList(getStringAnyTupleType()), constraint, - null); + functionSymbol.type = new BInvokableType(Collections.singletonList(getStringAnyTupleType()), constraint, null); function.symbol = functionSymbol; rewrite(function, env); env.enclPkg.addFunction(function); @@ -2285,7 +2282,7 @@ private BLangInvocation generateErrorCauseLanglibFunction(Location pos, BType ca private BLangInvocation generateCreateRecordValueInvocation(Location pos, BType targetType, BVarSymbol source) { - BType typedescType = new BTypedescType(symTable.typeEnv(), targetType, symTable.typeDesc.tsymbol); + BType typedescType = new BTypedescType(targetType, symTable.typeDesc.tsymbol); BLangInvocation invocationNode = createInvocationNode(CREATE_RECORD_VALUE, new ArrayList<>(), typedescType); BLangTypedescExpr typedescExpr = new BLangTypedescExpr(); @@ -2296,14 +2293,14 @@ private BLangInvocation generateCreateRecordValueInvocation(Location pos, invocationNode.symbol = symResolver.lookupLangLibMethod(typedescType, Names.fromString(CREATE_RECORD_VALUE), env); invocationNode.requiredArgs = Lists.of(ASTBuilderUtil.createVariableRef(pos, source), typedescExpr); - invocationNode.setBType(BUnionType.create(symTable.typeEnv(), null, targetType, symTable.errorType)); + invocationNode.setBType(BUnionType.create(null, targetType, symTable.errorType)); return invocationNode; } private BLangInvocation generateCloneWithTypeInvocation(Location pos, BType targetType, BVarSymbol source) { - BType typedescType = new BTypedescType(symTable.typeEnv(), targetType, symTable.typeDesc.tsymbol); + BType typedescType = new BTypedescType(targetType, symTable.typeDesc.tsymbol); BLangInvocation invocationNode = createInvocationNode(CLONE_WITH_TYPE, new ArrayList<>(), typedescType); BLangTypedescExpr typedescExpr = new BLangTypedescExpr(); @@ -2313,7 +2310,7 @@ private BLangInvocation generateCloneWithTypeInvocation(Location pos, invocationNode.expr = typedescExpr; invocationNode.symbol = symResolver.lookupLangLibMethod(typedescType, Names.fromString(CLONE_WITH_TYPE), env); invocationNode.requiredArgs = Lists.of(ASTBuilderUtil.createVariableRef(pos, source), typedescExpr); - invocationNode.setBType(BUnionType.create(symTable.typeEnv(), null, targetType, symTable.errorType)); + invocationNode.setBType(BUnionType.create(null, targetType, symTable.errorType)); return invocationNode; } @@ -2420,7 +2417,7 @@ private BInvokableSymbol createReturnTrueStatement(Location pos, BLangFunction f .map(param -> param.symbol) .toList(); functionSymbol.scope = env.scope; - functionSymbol.type = new BInvokableType(symTable.typeEnv(), Collections.singletonList(getStringAnyTupleType()), + functionSymbol.type = new BInvokableType(Collections.singletonList(getStringAnyTupleType()), getRestType(functionSymbol), symTable.booleanType, null); function.symbol = functionSymbol; rewrite(function, env); @@ -2452,7 +2449,7 @@ private BTupleType getStringAnyTupleType() { add(new BTupleMember(symTable.stringType, stringVarSymbol)); add(new BTupleMember(symTable.anyType, anyVarSymbol)); }}; - return new BTupleType(symTable.typeEnv(), typeList); + return new BTupleType(typeList); } /** @@ -2541,7 +2538,7 @@ public void visit(BLangTupleDestructure tupleDestructure) { final BLangBlockStmt blockStmt = ASTBuilderUtil.createBlockStmt(tupleDestructure.pos); //create a array of any-type based on the dimension - BType runTimeType = new BArrayType(symTable.typeEnv(), symTable.anyType); + BType runTimeType = new BArrayType(symTable.anyType); //create a simple var for the array 'any[] x = (tuple)' based on the dimension for x String name = "tuple"; @@ -2690,7 +2687,7 @@ private void createVarRefAssignmentStmts(BLangTupleVarRef parentTupleVariable, B BLangTupleVarRef tupleVarRef = (BLangTupleVarRef) expression; BLangLiteral indexExpr = ASTBuilderUtil.createLiteral(tupleVarRef.pos, symTable.intType, (long) index); BLangIndexBasedAccess arrayAccessExpr = ASTBuilderUtil.createIndexBasesAccessExpr(tupleVarRef.pos, - new BArrayType(symTable.typeEnv(), symTable.anyType), tupleVarSymbol, indexExpr); + new BArrayType(symTable.anyType), tupleVarSymbol, indexExpr); if (parentIndexAccessExpr != null) { arrayAccessExpr.expr = parentIndexAccessExpr; } @@ -2796,7 +2793,7 @@ public void visit(BLangRecordDestructure recordDestructure) { final BLangBlockStmt blockStmt = ASTBuilderUtil.createBlockStmt(recordDestructure.pos); - BType runTimeType = new BMapType(symTable.typeEnv(), TypeTags.MAP, symTable.anyType, null); + BType runTimeType = new BMapType(TypeTags.MAP, symTable.anyType, null); String name = "$map$_0"; final BLangSimpleVariable mapVariable = @@ -4164,9 +4161,9 @@ private BLangExpression createConditionForErrorArgListBindingPattern(BLangErrorB symTable.stringType, null, symTable.builtinPos, VIRTUAL); BVarSymbol anydataVarSymbol = new BVarSymbol(0, null, null, symTable.anydataType, null, symTable.builtinPos, VIRTUAL); - BMapType entriesType = new BMapType(symTable.typeEnv(), TypeTags.MAP, new BTupleType(symTable.typeEnv(), - Arrays.asList(new BTupleMember(symTable.stringType, stringVarSymbol), - new BTupleMember(symTable.anydataType, anydataVarSymbol))), null); + BMapType entriesType = new BMapType(TypeTags.MAP, new BTupleType(Arrays.asList( + new BTupleMember(symTable.stringType, stringVarSymbol), + new BTupleMember(symTable.anydataType, anydataVarSymbol))), null); BLangInvocation entriesInvocation = generateMapEntriesInvocation(errorDetailVarRef, entriesType); BLangSimpleVariableDef entriesVarDef = createVarDef("$entries$", entriesType, entriesInvocation, restPatternPos); @@ -4339,13 +4336,12 @@ private void createRestPattern(Location pos, List keysToRemove, BLangSim BType targetType, BLangBlockStmt blockStmt, BLangSimpleVarRef restMatchPatternVarRef) { BType constraintType = getRestFilterConstraintType(targetType); - BVarSymbol varSymbol = new BVarSymbol(constraintType.getFlags(), null, null, constraintType, null, + BVarSymbol varSymbol = new BVarSymbol(constraintType.flags, null, null, constraintType, null, null, null); BVarSymbol stringVarSymbol = new BVarSymbol(0, null, null, symTable.stringType, null, symTable.builtinPos, VIRTUAL); - BMapType entriesType = new BMapType(symTable.typeEnv(), TypeTags.MAP, new BTupleType(symTable.typeEnv(), - Arrays.asList(new BTupleMember(symTable.stringType, stringVarSymbol), - new BTupleMember(constraintType, varSymbol))), null); + BMapType entriesType = new BMapType(TypeTags.MAP, new BTupleType(Arrays.asList(new BTupleMember( + symTable.stringType, stringVarSymbol), new BTupleMember(constraintType, varSymbol))), null); BLangInvocation entriesInvocation = generateMapEntriesInvocation(matchExprVarRef, entriesType); BLangSimpleVariableDef entriesVarDef = createVarDef("$entries$", entriesType, entriesInvocation, pos); blockStmt.addStatement(entriesVarDef); @@ -4535,9 +4531,9 @@ private void createRestBindingPatternCondition(BLangMappingBindingPattern mappin BVarSymbol varSymbol = Symbols.createVarSymbolForTupleMember(restType); BVarSymbol stringVarSymbol = new BVarSymbol(0, null, null, symTable.stringType, null, symTable.builtinPos, VIRTUAL); - BMapType entriesType = new BMapType(symTable.typeEnv(), TypeTags.MAP, new BTupleType(symTable.typeEnv(), - Arrays.asList(new BTupleMember(symTable.stringType, stringVarSymbol), - new BTupleMember(restType, varSymbol))), null); + BMapType entriesType = new BMapType(TypeTags.MAP, new BTupleType(Arrays.asList( + new BTupleMember(symTable.stringType, stringVarSymbol), + new BTupleMember(restType, varSymbol))), null); BLangInvocation entriesInvocation = generateMapEntriesInvocation(varRef, entriesType); BLangSimpleVariableDef entriesVarDef = createVarDef("$entries$", entriesType, entriesInvocation, restPatternPos); @@ -4653,12 +4649,12 @@ private BLangExpression createVarCheckConditionForMappingMatchPattern(BLangMappi Location restPatternPos = restMatchPattern.pos; List keysToRemove = getKeysToRemove(mappingMatchPattern); BType restType = ((BRecordType) restMatchPattern.getBType()).restFieldType; - BVarSymbol varSymbol = new BVarSymbol(restType.getFlags(), null, null, restType, null, null, null); + BVarSymbol varSymbol = new BVarSymbol(restType.flags, null, null, restType, null, null, null); BVarSymbol stringVarSymbol = new BVarSymbol(0, null, null, symTable.stringType, null, symTable.builtinPos, VIRTUAL); - BMapType entriesType = new BMapType(symTable.typeEnv(), TypeTags.MAP, new BTupleType(symTable.typeEnv(), - Arrays.asList(new BTupleMember(symTable.stringType, stringVarSymbol), - new BTupleMember(restType, varSymbol))), null); + BMapType entriesType = new BMapType(TypeTags.MAP, new BTupleType(Arrays.asList( + new BTupleMember(symTable.stringType, stringVarSymbol), + new BTupleMember(restType, varSymbol))), null); BLangInvocation entriesInvocation = generateMapEntriesInvocation(tempCastVarRef, entriesType); BLangSimpleVariableDef entriesVarDef = createVarDef("$entries$", entriesType, entriesInvocation, restPatternPos); @@ -4831,9 +4827,9 @@ private BLangExpression createConditionForErrorArgListMatchPattern(BLangErrorMat symTable.stringType, null, symTable.builtinPos, VIRTUAL); BVarSymbol anydataVarSymbol = new BVarSymbol(0, null, null, symTable.anydataType, null, symTable.builtinPos, VIRTUAL); - BMapType entriesType = new BMapType(symTable.typeEnv(), TypeTags.MAP, new BTupleType(symTable.typeEnv(), - Arrays.asList(new BTupleMember(symTable.stringType, stringVarSymbol), - new BTupleMember(symTable.anydataType, anydataVarSymbol))), null); + BMapType entriesType = new BMapType(TypeTags.MAP, new BTupleType(Arrays.asList( + new BTupleMember(symTable.stringType, stringVarSymbol), + new BTupleMember(symTable.anydataType, anydataVarSymbol))), null); BLangInvocation entriesInvocation = generateMapEntriesInvocation(errorDetailVarRef, entriesType); BLangSimpleVariableDef entriesVarDef = createVarDef("$entries$", entriesType, entriesInvocation, restPatternPos); @@ -5340,7 +5336,7 @@ private BLangFail createOnFailInvocation(BLangOnFailClause onFailClause, BLangFa } } - BLangLiteral nilLiteral = ASTBuilderUtil.createLiteral(fail.pos, symTable.nilType, Names.NIL_VALUE.value); + BLangLiteral nilLiteral = ASTBuilderUtil.createLiteral(fail.pos, symTable.nilType, Names.NIL_VALUE); BLangStatementExpression statementExpression = createStatementExpression(onFailBody, nilLiteral); statementExpression.setBType(symTable.nilType); @@ -5601,8 +5597,8 @@ public void visit(BLangLock lockNode) { enclLocks.push(lockStmt); - BLangLiteral nilLiteral = ASTBuilderUtil.createLiteral(lockNode.pos, symTable.nilType, Names.NIL_VALUE.value); - BType nillableError = BUnionType.create(symTable.typeEnv(), null, symTable.errorType, symTable.nilType); + BLangLiteral nilLiteral = ASTBuilderUtil.createLiteral(lockNode.pos, symTable.nilType, Names.NIL_VALUE); + BType nillableError = BUnionType.create(null, symTable.errorType, symTable.nilType); BLangStatementExpression statementExpression = createStatementExpression(lockNode.body, nilLiteral); statementExpression.setBType(symTable.nilType); @@ -5910,7 +5906,7 @@ private BLangOnFailClause createRetryInternalOnFail(Location pos, BLangUnaryExpr createNotBinaryExpression(Location pos, BLangExpression expression) { List paramTypes = new ArrayList<>(); paramTypes.add(symTable.booleanType); - BInvokableType type = new BInvokableType(symTable.typeEnv(), paramTypes, symTable.booleanType, + BInvokableType type = new BInvokableType(paramTypes, symTable.booleanType, null); BOperatorSymbol notOperatorSymbol = new BOperatorSymbol( Names.fromString(OperatorKind.NOT.value()), symTable.rootPkgSymbol.pkgID, type, symTable.rootPkgSymbol, @@ -5937,7 +5933,7 @@ BLangLambdaFunction createLambdaFunction(Location pos, String functionNamePrefix lambdaFunction.pos = pos; List paramTypes = new ArrayList<>(); lambdaFunctionVariable.forEach(variable -> paramTypes.add(variable.symbol.type)); - lambdaFunction.setBType(new BInvokableType(symTable.typeEnv(), paramTypes, func.symbol.type.getReturnType(), + lambdaFunction.setBType(new BInvokableType(paramTypes, func.symbol.type.getReturnType(), null)); return lambdaFunction; } @@ -5995,8 +5991,7 @@ public void visit(BLangListConstructorExpr listConstructor) { expr = new BLangTupleLiteral(listConstructor.pos, listConstructor.exprs, listConstructor.getBType()); result = rewriteExpr(expr); } else if (listConstructorType.tag == TypeTags.JSON) { - expr = new BLangJSONArrayLiteral(listConstructor.exprs, - new BArrayType(symTable.typeEnv(), listConstructor.getBType())); + expr = new BLangJSONArrayLiteral(listConstructor.exprs, new BArrayType(listConstructor.getBType())); result = rewriteExpr(expr); } else if (getElementType(listConstructorType).tag == TypeTags.JSON) { expr = new BLangJSONArrayLiteral(listConstructor.exprs, listConstructor.getBType()); @@ -6023,8 +6018,7 @@ public void visit(BLangArrayLiteral arrayLiteral) { arrayLiteral.exprs = rewriteExprs(arrayLiteral.exprs); BType arrayLiteralType = Types.getImpliedType(arrayLiteral.getBType()); if (arrayLiteralType.tag == TypeTags.JSON) { - result = new BLangJSONArrayLiteral(arrayLiteral.exprs, - new BArrayType(symTable.typeEnv(), arrayLiteral.getBType())); + result = new BLangJSONArrayLiteral(arrayLiteral.exprs, new BArrayType(arrayLiteral.getBType())); return; } else if (getElementType(arrayLiteralType).tag == TypeTags.JSON) { result = new BLangJSONArrayLiteral(arrayLiteral.exprs, arrayLiteral.getBType()); @@ -6056,8 +6050,8 @@ public void visit(BLangTupleLiteral tupleLiteral) { spreadOpType = Types.getImpliedType(spreadOpType); if (spreadOpType.tag == TypeTags.ARRAY) { BArrayType spreadOpBArray = (BArrayType) spreadOpType; - if (spreadOpBArray.getSize() >= 0) { - i += spreadOpBArray.getSize(); + if (spreadOpBArray.size >= 0) { + i += spreadOpBArray.size; continue; } } else { @@ -6172,7 +6166,7 @@ private void generateFieldsForUserUnspecifiedRecordFields(List fieldNames = getNamesOfUserSpecifiedRecordFields(userSpecifiedFields); Location pos = recordLiteral.pos; BRecordType recordType = (BRecordType) type; - boolean isReadonly = Symbols.isFlagOn(recordType.getFlags(), Flags.READONLY); + boolean isReadonly = Symbols.isFlagOn(recordType.flags, Flags.READONLY); generateFieldsForUserUnspecifiedRecordFields(recordType, userSpecifiedFields, fieldNames, pos, isReadonly); } @@ -6569,8 +6563,7 @@ private BLangStatementExpression rewriteLaxMapAccess(BLangFieldBasedAccess field BLangStatementExpression statementExpression = new BLangStatementExpression(); BLangBlockStmt block = new BLangBlockStmt(); statementExpression.stmt = block; - BUnionType fieldAccessType = - BUnionType.create(symTable.typeEnv(), null, fieldAccessExpr.getBType(), symTable.errorType); + BUnionType fieldAccessType = BUnionType.create(null, fieldAccessExpr.getBType(), symTable.errorType); Location pos = fieldAccessExpr.pos; BLangSimpleVariableDef result = createVarDef("$mapAccessResult$", fieldAccessType, null, pos); block.addStatement(result); @@ -6584,7 +6577,7 @@ private BLangStatementExpression rewriteLaxMapAccess(BLangFieldBasedAccess field BLangLiteral mapIndex = ASTBuilderUtil.createLiteral( fieldAccessExpr.field.pos, symTable.stringType, fieldAccessExpr.field.value); BLangMapAccessExpr mapAccessExpr = new BLangMapAccessExpr(pos, fieldAccessExpr.expr, mapIndex); - BUnionType xmlOrNil = BUnionType.create(symTable.typeEnv(), null, fieldAccessExpr.getBType(), symTable.nilType); + BUnionType xmlOrNil = BUnionType.create(null, fieldAccessExpr.getBType(), symTable.nilType); mapAccessExpr.setBType(xmlOrNil); BLangSimpleVariableDef mapResult = createVarDef("$mapAccess", xmlOrNil, mapAccessExpr, pos); BLangSimpleVarRef mapResultRef = ASTBuilderUtil.createVariableRef(pos, mapResult.var.symbol); @@ -6695,7 +6688,7 @@ public void visit(BLangIndexBasedAccess indexAccessExpr) { if (varRefType.tag == TypeTags.MAP) { targetVarRef = new BLangMapAccessExpr(indexAccessExpr.pos, indexAccessExpr.expr, indexAccessExpr.indexExpr, indexAccessExpr.isStoreOnCreation); - } else if (types.isSubTypeOfMapping(types.getNilLiftType(varRefType.semType()))) { + } else if (types.isSubTypeOfMapping(types.getSafeType(varRefType, true, false))) { targetVarRef = new BLangStructFieldAccessExpr(indexAccessExpr.pos, indexAccessExpr.expr, indexAccessExpr.indexExpr, (BVarSymbol) indexAccessExpr.symbol, false); @@ -6874,7 +6867,7 @@ public void visit(BLangInvocation.BLangActionInvocation actionInvocation) { } // Add `@strand {thread: "any"}` annotation to an isolated start-action. - if (actionInvocation.async && Symbols.isFlagOn(actionInvocation.symbol.type.getFlags(), Flags.ISOLATED)) { + if (actionInvocation.async && Symbols.isFlagOn(actionInvocation.symbol.type.flags, Flags.ISOLATED)) { addStrandAnnotationWithThreadAny(actionInvocation.pos); actionInvocation.addAnnotationAttachment(this.strandAnnotAttachement); ((BInvokableSymbol) actionInvocation.symbol) @@ -7049,8 +7042,7 @@ private BLangInvocation createInvocationForPathParams( BResourcePathSegmentSymbol lastPathSegmentSym = pathSegmentSymbols.get(pathSegmentSymbols.size() - 1); if (lastPathSegmentSym.kind == SymbolKind.RESOURCE_PATH_REST_PARAM_SEGMENT) { invokableSymbol.restParam = new BVarSymbol(0, Names.EMPTY, this.env.scope.owner.pkgID, - new BArrayType(symTable.typeEnv(), lastPathSegmentSym.type), this.env.scope.owner, - lastPathSegmentSym.pos, VIRTUAL); + new BArrayType(lastPathSegmentSym.type), this.env.scope.owner, lastPathSegmentSym.pos, VIRTUAL); pathSegmentCount--; } @@ -7107,10 +7099,9 @@ private BLangExpression rewriteInvocation(BLangInvocation invocation, boolean as result = invRef; BInvokableSymbol invSym = (BInvokableSymbol) invocation.symbol; - if (Symbols.isFlagOn(invSym.retType.getFlags(), Flags.PARAMETERIZED)) { - BType retType = unifier.build(symTable.typeEnv(), invSym.retType); - invocation.setBType(invocation.async ? - new BFutureType(symTable.typeEnv(), retType, null) : retType); + if (Symbols.isFlagOn(invSym.retType.flags, Flags.PARAMETERIZED)) { + BType retType = unifier.build(invSym.retType); + invocation.setBType(invocation.async ? new BFutureType(TypeTags.FUTURE, retType, null) : retType); } if (invocation.expr == null) { @@ -7145,7 +7136,7 @@ private BLangExpression rewriteInvocation(BLangInvocation invocation, boolean as private void populateOCEInvocation(BLangInvocation invocation, BLangInvocation invRef) { - if (invocation.objectInitMethod && Symbols.isFlagOn(invocation.expr.getBType().getFlags(), Flags.OBJECT_CTOR)) { + if (invocation.objectInitMethod && Symbols.isFlagOn(invocation.expr.getBType().flags, Flags.OBJECT_CTOR)) { BObjectType initializingObject = (BObjectType) invocation.expr.getBType(); BLangClassDefinition classDef = initializingObject.classDef; if (classDef.hasClosureVars) { @@ -7314,13 +7305,13 @@ private BLangInvocation desugarStreamTypeInit(BLangTypeInit typeInitExpr) { BStreamType referredStreamType = (BStreamType) Types.getImpliedType(typeInitExpr.getBType()); BType constraintType = referredStreamType.constraint; - BType constraintTdType = new BTypedescType(symTable.typeEnv(), constraintType, symTable.typeDesc.tsymbol); + BType constraintTdType = new BTypedescType(constraintType, symTable.typeDesc.tsymbol); BLangTypedescExpr constraintTdExpr = new BLangTypedescExpr(); constraintTdExpr.resolvedType = constraintType; constraintTdExpr.setBType(constraintTdType); BType completionType = referredStreamType.completionType; - BType completionTdType = new BTypedescType(symTable.typeEnv(), completionType, symTable.typeDesc.tsymbol); + BType completionTdType = new BTypedescType(completionType, symTable.typeDesc.tsymbol); BLangTypedescExpr completionTdExpr = new BLangTypedescExpr(); completionTdExpr.resolvedType = completionType; completionTdExpr.setBType(completionTdType); @@ -7331,8 +7322,7 @@ private BLangInvocation desugarStreamTypeInit(BLangTypeInit typeInitExpr) { } BLangInvocation streamConstructInvocation = ASTBuilderUtil.createInvocationExprForMethod( typeInitExpr.pos, symbol, args, symResolver); - streamConstructInvocation.setBType(new BStreamType(symTable.typeEnv(), TypeTags.STREAM, constraintType, - completionType, null)); + streamConstructInvocation.setBType(new BStreamType(TypeTags.STREAM, constraintType, completionType, null)); return streamConstructInvocation; } @@ -7725,7 +7715,7 @@ private void createTypeCastExprForArithmeticExpr(BLangBinaryExpr binaryExpr, int return; } if (TypeTags.isXMLTypeTag(lhsExprTypeTag) && !TypeTags.isXMLTypeTag(rhsExprTypeTag)) { - if (types.isStringSubType(binaryExpr.rhsExpr.getBType())) { + if (types.checkTypeContainString(binaryExpr.rhsExpr.getBType())) { binaryExpr.rhsExpr = ASTBuilderUtil.createXMLTextLiteralNode(binaryExpr, binaryExpr.rhsExpr, binaryExpr.rhsExpr.pos, symTable.xmlType); return; @@ -7734,7 +7724,7 @@ private void createTypeCastExprForArithmeticExpr(BLangBinaryExpr binaryExpr, int return; } if (TypeTags.isXMLTypeTag(rhsExprTypeTag) && !TypeTags.isXMLTypeTag(lhsExprTypeTag)) { - if (types.isStringSubType(binaryExpr.lhsExpr.getBType())) { + if (types.checkTypeContainString(binaryExpr.lhsExpr.getBType())) { binaryExpr.lhsExpr = ASTBuilderUtil.createXMLTextLiteralNode(binaryExpr, binaryExpr.lhsExpr, binaryExpr.rhsExpr.pos, symTable.xmlType); return; @@ -7858,7 +7848,7 @@ private BLangExpression addNilType(BType exprType, BLangExpression expr) { LinkedHashSet members = new LinkedHashSet<>(2); members.add(exprType); members.add(symTable.nilType); - BUnionType unionType = new BUnionType(types.typeEnv(), null, members, false); + BUnionType unionType = new BUnionType(null, members, true, false); return createTypeCastExpr(expr, unionType); } @@ -8121,8 +8111,8 @@ public void visit(BLangLambdaFunction bLangLambdaFunction) { bLangLambdaFunction.function = rewrite(bLangLambdaFunction.function, bLangLambdaFunction.capturedClosureEnv); BLangFunction function = bLangLambdaFunction.function; // Add `@strand {thread: "any"}` annotation to an isolated named worker declaration in an isolated function. - if (function.flagSet.contains(Flag.WORKER) && Symbols.isFlagOn(function.symbol.type.getFlags(), Flags.ISOLATED) - && Symbols.isFlagOn(env.enclInvokable.symbol.flags, Flags.ISOLATED)) { + if (function.flagSet.contains(Flag.WORKER) && Symbols.isFlagOn(function.symbol.type.flags, Flags.ISOLATED) && + Symbols.isFlagOn(env.enclInvokable.symbol.flags, Flags.ISOLATED)) { addStrandAnnotationWithThreadAny(function.pos); function.addAnnotationAttachment(this.strandAnnotAttachement); BInvokableSymbol funcSymbol = function.symbol; @@ -8180,8 +8170,8 @@ public void visit(BLangArrowFunction bLangArrowFunction) { funcSymbol.retType = funcNode.returnTypeNode.getBType(); // Create function type. List paramTypes = new ArrayList<>(paramSymbols.stream().map(paramSym -> paramSym.type).toList()); - funcNode.setBType(new BInvokableType(symTable.typeEnv(), paramTypes, getRestType(funcSymbol), - funcNode.returnTypeNode.getBType(), funcSymbol.type.tsymbol)); + funcNode.setBType(new BInvokableType(paramTypes, getRestType(funcSymbol), funcNode.returnTypeNode.getBType(), + funcSymbol.type.tsymbol)); lambdaFunction.function.pos = bLangArrowFunction.pos; lambdaFunction.function.body.pos = bLangArrowFunction.pos; @@ -8367,7 +8357,7 @@ private BLangClassDefinition desugarTemplateLiteralObjectTypedef(List(); - expr.setBType(new BArrayType(symTable.typeEnv(), symTable.anyType)); + expr.setBType(new BArrayType(symTable.anyType)); return expr; } @@ -9343,7 +9334,7 @@ private BLangLiteral createByteLiteral(Location pos, Byte value) { } private BLangExpression createTypeCastExpr(BLangExpression expr, BType targetType) { - if (types.isSameTypeIncludingTags(expr.getBType(), targetType)) { + if (types.isSameType(expr.getBType(), targetType)) { return expr; } @@ -9551,7 +9542,7 @@ private void reorderArguments(BLangInvocation iExpr) { if (refType.tag == TypeTags.ARRAY) { BArrayType arrayType = (BArrayType) refType; if (arrayType.state == BArrayState.CLOSED && - arrayType.getSize() == (iExpr.requiredArgs.size() - originalRequiredArgCount)) { + arrayType.size == (iExpr.requiredArgs.size() - originalRequiredArgCount)) { // If the array was a closed array that provided only for the non rest params, set the rest param // type as the element type to satisfy code gen. The foreach will not be executed at runtime. valueExpr.setBType(restParamType.eType); @@ -9815,7 +9806,7 @@ private BType getStructuredBindingPatternType(BLangVariable bindingPatternVariab memberTypes.add( new BTupleMember(member, varSymbol)); } - BTupleType tupleType = new BTupleType(symTable.typeEnv(), memberTypes); + BTupleType tupleType = new BTupleType(memberTypes); if (tupleVariable.restVariable != null) { BArrayType restArrayType = (BArrayType) getStructuredBindingPatternType(tupleVariable.restVariable); tupleType.restType = restArrayType.eType; @@ -9849,7 +9840,7 @@ private BType getStructuredBindingPatternType(BLangVariable bindingPatternVariab recordSymbol.scope.define(fieldName, fieldSymbol); } - BRecordType recordVarType = new BRecordType(symTable.typeEnv(), recordSymbol); + BRecordType recordVarType = new BRecordType(recordSymbol); recordVarType.fields = fields; // if rest param is null we treat it as an open record with anydata rest param @@ -9886,7 +9877,7 @@ private BType getStructuredBindingPatternType(BLangVariable bindingPatternVariab TypeDefBuilderHelper.createTypeDefinitionForTSymbol(detailType, detailType.tsymbol, recordTypeNode, env); } - BErrorType errorType = new BErrorType(symTable.typeEnv(), errorTypeSymbol, detailType); + BErrorType errorType = new BErrorType(errorTypeSymbol, detailType); errorTypeSymbol.type = errorType; TypeDefBuilderHelper.createTypeDefinitionForTSymbol(errorType, errorTypeSymbol, @@ -9945,7 +9936,7 @@ private BRecordType createAnonRecordType(Location pos) { env.enclPkg.symbol.pkgID, null, null, pos, VIRTUAL); detailRecordTypeSymbol.scope = new Scope(detailRecordTypeSymbol); - BRecordType detailRecordType = new BRecordType(symTable.typeEnv(), detailRecordTypeSymbol); + BRecordType detailRecordType = new BRecordType(detailRecordTypeSymbol); detailRecordType.restFieldType = symTable.anydataType; return detailRecordType; } @@ -10103,7 +10094,7 @@ private void handleSafeNavigation(BLangBlockStmt blockStmt, BLangAccessExpressio if (!(accessExpr.errorSafeNavigation || accessExpr.nilSafeNavigation)) { BType originalType = Types.getImpliedType(accessExpr.originalType); if (isMapJson(originalType, false)) { - accessExpr.setBType(BUnionType.create(symTable.typeEnv(), null, originalType, symTable.errorType)); + accessExpr.setBType(BUnionType.create(null, originalType, symTable.errorType)); } else { accessExpr.setBType(originalType); } @@ -10278,7 +10269,7 @@ private BLangMatchClause getMatchAllAndNilReturnClause(BLangExpression matchExpr BLangVariableReference tempResultVarRef = ASTBuilderUtil.createVariableRef(pos, tempResultVar.symbol); BLangAssignment assignmentStmt = ASTBuilderUtil.createAssignmentStmt(pos, tempResultVarRef, createLiteral(pos, symTable.nilType, - Names.NIL_VALUE.value)); + Names.NIL_VALUE)); BLangBlockStmt clauseBody = ASTBuilderUtil.createBlockStmt(pos, this.env.scope, Lists.of(assignmentStmt)); BLangWildCardMatchPattern wildCardMatchPattern = ASTBuilderUtil.createWildCardMatchPattern(matchExpr); @@ -10331,8 +10322,7 @@ private BLangMatchClause getSuccessPatternClause(BType type, BLangExpression mat // and may not reflect the actual type of the child/field expr. if (TypeTags.isXMLTypeTag(Types.getImpliedType(tempAccessExpr.expr.getBType()).tag)) { // todo: add discription why this is special here - tempAccessExpr.setBType( - BUnionType.create(symTable.typeEnv(), null, accessExpr.originalType, symTable.errorType, + tempAccessExpr.setBType(BUnionType.create(null, accessExpr.originalType, symTable.errorType, symTable.nilType)); } else { tempAccessExpr.setBType(accessExpr.originalType); @@ -10446,8 +10436,8 @@ private BLangFunction createInitFunctionForClassDefn(BLangClassDefinition classD } BLangFunction initFunction = - TypeDefBuilderHelper.createInitFunctionForStructureType(symTable.typeEnv(), classDefinition.symbol, env, - names, GENERATED_INIT_SUFFIX, classDefinition.getBType(), returnType); + TypeDefBuilderHelper.createInitFunctionForStructureType(classDefinition.symbol, env, names, + GENERATED_INIT_SUFFIX, classDefinition.getBType(), returnType); BObjectTypeSymbol typeSymbol = ((BObjectTypeSymbol) classDefinition.getBType().tsymbol); typeSymbol.generatedInitializerFunc = new BAttachedFunction(GENERATED_INIT_SUFFIX, initFunction.symbol, (BInvokableType) initFunction.getBType(), null); @@ -10659,8 +10649,7 @@ public BLangLambdaFunction createArrowFunctionForNavigation(Location pos, List compUnitList = this.bLangPackage.getTestablePkg().getCompilationUnits(); - BArrayType bArrayType = new BArrayType(symTable.typeEnv(), symTable.stringType, null, -1, BArrayState.OPEN); + BArrayType bArrayType = new BArrayType(symTable.stringType, null, -1, BArrayState.OPEN); List modifiedcompUnitList = new ArrayList<>(); for (BLangCompilationUnit compUnit : compUnitList) { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/QueryDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/QueryDesugar.java index d52d0000dd98..e114284e819d 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/QueryDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/QueryDesugar.java @@ -17,9 +17,6 @@ package org.wso2.ballerinalang.compiler.desugar; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypes; import org.ballerinalang.model.TreeBuilder; import org.ballerinalang.model.clauses.OrderKeyNode; import org.ballerinalang.model.elements.Flag; @@ -302,7 +299,7 @@ BLangStatementExpression desugar(BLangQueryExpr queryExpr, SymbolEnv env, queryBlock, stmtsToBePropagated); BLangExpression result = streamRef; BLangLiteral isReadonly = ASTBuilderUtil.createLiteral(pos, symTable.booleanType, - Symbols.isFlagOn(queryExpr.getBType().getFlags(), Flags.READONLY)); + Symbols.isFlagOn(queryExpr.getBType().flags, Flags.READONLY)); BType resultType = queryExpr.getBType(); if (queryExpr.isStream) { resultType = streamRef.getBType(); @@ -327,16 +324,14 @@ BLangStatementExpression desugar(BLangQueryExpr queryExpr, SymbolEnv env, result = getStreamFunctionVariableRef(queryBlock, COLLECT_QUERY_FUNCTION, Lists.of(streamRef), pos); } else { BType refType = Types.getImpliedType(queryExpr.getBType()); - SemType refSemType = refType.semType(); - SemType safeType = types.getNilAndErrorLiftType(refSemType); - if (SemTypes.isSubtypeSimpleNotNever(safeType, PredefinedType.XML)) { - if (types.isSubTypeOfReadOnly(refSemType)) { + BType safeType = types.getSafeType(refType, true, true); + if (isXml(safeType)) { + if (types.isSubTypeOfReadOnly(refType, env)) { isReadonly.value = true; } result = getStreamFunctionVariableRef(queryBlock, QUERY_TO_XML_FUNCTION, Lists.of(streamRef, isReadonly), pos); - } else if (PredefinedType.STRING.equals(safeType) || - SemTypes.isSameType(types.typeCtx(), safeType, PredefinedType.STRING_CHAR)) { + } else if (TypeTags.isStringTypeTag(safeType.tag)) { result = getStreamFunctionVariableRef(queryBlock, QUERY_TO_STRING_FUNCTION, Lists.of(streamRef), pos); } else { BType arrayType = refType; @@ -613,11 +608,11 @@ BLangVariableReference addPipeline(BLangBlockStmt blockStmt, Location pos, constraintType = ((BStreamType) refType).constraint; completionType = ((BStreamType) refType).completionType; } - BType constraintTdType = new BTypedescType(symTable.typeEnv(), constraintType, symTable.typeDesc.tsymbol); + BType constraintTdType = new BTypedescType(constraintType, symTable.typeDesc.tsymbol); BLangTypedescExpr constraintTdExpr = new BLangTypedescExpr(); constraintTdExpr.resolvedType = constraintType; constraintTdExpr.setBType(constraintTdType); - BType completionTdType = new BTypedescType(symTable.typeEnv(), completionType, symTable.typeDesc.tsymbol); + BType completionTdType = new BTypedescType(completionType, symTable.typeDesc.tsymbol); BLangTypedescExpr completionTdExpr = new BLangTypedescExpr(); completionTdExpr.resolvedType = completionType; completionTdExpr.setBType(completionTdType); @@ -816,11 +811,11 @@ BLangVariableReference addOrderByFunction(BLangBlockStmt blockStmt, BLangOrderBy BLangArrayLiteral sortFieldsArrayExpr = (BLangArrayLiteral) TreeBuilder.createArrayLiteralExpressionNode(); sortFieldsArrayExpr.exprs = new ArrayList<>(); - sortFieldsArrayExpr.setBType(new BArrayType(symTable.typeEnv(), symTable.anydataType)); + sortFieldsArrayExpr.setBType(new BArrayType(symTable.anydataType)); BLangArrayLiteral sortModesArrayExpr = (BLangArrayLiteral) TreeBuilder.createArrayLiteralExpressionNode(); sortModesArrayExpr.exprs = new ArrayList<>(); - sortModesArrayExpr.setBType(new BArrayType(symTable.typeEnv(), symTable.booleanType)); + sortModesArrayExpr.setBType(new BArrayType(symTable.booleanType)); // Each order-key expression is added to sortFieldsArrayExpr. // Corresponding order-direction is added to sortModesArrayExpr. @@ -848,7 +843,7 @@ BLangVariableReference addGroupByFunction(BLangBlockStmt blockStmt, BLangGroupBy Location pos = groupByClause.pos; BLangArrayLiteral keys = (BLangArrayLiteral) TreeBuilder.createArrayLiteralExpressionNode(); keys.exprs = new ArrayList<>(); - keys.setBType(new BArrayType(symTable.typeEnv(), symTable.stringType)); + keys.setBType(new BArrayType(symTable.stringType)); for (BLangGroupingKey key :groupByClause.groupingKeyList) { if (key.variableDef == null) { keys.exprs.add(createStringLiteral(key.pos, key.variableRef.variableName.value)); @@ -863,7 +858,7 @@ BLangVariableReference addGroupByFunction(BLangBlockStmt blockStmt, BLangGroupBy BLangArrayLiteral nonGroupingKeys = (BLangArrayLiteral) TreeBuilder.createArrayLiteralExpressionNode(); nonGroupingKeys.exprs = new ArrayList<>(); - nonGroupingKeys.setBType(new BArrayType(symTable.typeEnv(), symTable.stringType)); + nonGroupingKeys.setBType(new BArrayType(symTable.stringType)); for (String nonGroupingKey : groupByClause.nonGroupingKeys) { nonGroupingKeys.exprs.add(createStringLiteral(pos, nonGroupingKey)); } @@ -876,7 +871,7 @@ BLangVariableReference addCollectFunction(BLangBlockStmt blockStmt, BLangCollect Location pos = collectClause.pos; BLangArrayLiteral nonGroupingKeys = (BLangArrayLiteral) TreeBuilder.createArrayLiteralExpressionNode(); nonGroupingKeys.exprs = new ArrayList<>(); - nonGroupingKeys.setBType(new BArrayType(symTable.typeEnv(), symTable.stringType)); + nonGroupingKeys.setBType(new BArrayType(symTable.stringType)); for (String nonGroupingKey : collectClause.nonGroupingKeys) { nonGroupingKeys.exprs.add(createStringLiteral(pos, nonGroupingKey)); } @@ -1449,7 +1444,7 @@ private BLangSimpleVarRef defineNilFrameForType(List symbols, BLangB private void addNilValueToFrame(BLangSimpleVarRef frameToAddValueTo, String key, BLangBlockStmt blockStmt, Location pos) { BLangStatement addToFrameStmt = getAddToFrameStmt(pos, frameToAddValueTo, key, - ASTBuilderUtil.createLiteral(pos, symTable.nilType, Names.NIL_VALUE.value)); + ASTBuilderUtil.createLiteral(pos, symTable.nilType, Names.NIL_VALUE)); blockStmt.addStatement(addToFrameStmt); } @@ -1554,8 +1549,7 @@ private BLangValueType getBooleanTypeNode() { */ private BLangUnionTypeNode getFrameErrorNilTypeNode() { BType frameType = getFrameTypeSymbol().type; - BUnionType unionType = - BUnionType.create(symTable.typeEnv(), null, frameType, symTable.errorType, symTable.nilType); + BUnionType unionType = BUnionType.create(null, frameType, symTable.errorType, symTable.nilType); BLangUnionTypeNode unionTypeNode = (BLangUnionTypeNode) TreeBuilder.createUnionTypeNode(); unionTypeNode.setBType(unionType); unionTypeNode.memberTypeNodes.add(getFrameTypeNode()); @@ -1566,7 +1560,7 @@ private BLangUnionTypeNode getFrameErrorNilTypeNode() { } private BLangUnionTypeNode getBooleanErrorTypeNode() { - BUnionType unionType = BUnionType.create(symTable.typeEnv(), null, symTable.errorType, symTable.booleanType); + BUnionType unionType = BUnionType.create(null, symTable.errorType, symTable.booleanType); BLangUnionTypeNode unionTypeNode = (BLangUnionTypeNode) TreeBuilder.createUnionTypeNode(); unionTypeNode.setBType(unionType); unionTypeNode.memberTypeNodes.add(getErrorTypeNode()); @@ -1576,7 +1570,7 @@ private BLangUnionTypeNode getBooleanErrorTypeNode() { } private BLangUnionTypeNode getIntErrorTypeNode() { - BUnionType unionType = BUnionType.create(symTable.typeEnv(), null, symTable.errorType, symTable.intType); + BUnionType unionType = BUnionType.create(null, symTable.errorType, symTable.intType); BLangUnionTypeNode unionTypeNode = (BLangUnionTypeNode) TreeBuilder.createUnionTypeNode(); unionTypeNode.setBType(unionType); unionTypeNode.memberTypeNodes.add(getErrorTypeNode()); @@ -1591,7 +1585,7 @@ private BLangUnionTypeNode getIntErrorTypeNode() { * @return a any & error type node. */ private BLangUnionTypeNode getAnyAndErrorTypeNode() { - BUnionType unionType = BUnionType.create(symTable.typeEnv(), null, symTable.anyType, symTable.errorType); + BUnionType unionType = BUnionType.create(null, symTable.anyType, symTable.errorType); BLangUnionTypeNode unionTypeNode = (BLangUnionTypeNode) TreeBuilder.createUnionTypeNode(); unionTypeNode.memberTypeNodes.add(getAnyTypeNode()); unionTypeNode.memberTypeNodes.add(getErrorTypeNode()); @@ -1744,7 +1738,7 @@ public void visit(BLangCollectContextInvocation collectContextInvocation) { if (isNilReturnInvocationInCollectClause(invocation)) { Location pos = invocation.pos; BLangSimpleVarRef restArg = (BLangSimpleVarRef) invocation.argExprs.get(0); - BType invocationType = BUnionType.create(symTable.typeEnv(), null, invocation.getBType(), symTable.nilType); + BType invocationType = BUnionType.create(null, invocation.getBType(), symTable.nilType); BLangSimpleVariable tempResultVar = ASTBuilderUtil.createVariable(pos, "$invocationResult$", invocationType, null, new BVarSymbol(0, Names.fromString("$invocationResult$"), this.env.scope.owner.pkgID, invocationType, this.env.scope.owner, pos, VIRTUAL)); @@ -1818,7 +1812,7 @@ private BType changeSeqSymbolType(BSymbol symbol) { BType elementType = ((BSequenceType) symbol.type).elementType; List tupleMembers = new ArrayList<>(1); tupleMembers.add(new BTupleMember(elementType, Symbols.createVarSymbolForTupleMember(elementType))); - symbol.type = new BTupleType(symTable.typeEnv(), null, tupleMembers, elementType, 0); + symbol.type = new BTupleType(null, tupleMembers, elementType, 0); } return symbol.type; } 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 7f2c356e2c2c..da39e5efca41 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 @@ -241,7 +241,7 @@ private BType getListenerTypeWithoutError(BType type) { } members.add(memberType); } - return BUnionType.create(symTable.typeEnv(), null, members); + return BUnionType.create(null, members); } return type; } @@ -268,7 +268,7 @@ private void addMethodInvocation(Location pos, BLangSimpleVarRef varRef, BInvoka // call is generated in BIRGen. Casting to the first listener type should be fine as actual method invocation // is based on the value rather than the type. BType listenerType = getListenerType(varRef.getBType()); - if (!types.isSameTypeIncludingTags(listenerType, varRef.getBType())) { + if (!types.isSameType(listenerType, varRef.getBType())) { BLangTypeConversionExpr castExpr = (BLangTypeConversionExpr) TreeBuilder.createTypeConversionNode(); castExpr.expr = varRef; castExpr.setBType(listenerType); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/TransactionDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/TransactionDesugar.java index 4c3137efc1f3..d81adba0d815 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/TransactionDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/TransactionDesugar.java @@ -205,7 +205,7 @@ private BLangBlockStmt desugarTransactionBody(BLangTransaction transactionNode, BType transactionReturnType = symTable.errorOrNilType; // wraps content within transaction body inside a statement expression - BLangLiteral nilLiteral = ASTBuilderUtil.createLiteral(pos, symTable.nilType, Names.NIL_VALUE.value); + BLangLiteral nilLiteral = ASTBuilderUtil.createLiteral(pos, symTable.nilType, Names.NIL_VALUE); BLangStatementExpression statementExpression = createStatementExpression(transactionNode.transactionBody, nilLiteral); statementExpression.setBType(symTable.nilType); @@ -373,7 +373,7 @@ public void startTransactionCoordinatorOnce(SymbolEnv env, Location pos) { } BLangSimpleVariableDef createPrevAttemptInfoVarDef(SymbolEnv env, Location pos) { - BLangLiteral nilLiteral = ASTBuilderUtil.createLiteral(pos, symTable.nilType, Names.NIL_VALUE.value); + BLangLiteral nilLiteral = ASTBuilderUtil.createLiteral(pos, symTable.nilType, Names.NIL_VALUE); BLangSimpleVariable prevAttemptVariable = createPrevAttemptVariable(env, pos); prevAttemptVariable.expr = nilLiteral; return ASTBuilderUtil.createVariableDef(pos, prevAttemptVariable); @@ -384,7 +384,7 @@ private BLangSimpleVariable createPrevAttemptVariable(SymbolEnv env, Location po BSymbol infoRecordSymbol = symResolver. lookupSymbolInMainSpace(symTable.pkgEnvMap.get(symTable.langTransactionModuleSymbol), TRANSACTION_INFO_RECORD); - BType infoRecordType = BUnionType.create(symTable.typeEnv(), null, infoRecordSymbol.type, symTable.nilType); + BType infoRecordType = BUnionType.create(null, infoRecordSymbol.type, symTable.nilType); BVarSymbol prevAttemptVarSymbol = new BVarSymbol(0, new Name("prevAttempt" + uniqueId), env.scope.owner.pkgID, infoRecordType, env.scope.owner, pos, VIRTUAL); prevAttemptVarSymbol.closure = true; @@ -515,7 +515,7 @@ BLangStatementExpression invokeRollbackFunc(Location pos, BLangExpression rollba BLangExpressionStmt cleanUpTrx = ASTBuilderUtil.createExpressionStmt(pos, rollbackBlockStmt); cleanUpTrx.expr = createCleanupTrxStmt(pos, trxBlockId); BLangStatementExpression rollbackStmtExpr = createStatementExpression(rollbackBlockStmt, - ASTBuilderUtil.createLiteral(pos, symTable.nilType, Names.NIL_VALUE.value)); + ASTBuilderUtil.createLiteral(pos, symTable.nilType, Names.NIL_VALUE)); rollbackStmtExpr.setBType(symTable.nilType); //at this point, @@ -564,7 +564,7 @@ BLangStatementExpression desugar(BLangCommitExpr commitExpr, SymbolEnv env) { createInvocationExprForMethod(pos, commitTransactionInvokableSymbol, args, symResolver); commitTransactionInvocation.argExprs = args; - BType commitReturnType = BUnionType.create(symTable.typeEnv(), null, symTable.stringType, symTable.errorType); + BType commitReturnType = BUnionType.create(null, symTable.stringType, symTable.errorType); BVarSymbol commitTransactionVarSymbol = new BVarSymbol(0, new Name("commitResult"), env.scope.owner.pkgID, commitReturnType, env.scope.owner, pos, VIRTUAL); @@ -611,7 +611,8 @@ BLangStatementExpression desugar(BLangCommitExpr commitExpr, SymbolEnv env) { isTransactionFailedVariable.symbol); List paramTypes = new ArrayList<>(); paramTypes.add(symTable.booleanType); - BInvokableType type = new BInvokableType(symTable.typeEnv(), paramTypes, symTable.booleanType, null); + BInvokableType type = new BInvokableType(paramTypes, symTable.booleanType, + null); BOperatorSymbol notOperatorSymbol = new BOperatorSymbol( Names.fromString(OperatorKind.NOT.value()), symTable.rootPkgSymbol.pkgID, type, symTable.rootPkgSymbol, symTable.builtinPos, VIRTUAL); @@ -639,7 +640,7 @@ BLangStatementExpression desugar(BLangCommitExpr commitExpr, SymbolEnv env) { } private BLangSimpleVariableDef createCommitResultVarDef(SymbolEnv env, Location pos) { - BLangExpression nilLiteral = ASTBuilderUtil.createLiteral(pos, symTable.nilType, Names.NIL_VALUE.value); + BLangExpression nilLiteral = ASTBuilderUtil.createLiteral(pos, symTable.nilType, Names.NIL_VALUE); BVarSymbol outputVarSymbol = new BVarSymbol(0, new Name("$outputVar$"), env.scope.owner.pkgID, symTable.errorOrNilType, env.scope.owner, pos, VIRTUAL); BLangSimpleVariable outputVariable = diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java index 83d503eb31ab..aa698df5108e 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java @@ -911,6 +911,7 @@ private void createAnonymousTypeDefForConstantDeclaration(BLangConstant constant BLangUnaryExpr unaryExpr = createBLangUnaryExpr(unaryConstant.pos, unaryConstant.operator, unaryConstant.expr); unaryExpr.setBType(unaryConstant.expr.getBType()); + unaryExpr.isConstant = true; finiteTypeNode.valueSpace.add(unaryExpr); } finiteTypeNode.pos = identifierPos; @@ -2793,7 +2794,7 @@ public BLangNode transform(ReturnStatementNode returnStmtNode) { } else { BLangLiteral nilLiteral = (BLangLiteral) TreeBuilder.createLiteralExpression(); nilLiteral.pos = getPosition(returnStmtNode); - nilLiteral.value = Names.NIL_VALUE.value; + nilLiteral.value = Names.NIL_VALUE; nilLiteral.setBType(symTable.nilType); bLReturn.expr = nilLiteral; } @@ -6114,7 +6115,6 @@ private BLangLiteral createSimpleLiteral(Node literal, boolean isFiniteType) { typeTag = TypeTags.INT; value = getIntegerLiteral(literal, textValue); originalValue = textValue; - // TODO: can we fix below? if (literalTokenKind == SyntaxKind.HEX_INTEGER_LITERAL_TOKEN && withinByteRange(value)) { typeTag = TypeTags.BYTE; } @@ -6184,9 +6184,9 @@ private BLangLiteral createSimpleLiteral(Node literal, boolean isFiniteType) { originalValue = textValue; bLiteral = (BLangLiteral) TreeBuilder.createLiteralExpression(); } else if (type == SyntaxKind.NIL_LITERAL) { - originalValue = Names.NIL_VALUE.value; + originalValue = "()"; typeTag = TypeTags.NIL; - value = Names.NIL_VALUE.value; + value = "()"; bLiteral = (BLangLiteral) TreeBuilder.createLiteralExpression(); } else if (type == SyntaxKind.NULL_LITERAL) { originalValue = "null"; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java index cccd4bdf22b0..75db8cf2452f 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java @@ -399,7 +399,6 @@ private void cloneBLangType(BLangType source, BLangType clone) { clone.nullable = source.nullable; clone.grouped = source.grouped; clone.flagSet = cloneSet(source.flagSet, Flag.class); - clone.defn = source.defn; } private > EnumSet cloneSet(Set source, Class elementType) { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java index 9c5229a36704..a3920e3d2720 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java @@ -19,10 +19,6 @@ import io.ballerina.identifier.Utils; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.Core; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.Value; import org.ballerinalang.compiler.CompilerPhase; import org.ballerinalang.model.elements.Flag; import org.ballerinalang.model.elements.PackageID; @@ -271,7 +267,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.Set; import java.util.function.Predicate; import java.util.stream.Stream; @@ -1091,8 +1086,16 @@ private HashMap getConstValue(BLangConstPattern constPattern) { } private Object getConstValueFromFiniteType(BFiniteType type) { - Optional value = Core.singleShape(type.semType()); - return value.map(v -> v.value).orElse(null); + if (type.getValueSpace().size() == 1) { + BLangExpression expr = type.getValueSpace().iterator().next(); + switch (expr.getKind()) { + case NUMERIC_LITERAL: + return ((BLangNumericLiteral) expr).value; + case LITERAL: + return ((BLangLiteral) expr).value; + } + } + return null; } private boolean checkSimilarListMatchPattern(BLangListMatchPattern firstListMatchPattern, @@ -1399,8 +1402,10 @@ public void visit(BLangVarBindingPatternMatchPattern varBindingPattern, Analyzer if (varBindingPattern.matchExpr == null) { return; } - varBindingPattern.isLastPattern = types.isAssignable(varBindingPattern.matchExpr.getBType(), - varBindingPattern.getBType()); + varBindingPattern.isLastPattern = types.isSameType(varBindingPattern.matchExpr.getBType(), + varBindingPattern.getBType()) || types.isAssignable( + varBindingPattern.matchExpr.getBType(), + varBindingPattern.getBType()); } } @@ -1529,8 +1534,7 @@ public void visit(BLangFail failNode, AnalyzerData data) { if (!data.failureHandled) { BType exprType = data.env.enclInvokable.getReturnTypeNode().getBType(); data.returnTypes.peek().add(exprType); - BType type = failNode.expr.getBType(); - if (!types.isSubtype(types.getErrorIntersection(type.semType()), exprType.semType())) { + if (!types.isAssignable(types.getErrorTypes(failNode.expr.getBType()), exprType)) { dlog.error(failNode.pos, DiagnosticErrorCode.FAIL_EXPR_NO_MATCHING_ERROR_RETURN_IN_ENCL_INVOKABLE); } } @@ -1649,7 +1653,7 @@ private void checkForExportableType(BTypeSymbol symbol, Location pos, HashSet 1) { - sendTypeWithNoMsgIgnored = BUnionType.create(symTable.typeEnv(), null, returnTypeAndSendType); + sendTypeWithNoMsgIgnored = BUnionType.create(null, returnTypeAndSendType); } else { sendTypeWithNoMsgIgnored = exprType; } @@ -2094,7 +2098,7 @@ private void setWorkerSendSendTypeDetails(BLangWorkerSendExpr workerSendExpr, BT lookup(Names.fromString(NO_MESSAGE_ERROR_TYPE)).symbol; returnTypeAndSendType.add(noMsgErrSymbol.getType()); if (returnTypeAndSendType.size() > 1) { - sendType = BUnionType.create(symTable.typeEnv(), null, returnTypeAndSendType); + sendType = BUnionType.create(null, returnTypeAndSendType); } else { sendType = exprType; } @@ -2139,7 +2143,7 @@ public void visit(BLangWorkerSyncSendExpr syncSendExpr, AnalyzerData data) { was.hasErrors = true; } - syncSendExpr.setBType(BUnionType.create(symTable.typeEnv(), null, symTable.nilType, symTable.errorType)); + syncSendExpr.setBType(BUnionType.create(null, symTable.nilType, symTable.errorType)); boolean withinIfOrOnFail = !invalidSendPos && withinIfOrOnFail(data.env.enclInvokable.body, data.env.node); setWorkerSendSendTypeDetails(syncSendExpr, syncSendExpr.expr.getBType(), withinIfOrOnFail, data); was.addWorkerAction(syncSendExpr); @@ -2250,7 +2254,7 @@ public BType createAccumulatedErrorTypeForMatchingSyncSend(AnalyzerData data, Lo returnTypeAndSendType.add(symTable.nilType); if (returnTypeAndSendType.size() > 1) { - return BUnionType.create(symTable.typeEnv(), null, returnTypeAndSendType); + return BUnionType.create(null, returnTypeAndSendType); } else { return symTable.nilType; } @@ -2275,7 +2279,25 @@ private void addErrorTypesToSet(BType returnType, LinkedHashSet errorType } private boolean hasNonErrorType(BType returnType) { - return !Core.isSubtypeSimple(returnType.semType(), PredefinedType.ERROR); + if (returnType == null) { + return false; + } + + BType effType = Types.getImpliedType(types.getTypeWithEffectiveIntersectionTypes(returnType)); + if (effType.tag == TypeTags.ERROR) { + return false; + } + + if (effType.tag == TypeTags.UNION) { + for (BType memberType : ((BUnionType) returnType).getMemberTypes()) { + if (hasNonErrorType(memberType)) { + return true; + } + } + return false; + } + + return true; } @Override @@ -3318,14 +3340,14 @@ public void visit(BLangCheckedExpr checkedExpr, AnalyzerData data) { BType exprType = Types.getImpliedType(enclInvokable.getReturnTypeNode().getBType()); BType checkedExprType = checkedExpr.expr.getBType(); - SemType errorType = types.getErrorIntersection(checkedExprType.semType()); + BType errorType = types.getErrorTypes(checkedExprType); - if (Core.isNever(errorType)) { + if (errorType == symTable.semanticError) { return; } boolean ignoreErrForCheckExpr = data.withinQuery && data.queryConstructType == Types.QueryConstructType.STREAM; - if (!data.failureHandled && !ignoreErrForCheckExpr && !types.isSubtype(errorType, exprType.semType()) + if (!data.failureHandled && !ignoreErrForCheckExpr && !types.isAssignable(errorType, exprType) && !types.isNeverTypeOrStructureTypeWithARequiredNeverMember(checkedExprType)) { dlog.error(checkedExpr.pos, DiagnosticErrorCode.CHECKED_EXPR_NO_MATCHING_ERROR_RETURN_IN_ENCL_INVOKABLE); @@ -3524,7 +3546,7 @@ public void visit(BLangTypeTestExpr typeTestExpr, AnalyzerData data) { // It'll be only possible iff, the target type has been assigned to the source // variable at some point. To do that, a value of target type should be assignable // to the type of the source variable. - if (!types.intersectionExists(expr.getBType().semType(), typeNodeType.semType())) { + if (!intersectionExists(expr, typeNodeType, data, typeTestExpr.pos)) { dlog.error(typeTestExpr.pos, DiagnosticErrorCode.INCOMPATIBLE_TYPE_CHECK, exprType, typeNodeType); } } @@ -3553,6 +3575,20 @@ private void logDeprecatedWaring(String deprecatedConstruct, BSymbol symbol, Loc dlog.warning(pos, DiagnosticWarningCode.USAGE_OF_DEPRECATED_CONSTRUCT, deprecatedConstruct); } + private boolean intersectionExists(BLangExpression expression, BType testType, AnalyzerData data, + Location intersectionPos) { + BType expressionType = expression.getBType(); + + BType intersectionType = types.getTypeIntersection( + Types.IntersectionContext.typeTestIntersectionExistenceContext(intersectionPos), + expressionType, testType, data.env); + + // any and readonly has an intersection + return (intersectionType != symTable.semanticError) || + (Types.getImpliedType(expressionType).tag == TypeTags.ANY && + Types.getImpliedType(testType).tag == TypeTags.READONLY); + } + @Override public void visit(BLangInferredTypedescDefaultNode inferTypedescExpr, AnalyzerData data) { /* Ignore */ @@ -3781,7 +3817,7 @@ private void typeCheckAlternateReceive(BLangAlternateWorkerReceive altWorkerRv) BType actualType; if (altTypes.size() > 1) { - actualType = BUnionType.create(symTable.typeEnv(), null, altTypes); + actualType = BUnionType.create(null, altTypes); } else { actualType = altTypes.iterator().next(); } @@ -4259,7 +4295,7 @@ private void validateInvocationInMatchGuard(BLangInvocation invocation) { BType matchedExprType = matchedExpr.getBType(); if (types.isInherentlyImmutableType(matchedExprType) || - Symbols.isFlagOn(matchedExprType.getFlags(), Flags.READONLY)) { + Symbols.isFlagOn(matchedExprType.flags, Flags.READONLY)) { return; } @@ -4283,7 +4319,7 @@ private void validateInvocationInMatchGuard(BLangInvocation invocation) { BLangExpression streamImplementorExpr = argsExpr.get(0); BType type = streamImplementorExpr.getBType(); - if (!types.isInherentlyImmutableType(type) && !Symbols.isFlagOn(type.getFlags(), Flags.READONLY)) { + if (!types.isInherentlyImmutableType(type) && !Symbols.isFlagOn(type.flags, Flags.READONLY)) { dlog.error(streamImplementorExpr.pos, DiagnosticErrorCode.INVALID_CALL_WITH_MUTABLE_ARGS_IN_MATCH_GUARD); } @@ -4308,7 +4344,7 @@ private void validateInvocationInMatchGuard(BLangInvocation invocation) { if (type != symTable.semanticError && !types.isInherentlyImmutableType(type) && - !Symbols.isFlagOn(type.getFlags(), Flags.READONLY)) { + !Symbols.isFlagOn(type.flags, Flags.READONLY)) { dlog.error(arg.pos, DiagnosticErrorCode.INVALID_CALL_WITH_MUTABLE_ARGS_IN_MATCH_GUARD); } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/ConditionResolver.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/ConditionResolver.java index a2fddc62af1f..7b667249be30 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/ConditionResolver.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/ConditionResolver.java @@ -17,8 +17,6 @@ */ package org.wso2.ballerinalang.compiler.semantics.analyzer; -import io.ballerina.types.Core; -import io.ballerina.types.Value; import org.ballerinalang.model.tree.OperatorKind; import org.wso2.ballerinalang.compiler.semantics.model.SymbolTable; import org.wso2.ballerinalang.compiler.semantics.model.symbols.SymTag; @@ -31,9 +29,8 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangSimpleVarRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangTypeTestExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangUnaryExpr; -import org.wso2.ballerinalang.compiler.util.TypeTags; -import java.util.Optional; +import java.util.HashSet; /** * This analyzes the condition in if statement and while statement. @@ -54,11 +51,9 @@ static BType checkConstCondition(Types types, SymbolTable symTable, BLangExpress if (value instanceof Boolean) { return value == Boolean.TRUE ? symTable.trueType : symTable.falseType; } - return BFiniteType.newSingletonBFiniteType(null, - SemTypeHelper.resolveSingletonType((BLangLiteral) condition)); + return new BFiniteType(null, new HashSet<>() { { add(condition); } }); case NUMERIC_LITERAL: - return BFiniteType.newSingletonBFiniteType(null, - SemTypeHelper.resolveSingletonType((BLangLiteral) condition)); + return new BFiniteType(null, new HashSet<>() { { add(condition); } }); case TYPE_TEST_EXPR: BLangTypeTestExpr typeTestExpr = (BLangTypeTestExpr) condition; BType exprType = typeTestExpr.expr.getBType(); @@ -124,21 +119,11 @@ static BType checkConstCondition(Types types, SymbolTable symTable, BLangExpress BLangSimpleVarRef simpleVarRef = (BLangSimpleVarRef) condition; BType type = (simpleVarRef.symbol.tag & SymTag.CONSTANT) == SymTag.CONSTANT ? simpleVarRef.symbol.type : condition.getBType(); - BType baseType = Types.getImpliedType(type); - - if (baseType.tag != TypeTags.FINITE) { - return symTable.semanticError; - } - - Optional val = Core.singleShape(baseType.semType()); - if (val.isEmpty()) { + if (!types.isSingletonType(type)) { return symTable.semanticError; } - - if (val.get().value instanceof Boolean) { - return val.get().value == Boolean.TRUE ? symTable.trueType : symTable.falseType; - } - return baseType; + return checkConstCondition(types, symTable, ((BFiniteType) Types.getImpliedType(type)) + .getValueSpace().iterator().next()); default: return symTable.semanticError; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/ConstantTypeChecker.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/ConstantTypeChecker.java index 07a643dfa4b1..19b37c0e15c3 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/ConstantTypeChecker.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/ConstantTypeChecker.java @@ -19,12 +19,6 @@ import io.ballerina.tools.diagnostics.DiagnosticCode; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.Core; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypes; -import io.ballerina.types.Value; -import io.ballerina.types.subtypedata.StringSubtype; import org.ballerinalang.model.TreeBuilder; import org.ballerinalang.model.elements.Flag; import org.ballerinalang.model.elements.PackageID; @@ -53,6 +47,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BAnyType; import org.wso2.ballerinalang.compiler.semantics.model.types.BAnydataType; import org.wso2.ballerinalang.compiler.semantics.model.types.BArrayType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BBuiltInRefType; import org.wso2.ballerinalang.compiler.semantics.model.types.BErrorType; import org.wso2.ballerinalang.compiler.semantics.model.types.BField; import org.wso2.ballerinalang.compiler.semantics.model.types.BFiniteType; @@ -63,6 +58,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BJSONType; import org.wso2.ballerinalang.compiler.semantics.model.types.BMapType; import org.wso2.ballerinalang.compiler.semantics.model.types.BNeverType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BNilType; import org.wso2.ballerinalang.compiler.semantics.model.types.BNoType; import org.wso2.ballerinalang.compiler.semantics.model.types.BObjectType; import org.wso2.ballerinalang.compiler.semantics.model.types.BPackageType; @@ -115,13 +111,11 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.function.BiFunction; import static org.ballerinalang.model.symbols.SymbolOrigin.SOURCE; import static org.ballerinalang.model.symbols.SymbolOrigin.VIRTUAL; -import static org.wso2.ballerinalang.compiler.semantics.analyzer.SemTypeHelper.singleShapeBroadType; /** * Resolve the value and check the type of constant expression. @@ -154,7 +148,7 @@ public ConstantTypeChecker(CompilerContext context) { this.types = Types.getInstance(context); this.anonymousModelHelper = BLangAnonymousModelHelper.getInstance(context); this.typeChecker = TypeChecker.getInstance(context); - this.typeResolver = TypeResolver.getInstance(context);; + this.typeResolver = TypeResolver.getInstance(context); this.fillMembers = FillMembers.getInstance(context); } @@ -267,7 +261,7 @@ public void visit(BLangLiteral literalExpr, AnalyzerData data) { return; } - BType finiteType = getFiniteType(literalExpr.value, data.constantSymbol, literalType); + BType finiteType = getFiniteType(literalExpr.value, data.constantSymbol, literalExpr.pos, literalType); if (data.compoundExprCount == 0 && types.typeIncompatible(literalExpr.pos, finiteType, data.expType)) { data.resultType = symTable.semanticError; @@ -281,14 +275,14 @@ private BType rewriteByteArrayLiteral(BLangLiteral literalExpr, AnalyzerData dat List memberTypes = new ArrayList<>(); for (byte b : values) { - memberTypes.add(getFiniteType(Byte.toUnsignedLong(b), data.constantSymbol, symTable.intType)); + memberTypes.add(getFiniteType(Byte.toUnsignedLong(b), data.constantSymbol, literalExpr.pos, + symTable.intType)); } BType expType = Types.getImpliedType(data.expType); if (expType.tag == TypeTags.ARRAY && ((BArrayType) expType).state == BArrayState.INFERRED) { - BArrayType expArrayType = (BArrayType) expType; - expArrayType.setSize(memberTypes.size()); - expArrayType.state = BArrayState.CLOSED; + ((BArrayType) expType).size = memberTypes.size(); + ((BArrayType) expType).state = BArrayState.CLOSED; } return createNewTupleType(literalExpr.pos, memberTypes, data); @@ -465,7 +459,7 @@ public void visit(BLangBinaryExpr binaryExpr, AnalyzerData data) { data.resultType = symTable.semanticError; return; } - BType finiteType = getFiniteType(resolvedValue, constantSymbol, resultType); + BType finiteType = getFiniteType(resolvedValue, constantSymbol, pos, resultType); if (data.compoundExprCount == 0 && types.typeIncompatible(pos, finiteType, expType)) { data.resultType = symTable.semanticError; return; @@ -502,13 +496,14 @@ public void visit(BLangUnaryExpr unaryExpr, AnalyzerData data) { } BConstantSymbol constantSymbol = data.constantSymbol; - Object resolvedValue = evaluateUnaryOperator((BFiniteType) actualType, resultType, unaryExpr.operator, data); + Object resolvedValue = evaluateUnaryOperator((BFiniteType) actualType, resultType, + unaryExpr.operator, data); if (resolvedValue == null) { data.resultType = symTable.semanticError; return; } - BType finiteType = getFiniteType(resolvedValue, constantSymbol, resultType); + BType finiteType = getFiniteType(resolvedValue, constantSymbol, unaryExpr.pos, resultType); if (data.compoundExprCount == 0 && types.typeIncompatible(unaryExpr.pos, finiteType, data.expType)) { data.resultType = symTable.semanticError; return; @@ -518,7 +513,7 @@ public void visit(BLangUnaryExpr unaryExpr, AnalyzerData data) { private BRecordType createNewRecordType(BRecordTypeSymbol symbol, LinkedHashMap inferredFields, AnalyzerData data) { - BRecordType recordType = new BRecordType(symTable.typeEnv(), symbol); + BRecordType recordType = new BRecordType(symbol); recordType.restFieldType = symTable.noType; recordType.fields = inferredFields; symbol.type = recordType; @@ -542,8 +537,8 @@ private BType checkMappingConstructorCompatibility(BType expType, BLangRecordLit } if (tag == TypeTags.INTERSECTION) { - return checkMappingConstructorCompatibility(((BIntersectionType) expType).effectiveType, mappingConstructor, - data); + return checkMappingConstructorCompatibility(((BIntersectionType) expType).effectiveType, + mappingConstructor, data); } BType possibleType = getMappingConstructorCompatibleNonUnionType(expType, data); @@ -619,7 +614,7 @@ private BType checkMappingConstructorCompatibilityForUnionType(BType expType, BL mappingConstructor, data); if (memCompatibiltyType != symTable.semanticError && dlog.errorCount() == 0 && - types.isUniqueType(compatibleTypes, listCompatibleMemType)) { + isUniqueType(compatibleTypes, listCompatibleMemType)) { compatibleTypes.add(listCompatibleMemType); } } @@ -647,15 +642,15 @@ private BType getMappingConstructorCompatibleNonUnionType(BType type, AnalyzerDa case TypeTags.READONLY: return type; case TypeTags.JSON: - return !Symbols.isFlagOn(type.getFlags(), Flags.READONLY) ? symTable.mapJsonType : + return !Symbols.isFlagOn(type.flags, Flags.READONLY) ? symTable.mapJsonType : ImmutableTypeCloner.getEffectiveImmutableType(null, types, symTable.mapJsonType, data.env, symTable, anonymousModelHelper, names); case TypeTags.ANYDATA: - return !Symbols.isFlagOn(type.getFlags(), Flags.READONLY) ? symTable.mapAnydataType : + return !Symbols.isFlagOn(type.flags, Flags.READONLY) ? symTable.mapAnydataType : ImmutableTypeCloner.getEffectiveImmutableType(null, types, symTable.mapAnydataType, data.env, symTable, anonymousModelHelper, names); case TypeTags.ANY: - return !Symbols.isFlagOn(type.getFlags(), Flags.READONLY) ? symTable.mapAllType : + return !Symbols.isFlagOn(type.flags, Flags.READONLY) ? symTable.mapAllType : ImmutableTypeCloner.getEffectiveImmutableType(null, types, symTable.mapAllType, data.env, symTable, anonymousModelHelper, names); case TypeTags.INTERSECTION: @@ -763,22 +758,20 @@ private BType validateMapTypeAndInferredType(BLangRecordLiteral mappingConstruct BLangRecordLiteral.BLangRecordKeyValueField keyValue = (BLangRecordLiteral.BLangRecordKeyValueField) field; BLangRecordLiteral.BLangRecordKey key = keyValue.key; BType fieldName = checkConstExpr(key.expr, data); - if (fieldName.tag == TypeTags.FINITE) { - SemType semtype = fieldName.semType(); - if (SemTypes.isSubtypeSimple(semtype, PredefinedType.STRING)) { - Optional str = StringSubtype.stringSubtypeSingleValue(Core.stringSubtype(semtype)); - if (str.isPresent()) { - exprToCheck = keyValue.valueExpr; - if (data.commonAnalyzerData.nonErrorLoggingCheck) { - exprToCheck = nodeCloner.cloneNode(keyValue.valueExpr); - } - BType keyValueType = checkConstExpr(exprToCheck, expType, data); - if (!addFields(inferredFields, Types.getImpliedType(keyValueType), str.get(), key.pos, - recordSymbol)) { - containErrors = true; - } - continue; + if (fieldName.tag == TypeTags.FINITE && ((BFiniteType) fieldName).getValueSpace().size() == 1) { + BLangLiteral fieldNameLiteral = + (BLangLiteral) ((BFiniteType) fieldName).getValueSpace().iterator().next(); + if (fieldNameLiteral.getBType().tag == TypeTags.STRING) { + exprToCheck = keyValue.valueExpr; + if (data.commonAnalyzerData.nonErrorLoggingCheck) { + exprToCheck = nodeCloner.cloneNode(keyValue.valueExpr); } + BType keyValueType = checkConstExpr(exprToCheck, expType, data); + if (!addFields(inferredFields, Types.getImpliedType(keyValueType), + fieldNameLiteral.getValue().toString(), key.pos, recordSymbol)) { + containErrors = true; + } + continue; } } dlog.error(key.pos, DiagnosticErrorCode.INCOMPATIBLE_TYPES, symTable.stringType, fieldName); @@ -905,35 +898,33 @@ private BType validateRecordType(BLangRecordLiteral mappingConstructor, BRecordT BLangRecordLiteral.BLangRecordKeyValueField keyValue = (BLangRecordLiteral.BLangRecordKeyValueField) field; BLangRecordLiteral.BLangRecordKey key = keyValue.key; BType fieldName = checkConstExpr(key.expr, data); - if (fieldName.tag == TypeTags.FINITE) { - SemType semtype = fieldName.semType(); - if (SemTypes.isSubtypeSimple(semtype, PredefinedType.STRING)) { - Optional str = StringSubtype.stringSubtypeSingleValue(Core.stringSubtype(semtype)); - if (str.isPresent()) { - String keyName = str.get(); - if (!targetFields.containsKey(keyName)) { - if (expRecordType.sealed) { - containErrors = true; - dlog.error(keyValue.pos, DiagnosticErrorCode.UNDEFINED_STRUCTURE_FIELD_WITH_TYPE, - key, expRecordType.tsymbol.type.getKind().typeName(), expRecordType); - continue; - } else { - expType = expRecordType.restFieldType; - } - } else { - expType = targetFields.get(keyName).type; - } - exprToCheck = keyValue.valueExpr; - if (data.commonAnalyzerData.nonErrorLoggingCheck) { - exprToCheck = nodeCloner.cloneNode(keyValue.valueExpr); - } - BType keyValueType = checkConstExpr(exprToCheck, expType, data); - if (!addFields(inferredFields, Types.getImpliedType(keyValueType), - keyName, key.pos, recordSymbol)) { + if (fieldName.tag == TypeTags.FINITE && ((BFiniteType) fieldName).getValueSpace().size() == 1) { + BLangLiteral fieldNameLiteral = + (BLangLiteral) ((BFiniteType) fieldName).getValueSpace().iterator().next(); + if (fieldNameLiteral.getBType().tag == TypeTags.STRING) { + String keyName = fieldNameLiteral.getValue().toString(); + if (!targetFields.containsKey(keyName)) { + if (expRecordType.sealed) { containErrors = true; + dlog.error(keyValue.pos, DiagnosticErrorCode.UNDEFINED_STRUCTURE_FIELD_WITH_TYPE, + key, expRecordType.tsymbol.type.getKind().typeName(), expRecordType); + continue; + } else { + expType = expRecordType.restFieldType; } - continue; + } else { + expType = targetFields.get(keyName).type; } + exprToCheck = keyValue.valueExpr; + if (data.commonAnalyzerData.nonErrorLoggingCheck) { + exprToCheck = nodeCloner.cloneNode(keyValue.valueExpr); + } + BType keyValueType = checkConstExpr(exprToCheck, expType, data); + if (!addFields(inferredFields, Types.getImpliedType(keyValueType), + keyName, key.pos, recordSymbol)) { + containErrors = true; + } + continue; } } dlog.error(key.pos, DiagnosticErrorCode.INCOMPATIBLE_TYPES, fieldName, symTable.stringType); @@ -947,6 +938,22 @@ private BType validateRecordType(BLangRecordLiteral mappingConstructor, BRecordT return createNewRecordType(recordSymbol, inferredFields, data); } + private boolean isUniqueType(Iterable typeList, BType type) { + boolean isRecord = type.tag == TypeTags.RECORD; + + for (BType bType : typeList) { + + if (isRecord) { + if (type == bType) { + return false; + } + } else if (types.isSameType(type, bType)) { + return false; + } + } + return true; + } + private boolean validateRequiredFields(BRecordType type, List specifiedFields, Location pos, AnalyzerData data) { HashSet specFieldNames = getFieldNames(specifiedFields, data); @@ -1066,7 +1073,7 @@ private BType checkListConstructorCompatibility(BType expType, BLangListConstruc BType memCompatibiltyType = checkListConstructorCompatibility(listCompatibleMemType, listConstructor, data); if (memCompatibiltyType != symTable.semanticError && dlog.errorCount() == 0 && - types.isUniqueType(compatibleTypes, memCompatibiltyType)) { + isUniqueType(compatibleTypes, memCompatibiltyType)) { compatibleTypes.add(memCompatibiltyType); } } @@ -1094,8 +1101,8 @@ private BType checkListConstructorCompatibility(BType expType, BLangListConstruc } if (tag == TypeTags.INTERSECTION) { - return checkListConstructorCompatibility(((BIntersectionType) expType).effectiveType, listConstructor, - data); + return checkListConstructorCompatibility(((BIntersectionType) expType).effectiveType, + listConstructor, data); } BType possibleType = getListConstructorCompatibleNonUnionType(expType, data); @@ -1127,7 +1134,7 @@ private BType checkArrayType(BArrayType arrayType, BLangListConstructorExpr list switch (spreadOpType.tag) { case TypeTags.ARRAY: - int arraySize = ((BArrayType) spreadOpType).getSize(); + int arraySize = ((BArrayType) spreadOpType).size; if (arraySize >= 0) { listExprSize += arraySize; continue; @@ -1154,12 +1161,12 @@ private BType checkArrayType(BArrayType arrayType, BLangListConstructorExpr list BType eType = arrayType.eType; if (arrayType.state == BArrayState.INFERRED) { - arrayType.setSize(listExprSize); + arrayType.size = listExprSize; arrayType.state = BArrayState.CLOSED; - } else if (arrayType.state != BArrayState.OPEN && arrayType.getSize() != listExprSize) { - if (arrayType.getSize() < listExprSize) { - dlog.error(listConstructor.pos, DiagnosticErrorCode.MISMATCHING_ARRAY_LITERAL_VALUES, - arrayType.getSize(), listExprSize); + } else if (arrayType.state != BArrayState.OPEN && arrayType.size != listExprSize) { + if (arrayType.size < listExprSize) { + dlog.error(listConstructor.pos, DiagnosticErrorCode.MISMATCHING_ARRAY_LITERAL_VALUES, arrayType.size, + listExprSize); return symTable.semanticError; } @@ -1210,7 +1217,7 @@ private BType checkArrayType(BArrayType arrayType, BLangListConstructorExpr list // Create new tuple type using inferred members. BTupleType resultTupleType = createNewTupleType(listConstructor.pos, memberTypes, data); - if (arrayType.state == BArrayState.CLOSED && arrayType.getSize() > listExprSize) { + if (arrayType.state == BArrayState.CLOSED && arrayType.size > listExprSize) { if (!fillMembers.addFillMembers(resultTupleType, arrayType, data)) { return symTable.semanticError; } @@ -1238,7 +1245,7 @@ private BType checkTupleType(BTupleType tupleType, BLangListConstructorExpr list switch (spreadOpType.tag) { case TypeTags.ARRAY: - int arraySize = ((BArrayType) spreadOpType).getSize(); + int arraySize = ((BArrayType) spreadOpType).size; if (arraySize >= 0) { listExprSize += arraySize; continue; @@ -1352,7 +1359,7 @@ private BTupleType createNewTupleType(Location pos, List memberTypes, Ana List members = new ArrayList<>(); memberTypes.forEach(m -> members.add(new BTupleMember(m, Symbols.createVarSymbolForTupleMember(m)))); - BTupleType tupleType = new BTupleType(symTable.typeEnv(), tupleTypeSymbol, members); + BTupleType tupleType = new BTupleType(tupleTypeSymbol, members); tupleType.tsymbol.type = tupleType; return tupleType; } @@ -1379,13 +1386,13 @@ private BType getListConstructorCompatibleNonUnionType(BType type, AnalyzerData TypeTags.TUPLE, TypeTags.READONLY, TypeTags.TYPEDESC -> type; - case TypeTags.JSON -> !Symbols.isFlagOn(type.getFlags(), Flags.READONLY) ? symTable.arrayJsonType : + case TypeTags.JSON -> !Symbols.isFlagOn(type.flags, Flags.READONLY) ? symTable.arrayJsonType : ImmutableTypeCloner.getEffectiveImmutableType(null, types, symTable.arrayJsonType, data.env, symTable, anonymousModelHelper, names); - case TypeTags.ANYDATA -> !Symbols.isFlagOn(type.getFlags(), Flags.READONLY) ? symTable.arrayAnydataType : + case TypeTags.ANYDATA -> !Symbols.isFlagOn(type.flags, Flags.READONLY) ? symTable.arrayAnydataType : ImmutableTypeCloner.getEffectiveImmutableType(null, types, symTable.arrayAnydataType, data.env, symTable, anonymousModelHelper, names); - case TypeTags.ANY -> !Symbols.isFlagOn(type.getFlags(), Flags.READONLY) ? symTable.arrayAllType : + case TypeTags.ANY -> !Symbols.isFlagOn(type.flags, Flags.READONLY) ? symTable.arrayAllType : ImmutableTypeCloner.getEffectiveImmutableType(null, types, symTable.arrayAllType, data.env, symTable, anonymousModelHelper, names); case TypeTags.INTERSECTION -> ((BIntersectionType) type).effectiveType; @@ -1397,7 +1404,7 @@ private BType getBroadType(BType type) { if (type.tag != TypeTags.FINITE) { return type; } - return singleShapeBroadType(type.semType(), symTable).get(); + return ((BFiniteType) type).getValueSpace().iterator().next().getBType(); } private BSymbol getUnaryOpSymbol(BLangUnaryExpr unaryExpr, BType type, AnalyzerData data) { @@ -1415,7 +1422,7 @@ private BSymbol getUnaryOpSymbol(BLangUnaryExpr unaryExpr, BType type, AnalyzerD } if (symbol == symTable.notFoundSymbol) { - exprType = singleShapeBroadType(type.semType(), symTable).get(); + exprType = ((BFiniteType) type).getValueSpace().iterator().next().getBType(); symbol = symResolver.resolveUnaryOperator(unaryExpr.operator, exprType); if (symbol == symTable.notFoundSymbol) { symbol = symResolver.getUnaryOpsForTypeSets(unaryExpr.operator, exprType); @@ -1438,10 +1445,12 @@ private Object calculateSingletonValue(BFiniteType lhs, BFiniteType rhs, Operato return null; } - // See Types.isAllowedConstantType() for supported types. - Object lhsValue = Core.singleShape(lhs.semType()).get().value; - Object rhsValue = Core.singleShape(rhs.semType()).get().value; + BLangLiteral lhsLiteral = (BLangLiteral) lhs.getValueSpace().iterator().next(); + BLangLiteral rhsLiteral = (BLangLiteral) rhs.getValueSpace().iterator().next(); + // See Types.isAllowedConstantType() for supported types. + Object lhsValue = getValue(lhsLiteral); + Object rhsValue = getValue(rhsLiteral); try { switch (kind) { case ADD: @@ -1489,15 +1498,14 @@ private Object getValue(BLangLiteral lhsLiteral) { private Object evaluateUnaryOperator(BFiniteType finiteType, BType type, OperatorKind kind, AnalyzerData data) { // Calculate the value for the unary operation. - Optional optionalValue = Core.singleShape(finiteType.semType()); - if (optionalValue.isEmpty()) { + BLangLiteral lhsLiteral = (BLangLiteral) finiteType.getValueSpace().iterator().next(); + Object value = getValue(lhsLiteral); + if (value == null) { // This is a compilation error. // This is to avoid NPE exceptions in sub-sequent validations. return null; } - Object value = optionalValue.get().value; - try { switch (kind) { case ADD: @@ -1710,6 +1718,13 @@ private BType setLiteralValueAndGetType(BLangLiteral literalExpr, BType expType, // Get the type matching to the tag from the symbol table. BType literalType = symTable.getTypeFromTag(literalExpr.getBType().tag); + if (literalType.tag == TypeTags.STRING && types.isCharLiteralValue((String) literalValue)) { + boolean foundMember = types.isAssignableToFiniteType(symTable.noType, literalExpr); + if (foundMember) { + setLiteralValueForFiniteType(literalExpr, literalType, data); + return literalType; + } + } return literalType; } @@ -1768,13 +1783,15 @@ private BType getIntegerLiteralTypeUsingExpType(BLangLiteral literalExpr, Object literalExpr.value = String.valueOf(literalValue); return symTable.decimalType; case TypeTags.FINITE: - Set broadTypes = SemTypeHelper.broadTypes((BFiniteType) expectedType, symTable); - if (broadTypes.size() == 1) { - return getIntegerLiteralTypeUsingExpType(literalExpr, literalValue, broadTypes.iterator().next()); - } - - BUnionType unionType = new BUnionType(types.typeEnv(), null, new LinkedHashSet<>(broadTypes), false); - return getIntegerLiteralTypeUsingExpType(literalExpr, literalValue, unionType); + Set valueSpace = ((BFiniteType) expectedType).getValueSpace(); + if (valueSpace.size() > 1) { + LinkedHashSet memTypes = new LinkedHashSet<>(); + valueSpace.forEach(memExpr -> memTypes.add(memExpr.getBType())); + BUnionType unionType = new BUnionType(null, memTypes, false, false); + return getIntegerLiteralTypeUsingExpType(literalExpr, literalValue, unionType); + } + BType expBroadType = ((BFiniteType) expectedType).getValueSpace().iterator().next().getBType(); + return getIntegerLiteralTypeUsingExpType(literalExpr, literalValue, expBroadType); case TypeTags.UNION: BUnionType expectedUnionType = (BUnionType) expectedType; List validTypes = new ArrayList<>(); @@ -1820,6 +1837,12 @@ private BType getIntegerLiteralTypeUsingExpType(BLangLiteral literalExpr, Object return symTable.intType; } + public void setLiteralValueForFiniteType(BLangLiteral literalExpr, BType type, AnalyzerData data) { + types.setImplicitCastExpr(literalExpr, type, data.expType); + data.resultType = type; + literalExpr.isFiniteContext = true; + } + private BType getTypeOfLiteralWithDecimalDiscriminator(BLangLiteral literalExpr, Object literalValue) { literalExpr.value = NumericLiteralSupport.stripDiscriminator(String.valueOf(literalValue)); if (!types.isValidDecimalNumber(literalExpr.pos, literalExpr.value.toString())) { @@ -1857,7 +1880,7 @@ private BType getTypeOfDecimalFloatingPointLiteralUsingExpType(BLangLiteral lite } return symTable.semanticError; case TypeTags.FINITE: - BType expBroadType = singleShapeBroadType(expectedType.semType(), symTable).get(); + BType expBroadType = ((BFiniteType) expectedType).getValueSpace().iterator().next().getBType(); return getTypeOfDecimalFloatingPointLiteralUsingExpType(literalExpr, literalValue, expBroadType); case TypeTags.UNION: BUnionType expectedUnionType = (BUnionType) expectedType; @@ -1898,22 +1921,28 @@ public BType getTypeOfHexFloatingPointLiteral(BLangLiteral literalExpr, Object l return symTable.floatType; } - private BType getFiniteType(Object value, BConstantSymbol constantSymbol, BType type) { - switch (type.tag) { - case TypeTags.INT: - case TypeTags.FLOAT: - case TypeTags.DECIMAL: - case TypeTags.BYTE: - case TypeTags.STRING: - case TypeTags.NIL: - case TypeTags.BOOLEAN: - BTypeSymbol finiteTypeSymbol = Symbols.createTypeSymbol(SymTag.FINITE_TYPE, constantSymbol.flags, - Names.EMPTY, constantSymbol.pkgID, null, constantSymbol.owner, constantSymbol.pos, VIRTUAL); - return BFiniteType.newSingletonBFiniteType(finiteTypeSymbol, - SemTypeHelper.resolveSingletonType(value, type.getKind())); - default: - return type; - } + private BType getFiniteType(Object value, BConstantSymbol constantSymbol, Location pos, BType type) { + return switch (type.tag) { + case TypeTags.INT, + TypeTags.FLOAT, + TypeTags.DECIMAL, + TypeTags.BYTE -> { + BLangNumericLiteral numericLiteral = (BLangNumericLiteral) TreeBuilder.createNumericLiteralExpression(); + yield createFiniteType(constantSymbol, updateLiteral(numericLiteral, value, type, pos)); + } +// case TypeTags.BYTE -> { +// BLangNumericLiteral byteLiteral = (BLangNumericLiteral) TreeBuilder.createNumericLiteralExpression(); +// yield createFiniteType(constantSymbol, updateLiteral(byteLiteral, value, symTable.intType, pos)); +// } + case TypeTags.STRING, + TypeTags.NIL, + TypeTags.BOOLEAN -> { + BLangLiteral literal = (BLangLiteral) TreeBuilder.createLiteralExpression(); + yield createFiniteType(constantSymbol, updateLiteral(literal, value, type, pos)); + } + case TypeTags.UNION -> createFiniteType(constantSymbol, value, (BUnionType) type, pos); + default -> type; + }; } private BLangLiteral getLiteral(Object value, Location pos, BType type) { @@ -1934,8 +1963,38 @@ private BLangLiteral updateLiteral(BLangLiteral literal, Object value, BType typ return literal; } + private BFiniteType createFiniteType(BConstantSymbol constantSymbol, BLangExpression expr) { + BTypeSymbol finiteTypeSymbol = Symbols.createTypeSymbol(SymTag.FINITE_TYPE, constantSymbol.flags, Names.EMPTY, + constantSymbol.pkgID, null, constantSymbol.owner, + constantSymbol.pos, VIRTUAL); + BFiniteType finiteType = new BFiniteType(finiteTypeSymbol); + finiteType.addValue(expr); + finiteType.tsymbol.type = finiteType; + return finiteType; + } + + private BUnionType createFiniteType(BConstantSymbol constantSymbol, Object value, BUnionType type, Location pos) { + LinkedHashSet memberTypes = new LinkedHashSet<>(3); + for (BType memberType : type.getMemberTypes()) { + BTypeSymbol finiteTypeSymbol = Symbols.createTypeSymbol(SymTag.FINITE_TYPE, constantSymbol.flags, + Names.EMPTY, constantSymbol.pkgID, null, constantSymbol.owner, constantSymbol.pos, VIRTUAL); + BFiniteType finiteType = new BFiniteType(finiteTypeSymbol); + Object memberValue = switch (memberType.tag) { + case TypeTags.FLOAT -> value instanceof String ? + Double.parseDouble((String) value) : ((Long) value).doubleValue(); + case TypeTags.DECIMAL -> new BigDecimal(String.valueOf(value)); + default -> value; + }; + finiteType.addValue(getLiteral(memberValue, pos, memberType)); + finiteType.tsymbol.type = finiteType; + memberTypes.add(finiteType); + } + + return BUnionType.create(null, memberTypes); + } + private boolean addFields(LinkedHashMap fields, BType keyValueType, String key, Location pos, - BRecordTypeSymbol recordSymbol) { + BRecordTypeSymbol recordSymbol) { Name fieldName = Names.fromString(key); if (fields.containsKey(key)) { dlog.error(pos, DiagnosticErrorCode.DUPLICATE_KEY_IN_MAPPING_CONSTRUCTOR, TypeKind.RECORD.typeName(), key); @@ -1994,7 +2053,7 @@ private BSymbol getOpSymbolBothUnion(BUnionType lhsType, BUnionType rhsType, lhsType.remove(memberTypeLhs); } if (memberTypes.size() != 1) { - data.resultType = BUnionType.create(symTable.typeEnv(), null, memberTypes); + data.resultType = BUnionType.create(null, memberTypes); } else { data.resultType = memberTypes.iterator().next(); } @@ -2030,7 +2089,7 @@ private BSymbol getOpSymbolLhsUnion(BUnionType lhsType, BType rhsType, lhsType.remove(memberTypeLhs); } if (memberTypes.size() != 1) { - data.resultType = BUnionType.create(symTable.typeEnv(), null, memberTypes); + data.resultType = BUnionType.create(null, memberTypes); } else { data.resultType = memberTypes.iterator().next(); } @@ -2093,7 +2152,7 @@ private BSymbol getOpSymbol(BType lhsType, BType rhsType, BLangBinaryExpr binary /** * @since 2201.7.0 */ - public static class FillMembers extends TypeVisitor { + public static class FillMembers implements TypeVisitor { private static final CompilerContext.Key FILL_MEMBERS_KEY = new CompilerContext.Key<>(); @@ -2131,7 +2190,7 @@ public boolean addFillMembers(BTupleType type, BType expType, AnalyzerData data) int tupleMemberCount = tupleTypes.size(); if (refType.tag == TypeTags.ARRAY) { BArrayType arrayType = (BArrayType) expType; - int noOfFillMembers = arrayType.getSize() - tupleMemberCount; + int noOfFillMembers = arrayType.size - tupleMemberCount; BType fillMemberType = getFillMembers(arrayType.eType, data); if (fillMemberType == symTable.semanticError) { return false; @@ -2177,7 +2236,7 @@ public void visit(BArrayType arrayType) { Flags.asMask(EnumSet.of(Flag.PUBLIC)), Names.EMPTY, data.env.enclPkg.symbol.pkgID, null, data.env.scope.owner, null, SOURCE); if (arrayType.state == BArrayState.OPEN) { - BTupleType resultTupleType = new BTupleType(symTable.typeEnv(), tupleTypeSymbol, new ArrayList<>()); + BTupleType resultTupleType = new BTupleType(tupleTypeSymbol, new ArrayList<>()); tupleTypeSymbol.type = resultTupleType; data.resultType = resultTupleType; return; @@ -2190,18 +2249,23 @@ public void visit(BArrayType arrayType) { data.resultType = symTable.semanticError; return; } - List tupleTypes = new ArrayList<>(arrayType.getSize()); - for (int i = 0; i < arrayType.getSize(); i++) { + List tupleTypes = new ArrayList<>(arrayType.size); + for (int i = 0; i < arrayType.size; i++) { tupleTypes.add(fillMemberType); } List members = new ArrayList<>(); tupleTypes.forEach(m -> members.add(new BTupleMember(m, Symbols.createVarSymbolForTupleMember(m)))); - BTupleType resultTupleType = new BTupleType(symTable.typeEnv(), tupleTypeSymbol, members); + BTupleType resultTupleType = new BTupleType(tupleTypeSymbol, members); tupleTypeSymbol.type = resultTupleType; data.resultType = resultTupleType; } + @Override + public void visit(BBuiltInRefType bBuiltInRefType) { + + } + @Override public void visit(BAnyType bAnyType) { data.resultType = symTable.nilType; @@ -2219,7 +2283,8 @@ public void visit(BErrorType bErrorType) { @Override public void visit(BFiniteType finiteType) { - if (Core.singleShape(finiteType.semType()).isEmpty()) { + Set valueSpace = finiteType.getValueSpace(); + if (valueSpace.size() > 1) { if (finiteType.isNullable()) { // Ex. 1|null data.resultType = symTable.nilType; return; @@ -2250,8 +2315,8 @@ public void visit(BJSONType bjsonType) { public void visit(BMapType bMapType) { BRecordTypeSymbol recordSymbol = constantTypeChecker.createRecordTypeSymbol(data.constantSymbol.pkgID, data.constantSymbol.pos, VIRTUAL, data); - recordSymbol.type = new BRecordType(symTable.typeEnv(), recordSymbol); - BRecordType resultRecordType = new BRecordType(symTable.typeEnv(), recordSymbol); + recordSymbol.type = new BRecordType(recordSymbol); + BRecordType resultRecordType = new BRecordType(recordSymbol); recordSymbol.type = resultRecordType; resultRecordType.tsymbol = recordSymbol; resultRecordType.sealed = true; @@ -2287,7 +2352,7 @@ public void visit(BNeverType bNeverType) { } @Override - public void visitNilType(BType bType) { + public void visit(BNilType bNilType) { data.resultType = symTable.nilType; } @@ -2324,7 +2389,7 @@ public void visit(BTupleType tupleType) { List members = new ArrayList<>(); tupleTypes.forEach(m -> members.add(new BTupleMember(m, Symbols.createVarSymbolForTupleMember(m)))); - BTupleType resultTupleType = new BTupleType(symTable.typeEnv(), tupleTypeSymbol, members); + BTupleType resultTupleType = new BTupleType(tupleTypeSymbol, members); tupleTypeSymbol.type = resultTupleType; data.resultType = resultTupleType; } @@ -2345,7 +2410,7 @@ public void visit(BUnionType unionType) { @Override public void visit(BIntersectionType intersectionType) { - data.resultType = getFillMembers(intersectionType.effectiveType, data); + data.resultType = getFillMembers(intersectionType.getEffectiveType(), data); } @Override @@ -2369,7 +2434,7 @@ public void visit(BRecordType recordType) { return; } } - BRecordType resultRecordType = new BRecordType(symTable.typeEnv(), recordSymbol); + BRecordType resultRecordType = new BRecordType(recordSymbol); recordSymbol.type = resultRecordType; resultRecordType.tsymbol = recordSymbol; resultRecordType.sealed = true; @@ -2385,22 +2450,12 @@ public void visit(BObjectType bObjectType) { } @Override - public void visit(BType type) { // TODO: Can we get rid of refType switch? - switch (type.tag) { - case TypeTags.NIL: - visitNilType(type); - return; - } - - BConstantSymbol constantSymbol = data.constantSymbol; - BTypeSymbol finiteTypeSym = Symbols.createTypeSymbol(SymTag.FINITE_TYPE, constantSymbol.flags, - Names.EMPTY, constantSymbol.pkgID, null, constantSymbol.owner, constantSymbol.pos, VIRTUAL); - + public void visit(BType type) { BType refType = Types.getImpliedType(type); switch (refType.tag) { case TypeTags.BOOLEAN: data.resultType = symTable.falseType; - break; + return; case TypeTags.INT: case TypeTags.SIGNED8_INT: case TypeTags.SIGNED16_INT: @@ -2409,21 +2464,24 @@ public void visit(BType type) { // TODO: Can we get rid of refType switch? case TypeTags.UNSIGNED16_INT: case TypeTags.UNSIGNED32_INT: case TypeTags.BYTE: - data.resultType = BFiniteType.newSingletonBFiniteType(finiteTypeSym, SemTypes.intConst(0)); - break; + data.resultType = constantTypeChecker.getFiniteType(0L, data.constantSymbol, + null, symTable.intType); + return; case TypeTags.FLOAT: - data.resultType = BFiniteType.newSingletonBFiniteType(finiteTypeSym, SemTypes.floatConst(0)); - break; + data.resultType = constantTypeChecker.getFiniteType(0.0d, data.constantSymbol, + null, symTable.floatType); + return; case TypeTags.DECIMAL: - data.resultType = BFiniteType.newSingletonBFiniteType(finiteTypeSym, SemTypes.decimalConst("0")); - break; + data.resultType = constantTypeChecker.getFiniteType(new BigDecimal(0), data.constantSymbol, + null, symTable.decimalType); + return; case TypeTags.STRING: case TypeTags.CHAR_STRING: - data.resultType = BFiniteType.newSingletonBFiniteType(finiteTypeSym, SemTypes.stringConst("")); - break; + data.resultType = constantTypeChecker.getFiniteType("", data.constantSymbol, + null, symTable.stringType); + return; default: data.resultType = symTable.semanticError; - break; } } @@ -2443,10 +2501,11 @@ public BLangConstantValue getConstantValue(BType type) { BType refType = Types.getImpliedType(type); switch (refType.tag) { case TypeTags.FINITE: - BType t = singleShapeBroadType(refType.semType(), symTable).get(); - Value v = Core.singleShape(refType.semType()).get(); - // TODO: 12/9/23 merge t and v to a single object - return new BLangConstantValue (v.value, t); + BLangExpression expr = ((BFiniteType) refType).getValueSpace().iterator().next(); + if (expr.getBType().tag == TypeTags.DECIMAL) { + return new BLangConstantValue ((((BLangNumericLiteral) expr).value).toString(), expr.getBType()); + } + return new BLangConstantValue (((BLangLiteral) expr).value, expr.getBType()); case TypeTags.RECORD: Map fields = new HashMap<>(); LinkedHashMap recordFields = ((BRecordType) refType).fields; @@ -2481,13 +2540,11 @@ public static class ResolveConstantExpressionType extends RESOLVE_CONSTANT_EXPRESSION_TYPE = new CompilerContext.Key<>(); private final Types types; private final ConstantTypeChecker constantTypeChecker; - private final SymbolTable symTable; public ResolveConstantExpressionType(CompilerContext context) { context.put(RESOLVE_CONSTANT_EXPRESSION_TYPE, this); this.types = Types.getInstance(context); this.constantTypeChecker = ConstantTypeChecker.getInstance(context); - this.symTable = SymbolTable.getInstance(context); } public static ResolveConstantExpressionType getInstance(CompilerContext context) { @@ -2542,7 +2599,7 @@ public void visit(BLangLiteral literalExpr, AnalyzerData data) { private void updateBlangExprType(BLangExpression expression, AnalyzerData data) { BType expressionType = expression.getBType(); if (expressionType.tag == TypeTags.FINITE) { - expressionType = singleShapeBroadType(expressionType.semType(), symTable).get(); + expressionType = ((BFiniteType) expressionType).getValueSpace().iterator().next().getBType(); expression.setBType(expressionType); types.setImplicitCastExpr(expression, data.expType, expressionType); return; @@ -2554,13 +2611,13 @@ private void updateBlangExprType(BLangExpression expression, AnalyzerData data) BType targetType; BType expType = data.expType; if (expType.tag == TypeTags.FINITE) { - targetType = singleShapeBroadType(expType.semType(), symTable).get(); + targetType = ((BFiniteType) expType).getValueSpace().iterator().next().getBType(); } else { targetType = expType; } for (BType memberType : ((BUnionType) expressionType).getMemberTypes()) { - BType type = singleShapeBroadType(memberType.semType(), symTable).get(); + BType type = ((BFiniteType) memberType).getValueSpace().iterator().next().getBType(); if (type.tag == targetType.tag || types.isAssignable(memberType, targetType)) { expression.setBType(type); @@ -2614,8 +2671,10 @@ public void visit(BLangRecordLiteral recordLiteral, AnalyzerData data) { (BLangRecordLiteral.BLangRecordKeyValueField) field; BLangRecordLiteral.BLangRecordKey computedKey = computedKeyValue.key; BType fieldName = constantTypeChecker.checkConstExpr(computedKey.expr, data); - expFieldType = getResolvedFieldType(Core.singleShape(fieldName.semType()).get().value, - resolvedType); + BLangLiteral fieldNameLiteral = + (BLangLiteral) ((BFiniteType) fieldName).getValueSpace().iterator().next(); + expFieldType = + getResolvedFieldType(constantTypeChecker.getKeyName(fieldNameLiteral), resolvedType); resolveConstExpr(computedKey.expr, expFieldType, data); resolveConstExpr(keyValueExpr, expFieldType, data); continue; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/ConstantValueResolver.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/ConstantValueResolver.java index ecedc5dd1a37..b929c95ad4fe 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/ConstantValueResolver.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/ConstantValueResolver.java @@ -698,11 +698,13 @@ private boolean isListOrMapping(int tag) { }; } - private BFiniteType createFiniteType(BConstantSymbol constantSymbol, BLangLiteral literal) { + private BFiniteType createFiniteType(BConstantSymbol constantSymbol, BLangExpression expr) { BTypeSymbol finiteTypeSymbol = Symbols.createTypeSymbol(SymTag.FINITE_TYPE, constantSymbol.flags, Names.EMPTY, constantSymbol.pkgID, null, constantSymbol.owner, constantSymbol.pos, VIRTUAL); - return BFiniteType.newSingletonBFiniteType(finiteTypeSymbol, SemTypeHelper.resolveSingletonType(literal)); + BFiniteType finiteType = new BFiniteType(finiteTypeSymbol); + finiteType.addValue(expr); + return finiteType; } private BType checkType(BLangExpression expr, BConstantSymbol constantSymbol, Object value, BType type, @@ -843,7 +845,7 @@ private BType createRecordType(BLangExpression expr, BConstantSymbol constantSym constantSymbol.pkgID, null, constantSymbol.owner, pos, VIRTUAL); recordTypeSymbol.scope = constantSymbol.scope; - BRecordType recordType = new BRecordType(symTable.typeEnv(), recordTypeSymbol); + BRecordType recordType = new BRecordType(recordTypeSymbol); recordType.tsymbol.name = genName; recordType.sealed = true; recordType.restFieldType = new BNoType(TypeTags.NONE); @@ -858,7 +860,7 @@ private BType createRecordType(BLangExpression expr, BConstantSymbol constantSym createTypeDefinition(recordType, pos, env); updateRecordFields(recordType, pos, env); recordType.tsymbol.flags |= Flags.READONLY; - recordType.addFlags(Flags.READONLY); + recordType.flags |= Flags.READONLY; return recordType; } @@ -1024,8 +1026,8 @@ private BType createTupleType(BLangExpression expr, BConstantSymbol constantSymb Names.EMPTY, env.enclPkg.symbol.pkgID, null, env.scope.owner, pos, VIRTUAL); - return ImmutableTypeCloner.getImmutableIntersectionType(pos, types, - new BTupleType(symTable.typeEnv(), tupleTypeSymbol, tupleTypes), env, symTable, anonymousModelHelper, - names, new HashSet<>()); + return ImmutableTypeCloner.getImmutableIntersectionType(pos, types, new BTupleType(tupleTypeSymbol, tupleTypes), + env, symTable, anonymousModelHelper, names, + new HashSet<>()); } } 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 663d32078caf..61f0b0af8994 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 @@ -18,7 +18,6 @@ package org.wso2.ballerinalang.compiler.semantics.analyzer; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.PredefinedType; import org.ballerinalang.compiler.CompilerPhase; import org.ballerinalang.model.elements.Flag; import org.ballerinalang.model.symbols.SymbolKind; @@ -2739,7 +2738,7 @@ private void checkFinalObjectFieldUpdate(BLangFieldBasedAccess fieldAccess) { BType exprType = Types.getImpliedType(expr.getBType()); - if (types.isSubTypeOfBaseType(exprType, PredefinedType.OBJECT) && + if (types.isSubTypeOfBaseType(exprType, TypeTags.OBJECT) && isFinalFieldInAllObjects(fieldAccess.pos, exprType, fieldAccess.field.value)) { dlog.error(fieldAccess.pos, DiagnosticErrorCode.CANNOT_UPDATE_FINAL_OBJECT_FIELD, fieldAccess.symbol.originalName); @@ -2817,7 +2816,11 @@ private void emitUnusedVariableWarnings(Map unusedLocalVariab } private boolean addVarIfInferredTypeIncludesError(BLangSimpleVariable variable) { - if (types.containsErrorType(variable.getBType().semType())) { + BType typeIntersection = + types.getTypeIntersection(Types.IntersectionContext.compilerInternalIntersectionContext(), + variable.getBType(), symTable.errorType, env); + if (typeIntersection != null && + typeIntersection != symTable.semanticError && typeIntersection != symTable.noType) { unusedErrorVarsDeclaredWithVar.put(variable.symbol, variable.pos); return true; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/EffectiveTypePopulator.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/EffectiveTypePopulator.java index 4f25fd82f9fd..9d916811e724 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/EffectiveTypePopulator.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/EffectiveTypePopulator.java @@ -33,6 +33,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BAnyType; import org.wso2.ballerinalang.compiler.semantics.model.types.BAnydataType; import org.wso2.ballerinalang.compiler.semantics.model.types.BArrayType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BBuiltInRefType; import org.wso2.ballerinalang.compiler.semantics.model.types.BErrorType; import org.wso2.ballerinalang.compiler.semantics.model.types.BField; import org.wso2.ballerinalang.compiler.semantics.model.types.BFiniteType; @@ -43,6 +44,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BJSONType; import org.wso2.ballerinalang.compiler.semantics.model.types.BMapType; import org.wso2.ballerinalang.compiler.semantics.model.types.BNeverType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BNilType; import org.wso2.ballerinalang.compiler.semantics.model.types.BNoType; import org.wso2.ballerinalang.compiler.semantics.model.types.BObjectType; import org.wso2.ballerinalang.compiler.semantics.model.types.BPackageType; @@ -81,7 +83,7 @@ * * @since 2201.7.0 */ -public class EffectiveTypePopulator extends TypeVisitor { +public class EffectiveTypePopulator implements TypeVisitor { private static final CompilerContext.Key UPDATE_IMMUTABLE_TYPE_KEY = new CompilerContext.Key<>(); @@ -149,6 +151,11 @@ public void visit(BArrayType bArrayType) { } } + @Override + public void visit(BBuiltInRefType bBuiltInRefType) { + + } + @Override public void visit(BAnyType bAnyType) { @@ -219,7 +226,7 @@ public void visit(BNeverType bNeverType) { } @Override - public void visitNilType(BType bNilType) { + public void visit(BNilType bNilType) { } @@ -264,7 +271,7 @@ public void visit(BTupleType bTupleType) { BTypeSymbol tsymbol = bTupleType.tsymbol; if (tsymbol != null && tsymbol.name != null && !tsymbol.name.value.isEmpty() - && !Symbols.isFlagOn(bTupleType.getFlags(), Flags.EFFECTIVE_TYPE_DEF)) { + && !Symbols.isFlagOn(bTupleType.flags, Flags.EFFECTIVE_TYPE_DEF)) { BLangTupleTypeNode tupleTypeNode = (BLangTupleTypeNode) TreeBuilder.createTupleTypeNode(); tupleTypeNode.setBType(bTupleType); BLangTypeDefinition typeDefinition = TypeDefBuilderHelper.addTypeDefinition(bTupleType, @@ -435,6 +442,11 @@ public void visit(BObjectType bObjectType) { } } + @Override + public void visit(BType bType) { + + } + @Override public void visit(BFutureType bFutureType) { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/IsAnydataUniqueVisitor.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/IsAnydataUniqueVisitor.java new file mode 100644 index 000000000000..cbbc0d8417df --- /dev/null +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/IsAnydataUniqueVisitor.java @@ -0,0 +1,342 @@ +package org.wso2.ballerinalang.compiler.semantics.analyzer; + +import org.wso2.ballerinalang.compiler.semantics.model.UniqueTypeVisitor; +import org.wso2.ballerinalang.compiler.semantics.model.types.BAnnotationType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BAnyType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BAnydataType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BArrayType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BBuiltInRefType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BErrorType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BField; +import org.wso2.ballerinalang.compiler.semantics.model.types.BFiniteType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BFutureType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BHandleType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BIntSubType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BIntersectionType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BInvokableType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BJSONType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BMapType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BNeverType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BNilType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BNoType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BObjectType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BPackageType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BParameterizedType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BRecordType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BStreamType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BStructureType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BTableType; +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.BTypeReferenceType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BTypedescType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BUnionType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BXMLSubType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BXMLType; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangExpression; +import org.wso2.ballerinalang.compiler.util.TypeTags; + +import java.util.HashSet; + +/** + * IsAnydataUniqueVisitor to check if a type is anydata. + * + * This is introduced to handle cyclic unions. + * @since slp4 + */ +public class IsAnydataUniqueVisitor implements UniqueTypeVisitor { + + private final HashSet visited; + private final boolean isAnydata; + + public IsAnydataUniqueVisitor() { + visited = new HashSet<>(); + isAnydata = true; + } + + public IsAnydataUniqueVisitor(HashSet visited) { + this.visited = visited; + isAnydata = true; + } + + private boolean isAnydata(BType type) { + return switch (Types.getImpliedType(type).tag) { + case TypeTags.INT, + TypeTags.BYTE, + TypeTags.FLOAT, + TypeTags.DECIMAL, + TypeTags.STRING, + TypeTags.CHAR_STRING, + TypeTags.BOOLEAN, + TypeTags.JSON, + TypeTags.XML, + TypeTags.XML_TEXT, + TypeTags.XML_ELEMENT, + TypeTags.XML_COMMENT, + TypeTags.XML_PI, + TypeTags.NIL, + TypeTags.NEVER, + TypeTags.ANYDATA, + TypeTags.SIGNED8_INT, + TypeTags.SIGNED16_INT, + TypeTags.SIGNED32_INT, + TypeTags.UNSIGNED8_INT, + TypeTags.UNSIGNED16_INT, + TypeTags.UNSIGNED32_INT, + TypeTags.REGEXP -> true; + default -> false; + }; + } + + @Override + public boolean isVisited(BType type) { + return visited.contains(type); + } + + @Override + public void reset() { + visited.clear(); + } + + @Override + public Boolean visit(BAnnotationType type) { + return isAnydata(type); + } + + @Override + public Boolean visit(BArrayType type) { + if (isVisited(type)) { + return isAnydata; + } + visited.add(type); + return visit(type.eType); + } + + @Override + public Boolean visit(BBuiltInRefType type) { + return isAnydata(type); + } + + @Override + public Boolean visit(BAnyType type) { + return isAnydata(type); + } + + @Override + public Boolean visit(BAnydataType type) { + return isAnydata(type); + } + + @Override + public Boolean visit(BErrorType type) { + return isAnydata(type); + } + + @Override + public Boolean visit(BInvokableType type) { + return isAnydata(type); + } + + @Override + public Boolean visit(BJSONType type) { + return isAnydata(type); + } + + @Override + public Boolean visit(BMapType type) { + if (isVisited(type)) { + return isAnydata; + } + visited.add(type); + return visit(type.constraint); + } + + @Override + public Boolean visit(BStreamType type) { + return isAnydata(type); + } + + @Override + public Boolean visit(BTypedescType type) { + return isAnydata(type); + } + + @Override + public Boolean visit(BParameterizedType type) { + return isAnydata(type); + } + + @Override + public Boolean visit(BNeverType type) { + return isAnydata(type); + } + + @Override + public Boolean visit(BNilType type) { + return isAnydata(type); + } + + @Override + public Boolean visit(BNoType type) { + return isAnydata(type); + } + + @Override + public Boolean visit(BPackageType type) { + return isAnydata(type); + } + + @Override + public Boolean visit(BStructureType type) { + return isAnydata(type); + } + + @Override + public Boolean visit(BTupleType type) { + if (type.isAnyData != null) { + return type.isAnyData; + } + if (!visited.add(type)) { + return isAnydata; + } + for (BType memberType : type.getTupleTypes()) { + if (!visit(memberType)) { + type.isAnyData = false; + return false; + } + } + type.isAnyData = (type.restType == null) || visit(type.restType); + return isAnydata; + } + + @Override + public Boolean visit(BIntersectionType type) { + return visit(type.effectiveType); + } + + @Override + public Boolean visit(BTypeReferenceType type) { + return visit(type.referredType); + } + + @Override + public Boolean visit(BXMLType type) { + return isAnydata(type); + } + + @Override + public Boolean visit(BTableType type) { + return visit(type.constraint); + } + + @Override + public Boolean visit(BFiniteType type) { + if (type.isAnyData != null) { + return type.isAnyData; + } + for (BLangExpression value : type.getValueSpace()) { + if (!visit(value.getBType())) { + type.isAnyData = false; + return false; + } + } + type.isAnyData = true; + return isAnydata; + } + + @Override + public Boolean visit(BObjectType type) { + return isAnydata(type); + } + + @Override + public Boolean visit(BUnionType type) { + if (type.isAnyData != null) { + return type.isAnyData; + } + if (isVisited(type)) { + return isAnydata; + } + visited.add(type); + for (BType member : type.getMemberTypes()) { + if (!visit(member)) { + type.isAnyData = false; + return false; + } + } + type.isAnyData = isAnydata; + return isAnydata; + } + + @Override + public Boolean visit(BRecordType type) { + if (type.isAnyData != null) { + return type.isAnyData; + } + if (isVisited(type)) { + return isAnydata; + } + visited.add(type); + for (BField field : type.fields.values()) { + if (!visit(field.type)) { + type.isAnyData = false; + return false; + } + } + + if (!type.sealed && (type.restFieldType == null)) { + return false; + } + + type.isAnyData = type.sealed || visit(type.restFieldType); + return type.isAnyData; + } + + @Override + public Boolean visit(BType type) { + return switch (type.tag) { + case TypeTags.TABLE -> visit((BTableType) type); + case TypeTags.ANYDATA -> visit((BAnydataType) type); + case TypeTags.RECORD -> visit((BRecordType) type); + case TypeTags.ARRAY -> visit((BArrayType) type); + case TypeTags.UNION -> visit((BUnionType) type); + case TypeTags.TYPEDESC -> visit((BTypedescType) type); + case TypeTags.MAP -> visit((BMapType) type); + case TypeTags.FINITE -> visit((BFiniteType) type); + case TypeTags.TUPLE -> visit((BTupleType) type); + case TypeTags.INTERSECTION -> visit((BIntersectionType) type); + case TypeTags.TYPEREFDESC -> visit((BTypeReferenceType) type); + case TypeTags.SIGNED8_INT, + TypeTags.SIGNED16_INT, + TypeTags.SIGNED32_INT, + TypeTags.UNSIGNED8_INT, + TypeTags.UNSIGNED16_INT, + TypeTags.UNSIGNED32_INT -> visit((BIntSubType) type); + case TypeTags.XML_ELEMENT, + TypeTags.XML_PI, + TypeTags.XML_COMMENT, + TypeTags.XML_TEXT -> visit((BXMLSubType) type); + default -> isAnydata(type); + }; + } + + @Override + public Boolean visit(BFutureType type) { + return isAnydata(type); + } + + @Override + public Boolean visit(BHandleType type) { + return isAnydata(type); + } + + @Override + public Boolean visit(BIntSubType bHandleType) { + return true; + } + + @Override + public Boolean visit(BXMLSubType bxmlSubType) { + return true; + } +} diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/IsPureTypeUniqueVisitor.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/IsPureTypeUniqueVisitor.java new file mode 100644 index 000000000000..ca6528a68796 --- /dev/null +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/IsPureTypeUniqueVisitor.java @@ -0,0 +1,295 @@ +package org.wso2.ballerinalang.compiler.semantics.analyzer; + +import org.wso2.ballerinalang.compiler.semantics.model.UniqueTypeVisitor; +import org.wso2.ballerinalang.compiler.semantics.model.types.BAnnotationType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BAnyType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BAnydataType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BArrayType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BBuiltInRefType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BErrorType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BFiniteType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BFutureType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BHandleType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BIntSubType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BIntersectionType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BInvokableType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BJSONType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BMapType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BNeverType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BNilType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BNoType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BObjectType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BPackageType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BParameterizedType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BRecordType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BStreamType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BStructureType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BTableType; +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.BTypeReferenceType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BTypedescType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BUnionType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BXMLSubType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BXMLType; +import org.wso2.ballerinalang.compiler.util.TypeTags; + +import java.util.HashSet; + +/** + * IsPureTypeUniqueVisitor to check if a type is pure data. + * + * This is introduced to handle cyclic unions. + * @since slp4 + */ +public class IsPureTypeUniqueVisitor implements UniqueTypeVisitor { + + private final HashSet visited; + private final boolean isPureType; + + public IsPureTypeUniqueVisitor() { + visited = new HashSet<>(); + isPureType = true; + } + + public IsPureTypeUniqueVisitor(HashSet visited) { + this.visited = visited; + isPureType = true; + } + + private boolean isAnyData(BType type) { + return switch (Types.getImpliedType(type).tag) { + case TypeTags.INT, + TypeTags.BYTE, + TypeTags.FLOAT, + TypeTags.DECIMAL, + TypeTags.STRING, + TypeTags.BOOLEAN, + TypeTags.JSON, + TypeTags.XML, + TypeTags.XML_TEXT, + TypeTags.TABLE, + TypeTags.NIL, + TypeTags.NEVER, + TypeTags.ANYDATA, + TypeTags.SIGNED8_INT, + TypeTags.SIGNED16_INT, + TypeTags.SIGNED32_INT, + TypeTags.UNSIGNED8_INT, + TypeTags.UNSIGNED16_INT, + TypeTags.UNSIGNED32_INT, + TypeTags.CHAR_STRING -> true; + default -> false; + }; + } + + @Override + public boolean isVisited(BType type) { + return visited.contains(type); + } + + @Override + public void reset() { + visited.clear(); + } + + @Override + public Boolean visit(BAnnotationType type) { + return isAnyData(type); + } + + @Override + public Boolean visit(BArrayType type) { + if (isVisited(type)) { + return isPureType; + } + visited.add(type); + return visit(type.eType); + } + + @Override + public Boolean visit(BBuiltInRefType type) { + return isAnyData(type); + } + + @Override + public Boolean visit(BAnyType type) { + return isAnyData(type); + } + + @Override + public Boolean visit(BAnydataType type) { + return isAnyData(type); + } + + @Override + public Boolean visit(BErrorType type) { + return isAnyData(type); + } + + @Override + public Boolean visit(BFiniteType type) { + IsAnydataUniqueVisitor isAnydataUniqueVisitor = new IsAnydataUniqueVisitor(visited); + return isAnydataUniqueVisitor.visit(type); + } + + @Override + public Boolean visit(BInvokableType type) { + return isAnyData(type); + } + + @Override + public Boolean visit(BJSONType type) { + return isAnyData(type); + } + + @Override + public Boolean visit(BMapType type) { + if (isVisited(type)) { + return isPureType; + } + visited.add(type); + return visit(type.constraint); + } + + @Override + public Boolean visit(BStreamType type) { + return isAnyData(type); + } + + @Override + public Boolean visit(BTypedescType type) { + return isAnyData(type); + } + + @Override + public Boolean visit(BParameterizedType type) { + return isAnyData(type); + } + + @Override + public Boolean visit(BNeverType type) { + return isAnyData(type); + } + + @Override + public Boolean visit(BNilType type) { + return isAnyData(type); + } + + @Override + public Boolean visit(BNoType type) { + return isAnyData(type); + } + + @Override + public Boolean visit(BPackageType type) { + return isAnyData(type); + } + + @Override + public Boolean visit(BStructureType type) { + return isAnyData(type); + } + + @Override + public Boolean visit(BTupleType type) { + IsAnydataUniqueVisitor isAnydataUniqueVisitor = new IsAnydataUniqueVisitor(visited); + return isAnydataUniqueVisitor.visit(type); + } + + @Override + public Boolean visit(BUnionType type) { + if (type.isPureType != null) { + return type.isPureType; + } + if (isVisited(type)) { + return isPureType; + } + visited.add(type); + for (BType member : type.getMemberTypes()) { + if (!visit(member)) { + type.isPureType = false; + return false; + } + } + type.isPureType = isPureType; + return isPureType; + } + + @Override + public Boolean visit(BIntersectionType type) { + return visit(type.effectiveType); + } + + @Override + public Boolean visit(BTypeReferenceType type) { + return visit(type.referredType); + } + + @Override + public Boolean visit(BXMLType type) { + return isAnyData(type); + } + + @Override + public Boolean visit(BTableType type) { + return isAnyData(type); + } + + @Override + public Boolean visit(BRecordType type) { + + IsAnydataUniqueVisitor isAnydataUniqueVisitor = new IsAnydataUniqueVisitor(visited); + return isAnydataUniqueVisitor.visit(type); + } + + @Override + public Boolean visit(BObjectType type) { + return isAnyData(type); + } + + @Override + public Boolean visit(BType type) { + return switch (type.tag) { + case TypeTags.TABLE -> visit((BTableType) type); + case TypeTags.ANYDATA -> visit((BAnydataType) type); + case TypeTags.RECORD -> visit((BRecordType) type); + case TypeTags.ARRAY -> visit((BArrayType) type); + case TypeTags.UNION -> visit((BUnionType) type); + case TypeTags.TYPEDESC -> visit((BTypedescType) type); + case TypeTags.MAP -> visit((BMapType) type); + case TypeTags.FINITE -> visit((BFiniteType) type); + case TypeTags.TUPLE -> visit((BTupleType) type); + case TypeTags.INTERSECTION -> visit((BIntersectionType) type); + case TypeTags.TYPEREFDESC -> visit((BTypeReferenceType) type); + case TypeTags.SIGNED8_INT, + TypeTags.SIGNED16_INT, + TypeTags.SIGNED32_INT, + TypeTags.UNSIGNED8_INT, + TypeTags.UNSIGNED16_INT, + TypeTags.UNSIGNED32_INT -> visit((BIntSubType) type); + default -> isAnyData(type); + }; + } + + @Override + public Boolean visit(BFutureType type) { + return isAnyData(type); + } + + @Override + public Boolean visit(BHandleType type) { + return isAnyData(type); + } + + @Override + public Boolean visit(BIntSubType type) { + return true; + } + + @Override + public Boolean visit(BXMLSubType bxmlSubType) { + return isAnyData(bxmlSubType); + } +} diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/IsolationAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/IsolationAnalyzer.java index 182ec315066f..298891dc56c8 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/IsolationAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/IsolationAnalyzer.java @@ -50,6 +50,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BAnyType; import org.wso2.ballerinalang.compiler.semantics.model.types.BAnydataType; import org.wso2.ballerinalang.compiler.semantics.model.types.BArrayType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BBuiltInRefType; import org.wso2.ballerinalang.compiler.semantics.model.types.BErrorType; import org.wso2.ballerinalang.compiler.semantics.model.types.BField; import org.wso2.ballerinalang.compiler.semantics.model.types.BFiniteType; @@ -60,6 +61,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BJSONType; import org.wso2.ballerinalang.compiler.semantics.model.types.BMapType; import org.wso2.ballerinalang.compiler.semantics.model.types.BNeverType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BNilType; import org.wso2.ballerinalang.compiler.semantics.model.types.BNoType; import org.wso2.ballerinalang.compiler.semantics.model.types.BObjectType; import org.wso2.ballerinalang.compiler.semantics.model.types.BPackageType; @@ -357,7 +359,7 @@ public void visit(BLangPackage pkgNode) { } for (BLangClassDefinition classDefinition : pkgNode.classDefinitions) { - if (classDefinition.flagSet.contains(Flag.ANONYMOUS) && isIsolated(classDefinition.getBType().getFlags())) { + if (classDefinition.flagSet.contains(Flag.ANONYMOUS) && isIsolated(classDefinition.getBType().flags)) { // If this is a class definition for an object constructor expression, and the type is `isolated`, // that is due to the expected type being an `isolated` object. We now mark the class definition also // as `isolated`, to enforce the isolation validation. @@ -1514,7 +1516,7 @@ private boolean checkStrandAnnotationExists(List atta private boolean isValidIsolatedAsyncInvocation(BLangInvocation.BLangActionInvocation actionInvocation) { boolean isIsolatedStartAction = true; - if (!isIsolated(actionInvocation.symbol.type.getFlags())) { + if (!isIsolated(actionInvocation.symbol.type.flags)) { dlog.error(actionInvocation.name.pos, DiagnosticErrorCode.INVALID_ASYNC_INVOCATION_OF_NON_ISOLATED_FUNCTION_IN_ISOLATED_FUNCTION); isIsolatedStartAction = false; @@ -2112,7 +2114,7 @@ private void analyzeInvocation(BLangInvocation invocationExpr) { boolean expectsIsolation = inIsolatedFunction || recordFieldDefaultValue || objectFieldDefaultValueRequiringIsolation; - boolean isolatedFunctionCall = isIsolated(symbol.type.getFlags()); + boolean isolatedFunctionCall = isIsolated(symbol.type.flags); boolean inStartAction = invocationExpr.async && !invocationExpr.functionPointerInvocation; @@ -2166,7 +2168,7 @@ private void analyzeInvocation(BLangInvocation invocationExpr) { private void markFunctionDependentlyIsolatedOnStartAction(BInvokableSymbol enclInvokableSymbol, Set argsList, BInvokableSymbol symbol) { - boolean isIsolatedFunction = isIsolated(symbol.type.getFlags()); + boolean isIsolatedFunction = isIsolated(symbol.type.flags); if (!isIsolatedFunction && Symbols.isFlagOn(symbol.flags, Flags.PUBLIC)) { markDependsOnIsolationNonInferableConstructs(); return; @@ -2247,10 +2249,9 @@ private void analyzeAndSetArrowFuncFlagForIsolatedParamArg(BLangExpression arg) tsymbol.pkgID, null, tsymbol.owner, tsymbol.pos, tsymbol.origin); dupInvokableTypeSymbol.params = tsymbol.params == null ? null : new ArrayList<>(tsymbol.params); - BInvokableType dupInvokableType = - new BInvokableType(symTable.typeEnv(), invokableType.paramTypes, invokableType.restType, - invokableType.retType, dupInvokableTypeSymbol); - dupInvokableType.addFlags(Flags.ISOLATED); + BInvokableType dupInvokableType = new BInvokableType(invokableType.paramTypes, invokableType.restType, + invokableType.retType, dupInvokableTypeSymbol); + dupInvokableType.flags |= Flags.ISOLATED; dupInvokableTypeSymbol.type = dupInvokableType; argExpr.setBType(dupInvokableType); @@ -2471,16 +2472,16 @@ private BTupleType getRepresentativeTupleTypeForRemainingArgs(int paramCount, in members.add(new BTupleMember(eType, Symbols.createVarSymbolForTupleMember(eType))); } - if (arrayType.getSize() > remReqArgCount) { - return new BTupleType(symTable.typeEnv(), null, members, eType, 0); + if (arrayType.size > remReqArgCount) { + return new BTupleType(null, members, eType, 0); } - return new BTupleType(symTable.typeEnv(), members); + return new BTupleType(members); } private void analyzeRestArgsForRestParam(BLangInvocation invocationExpr, List restArgs, BInvokableSymbol symbol, boolean expectsIsolation) { - if (Symbols.isFlagOn(((BArrayType) symbol.restParam.type).eType.getFlags(), Flags.ISOLATED)) { + if (Symbols.isFlagOn(((BArrayType) symbol.restParam.type).eType.flags, Flags.ISOLATED)) { for (BLangExpression restArg : restArgs) { analyzeNode(restArg, env); } @@ -2542,7 +2543,7 @@ private void analyzeVarArgIsolatedness(BLangInvocation invocationExpr, BLangRest private void handleNonExplicitlyIsolatedArgForIsolatedParam(BLangInvocation invocationExpr, BLangExpression expr, boolean expectsIsolation, BType type, Location pos) { - if (Symbols.isFlagOn(type.getFlags(), Flags.ISOLATED)) { + if (Symbols.isFlagOn(type.flags, Flags.ISOLATED)) { return; } @@ -2578,7 +2579,7 @@ private boolean isInIsolatedFunction(BLangInvokableNode enclInvokable) { if (isNotInArrowFunctionBody(env)) { return false; } - return isIsolated(((BLangArrowFunction) env.enclEnv.node).funcType.getFlags()); + return isIsolated(((BLangArrowFunction) env.enclEnv.node).funcType.flags); } return isIsolated(enclInvokable.symbol.flags); @@ -3015,7 +3016,7 @@ private boolean isIsolatedExpression(BLangExpression expression, boolean logErro return isIsolatedExpression(argExprs.get(0), logErrors, visitRestOnError, nonIsolatedExpressions, inferring, publiclyExposedObjectTypes, classDefinitions, moduleLevelVariables, unresolvedSymbols); - } else if (isIsolated(invocationSymbol.type.getFlags()) || + } else if (isIsolated(invocationSymbol.type.flags) || (inferring && this.isolationInferenceInfoMap.containsKey(invocationSymbol) && inferFunctionIsolation(invocationSymbol, this.isolationInferenceInfoMap.get(invocationSymbol), publiclyExposedObjectTypes, @@ -3257,7 +3258,7 @@ private boolean isSelfOfObject(BLangSimpleVarRef varRefExpr) { } private boolean isSelfOfIsolatedObject(BLangSimpleVarRef varRefExpr) { - return isSelfOfObject(varRefExpr) && isIsolated(varRefExpr.symbol.type.getFlags()); + return isSelfOfObject(varRefExpr) && isIsolated(varRefExpr.symbol.type.flags); } private boolean hasRefDefinedOutsideLock(BLangExpression variableReference) { @@ -3350,7 +3351,7 @@ private boolean isInIsolatedObjectMethod(SymbolEnv env, boolean ignoreInit) { BType ownerType = Types.getImpliedType(enclFunction.symbol.owner.type); - return ownerType.tag == TypeTags.OBJECT && isIsolated(ownerType.getFlags()); + return ownerType.tag == TypeTags.OBJECT && isIsolated(ownerType.flags); } private BLangFunction getEnclNonAnonymousFunction(BLangFunction enclFunction) { @@ -3683,7 +3684,7 @@ private boolean isVarRequiringInference(BSymbol moduleLevelVarSymbol) { } BType type = moduleLevelVarSymbol.type; - return !types.isInherentlyImmutableType(type) && !Symbols.isFlagOn(type.getFlags(), Flags.READONLY); + return !types.isInherentlyImmutableType(type) && !Symbols.isFlagOn(type.flags, Flags.READONLY); } private void populateInferableClass(BLangClassDefinition classDefinition) { @@ -3693,7 +3694,7 @@ private void populateInferableClass(BLangClassDefinition classDefinition) { } BType type = classDefinition.getBType(); - if (Symbols.isFlagOn(type.getFlags(), Flags.ISOLATED)) { + if (Symbols.isFlagOn(type.flags, Flags.ISOLATED)) { return; } @@ -3849,7 +3850,7 @@ private void inferIsolation(Set moduleLevelVarSymbols, Set publi symbol.flags |= Flags.ISOLATED; if (!moduleLevelVarSymbols.contains(symbol)) { - symbol.type.addFlags(Flags.ISOLATED); + symbol.type.flags |= Flags.ISOLATED; } } continue; @@ -3872,7 +3873,7 @@ private void inferIsolation(Set moduleLevelVarSymbols, Set publi symbol.flags |= Flags.ISOLATED; if (isObjectType) { - symbol.type.addFlags(Flags.ISOLATED); + symbol.type.flags |= Flags.ISOLATED; } } } @@ -4183,7 +4184,7 @@ private void logServiceIsolationHints(List classDefinition } private void logServiceIsolationHints(BLangClassDefinition classDefinition) { - boolean isolatedService = isIsolated(classDefinition.getBType().getFlags()); + boolean isolatedService = isIsolated(classDefinition.getBType().flags); for (BLangFunction function : classDefinition.functions) { Set flagSet = function.flagSet; @@ -4192,7 +4193,7 @@ private void logServiceIsolationHints(BLangClassDefinition classDefinition) { continue; } - boolean isolatedMethod = isIsolated(function.getBType().getFlags()); + boolean isolatedMethod = isIsolated(function.getBType().flags); if (isolatedService && isolatedMethod) { continue; @@ -4306,7 +4307,7 @@ private class TemporaryArrowFunctionSymbol extends BInvokableSymbol { } } - private static class BPubliclyExposedInferableTypeCollector extends TypeVisitor { + private static class BPubliclyExposedInferableTypeCollector implements TypeVisitor { Set unresolvedTypes; Set exposedTypes; @@ -4337,6 +4338,10 @@ public void visit(BArrayType bArrayType) { visitType(bArrayType.eType); } + @Override + public void visit(BBuiltInRefType bBuiltInRefType) { + } + @Override public void visit(BAnyType bAnyType) { } @@ -4356,7 +4361,7 @@ public void visit(BFiniteType bFiniteType) { @Override public void visit(BInvokableType bInvokableType) { - if (Symbols.isFlagOn(bInvokableType.getFlags(), Flags.ANY_FUNCTION)) { + if (Symbols.isFlagOn(bInvokableType.flags, Flags.ANY_FUNCTION)) { return; } @@ -4401,7 +4406,7 @@ public void visit(BNeverType bNeverType) { } @Override - public void visitNilType(BType bType) { + public void visit(BNilType bNilType) { } @Override @@ -4474,6 +4479,10 @@ public void visit(BObjectType bObjectType) { } } + @Override + public void visit(BType bType) { + } + @Override public void visit(BFutureType bFutureType) { visitType(bFutureType.constraint); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/QueryTypeChecker.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/QueryTypeChecker.java index 73fea76ef339..dd92270be20c 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/QueryTypeChecker.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/QueryTypeChecker.java @@ -18,7 +18,6 @@ package org.wso2.ballerinalang.compiler.semantics.analyzer; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.PredefinedType; import org.ballerinalang.model.clauses.OrderKeyNode; import org.ballerinalang.model.elements.PackageID; import org.ballerinalang.model.symbols.SymbolOrigin; @@ -196,7 +195,7 @@ public void checkQueryType(BLangQueryExpr queryExpr, TypeChecker.AnalyzerData da List collectionTypes = getCollectionTypes(clauses); BType completionType = getCompletionType(collectionTypes, Types.QueryConstructType.DEFAULT, data); if (completionType != null) { - queryType = BUnionType.create(symTable.typeEnv(), null, queryType, completionType); + queryType = BUnionType.create(null, queryType, completionType); } queryExpr.setDeterminedType(queryType); actualType = types.checkType(finalClauseExpr.pos, queryType, data.expType, @@ -303,15 +302,15 @@ public BType resolveQueryType(SymbolEnv env, BLangExpression selectExp, BType ta BType completionType = getCompletionType(collectionTypes, types.getQueryConstructType(queryExpr), data); if (queryExpr.isStream) { - return new BStreamType(symTable.typeEnv(), TypeTags.STREAM, selectType, completionType, null); + return new BStreamType(TypeTags.STREAM, selectType, completionType, null); } else if (queryExpr.isTable) { actualType = getQueryTableType(queryExpr, selectType, resolvedTypes.get(0), env); } else if (queryExpr.isMap) { BType mapConstraintType = getTypeOfTypeParameter(selectType, queryExpr.getSelectClause().expression.pos); if (mapConstraintType != symTable.semanticError) { - actualType = new BMapType(symTable.typeEnv(), TypeTags.MAP, mapConstraintType, null); - if (Symbols.isFlagOn(resolvedTypes.get(0).getFlags(), Flags.READONLY)) { + actualType = new BMapType(TypeTags.MAP, mapConstraintType, null); + if (Symbols.isFlagOn(resolvedTypes.get(0).flags, Flags.READONLY)) { actualType = ImmutableTypeCloner.getImmutableIntersectionType(null, types, actualType, env, symTable, anonymousModelHelper, names, null); } @@ -321,8 +320,7 @@ public BType resolveQueryType(SymbolEnv env, BLangExpression selectExp, BType ta } if (completionType != null && completionType.tag != TypeTags.NIL) { - return BUnionType.create(symTable.typeEnv(), null, actualType, - types.getSafeType(completionType, true, false)); + return BUnionType.create(null, actualType, types.getSafeType(completionType, true, false)); } else { return actualType; } @@ -351,7 +349,7 @@ void solveSelectTypeAndResolveType(BLangQueryExpr queryExpr, BLangExpression sel errorTypes.add(elementType); continue; } - BType queryResultType = new BArrayType(symTable.typeEnv(), selectType); + BType queryResultType = new BArrayType(selectType); resolvedType = getResolvedType(queryResultType, type, isReadonly, env); break; case TypeTags.TABLE: @@ -382,7 +380,7 @@ void solveSelectTypeAndResolveType(BLangQueryExpr queryExpr, BLangExpression sel BType memberType = ((BMapType) type).getConstraint(); BVarSymbol varSymbol = Symbols.createVarSymbolForTupleMember(memberType); memberTypeList.add(new BTupleMember(memberType, varSymbol)); - BTupleType newExpType = new BTupleType(symTable.typeEnv(), memberTypeList); + BTupleType newExpType = new BTupleType(null, memberTypeList); selectType = checkExprSilent(selectExp, env, newExpType, data); if (selectType == symTable.semanticError) { errorTypes.add(newExpType); @@ -416,7 +414,7 @@ void solveSelectTypeAndResolveType(BLangQueryExpr queryExpr, BLangExpression sel case TypeTags.INTERSECTION: type = ((BIntersectionType) type).effectiveType; solveSelectTypeAndResolveType(queryExpr, selectExp, List.of(type), collectionType, selectTypes, - resolvedTypes, env, data, Symbols.isFlagOn(type.getFlags(), Flags.READONLY)); + resolvedTypes, env, data, Symbols.isFlagOn(type.flags, Flags.READONLY)); return; case TypeTags.NONE: default: @@ -474,7 +472,7 @@ void solveSelectTypeAndResolveType(BLangQueryExpr queryExpr, BLangExpression sel BType actualQueryType = silentTypeCheckExpr(queryExpr, symTable.noType, data); if (actualQueryType != symTable.semanticError) { types.checkType(queryExpr, actualQueryType, - BUnionType.create(symTable.typeEnv(), null, new LinkedHashSet<>(expTypes))); + BUnionType.create(null, new LinkedHashSet<>(expTypes))); errorTypes.forEach(expType -> { if (expType.tag == TypeTags.UNION) { checkExpr(nodeCloner.cloneNode(selectExp), env, expType, data); @@ -493,14 +491,14 @@ void solveSelectTypeAndResolveType(BLangQueryExpr queryExpr, BLangExpression sel } private BType getQueryTableType(BLangQueryExpr queryExpr, BType constraintType, BType resolvedType, SymbolEnv env) { - final BTableType tableType = new BTableType(symTable.typeEnv(), constraintType, null); + final BTableType tableType = new BTableType(TypeTags.TABLE, constraintType, null); if (!queryExpr.fieldNameIdentifierList.isEmpty()) { validateKeySpecifier(queryExpr.fieldNameIdentifierList, constraintType); markReadOnlyForConstraintType(constraintType); tableType.fieldNameList = queryExpr.fieldNameIdentifierList.stream() .map(identifier -> ((BLangIdentifier) identifier).value).toList(); } - if (Symbols.isFlagOn(resolvedType.getFlags(), Flags.READONLY)) { + if (Symbols.isFlagOn(resolvedType.flags, Flags.READONLY)) { return ImmutableTypeCloner.getImmutableIntersectionType(null, types, tableType, env, symTable, anonymousModelHelper, names, null); } @@ -530,7 +528,7 @@ private void markReadOnlyForConstraintType(BType constraintType) { } } if (recordType.sealed) { - recordType.addFlags(Flags.READONLY); + recordType.flags |= Flags.READONLY; recordType.tsymbol.flags |= Flags.READONLY; } } @@ -551,7 +549,7 @@ private BType getTypeOfTypeParameter(BType selectType, Location pos) { } memberTypes.add(mapType); } - return new BUnionType(types.typeEnv(), null, memberTypes, false); + return new BUnionType(null, memberTypes, false, false); } else { return getQueryMapConstraintType(referredType, pos); } @@ -560,7 +558,7 @@ private BType getTypeOfTypeParameter(BType selectType, Location pos) { private BType getQueryMapConstraintType(BType type, Location pos) { if (type.tag == TypeTags.ARRAY) { BArrayType arrayType = (BArrayType) type; - if (arrayType.state != BArrayState.OPEN && arrayType.getSize() == 2 && + if (arrayType.state != BArrayState.OPEN && arrayType.size == 2 && types.isAssignable(arrayType.eType, symTable.stringType)) { return arrayType.eType; } @@ -634,7 +632,7 @@ private BType getCompletionType(List collectionTypes, Types.QueryConstruc if (completionTypes.size() == 1) { completionType = completionTypes.iterator().next(); } else { - completionType = BUnionType.create(symTable.typeEnv(), null, completionTypes.toArray(new BType[0])); + completionType = BUnionType.create(null, completionTypes.toArray(new BType[0])); } } return completionType; @@ -649,7 +647,7 @@ private List getCollectionTypes(List clauses) { private BType getResolvedType(BType initType, BType expType, boolean isReadonly, SymbolEnv env) { if (initType.tag != TypeTags.SEMANTIC_ERROR && (isReadonly || - Symbols.isFlagOn(expType.getFlags(), Flags.READONLY))) { + Symbols.isFlagOn(expType.flags, Flags.READONLY))) { return ImmutableTypeCloner.getImmutableIntersectionType(null, types, initType, env, symTable, anonymousModelHelper, names, null); } @@ -672,19 +670,19 @@ private BType getNonContextualQueryType(BType constraintType, BType basicType, L dlog.error(pos, INVALID_QUERY_CONSTRUCT_INFERRED_MAP); return symTable.semanticError; case TypeTags.XML: - if (types.isSubTypeOfBaseType(constraintType, PredefinedType.XML)) { + if (types.isSubTypeOfBaseType(constraintType, symTable.xmlType.tag)) { return new BXMLType(constraintType, null); } break; case TypeTags.STRING: - if (types.isSubTypeOfBaseType(constraintType, PredefinedType.STRING)) { + if (types.isSubTypeOfBaseType(constraintType, TypeTags.STRING)) { return symTable.stringType; } break; case TypeTags.ARRAY: case TypeTags.TUPLE: case TypeTags.OBJECT: - return new BArrayType(symTable.typeEnv(), constraintType); + return new BArrayType(constraintType); default: return symTable.semanticError; } @@ -745,26 +743,24 @@ private void handleInputClauseVariables(BLangInputClause bLangInputClause, Symbo BLangVariable variableNode = (BLangVariable) bLangInputClause.variableDefinitionNode.getVariable(); // Check whether the foreach node's variables are declared with var. - BType inputClauseVarType = bLangInputClause.varType; if (bLangInputClause.isDeclaredWithVar) { // If the foreach node's variables are declared with var, type is `varType`. - semanticAnalyzer.handleDeclaredVarInForeach(variableNode, inputClauseVarType, blockEnv); + semanticAnalyzer.handleDeclaredVarInForeach(variableNode, bLangInputClause.varType, blockEnv); return; } // If the type node is available, we get the type from it. BType typeNodeType = symResolver.resolveTypeNode(variableNode.typeNode, blockEnv); // Then we need to check whether the RHS type is assignable to LHS type. - if (inputClauseVarType.tag != TypeTags.SEMANTIC_ERROR) { - if (types.isAssignable(inputClauseVarType, typeNodeType)) { - // If assignable, we set types to the variables. - semanticAnalyzer.handleDeclaredVarInForeach(variableNode, inputClauseVarType, blockEnv); - return; - } - // Log an error and define a symbol with the node's type to avoid undeclared symbol errors. + if (types.isAssignable(bLangInputClause.varType, typeNodeType)) { + // If assignable, we set types to the variables. + semanticAnalyzer.handleDeclaredVarInForeach(variableNode, bLangInputClause.varType, blockEnv); + return; + } + // Log an error and define a symbol with the node's type to avoid undeclared symbol errors. + if (typeNodeType != symTable.semanticError) { dlog.error(variableNode.typeNode.pos, DiagnosticErrorCode.INCOMPATIBLE_TYPES, - inputClauseVarType, typeNodeType); + bLangInputClause.varType, typeNodeType); } - semanticAnalyzer.handleDeclaredVarInForeach(variableNode, typeNodeType, blockEnv); } @@ -871,8 +867,7 @@ public void visit(BLangCollectClause collectClause, TypeChecker.AnalyzerData dat Name name = new Name(var); BSymbol originalSymbol = symResolver.lookupSymbolInMainSpace(collectEnv, name); BSequenceSymbol sequenceSymbol = new BSequenceSymbol(originalSymbol.flags, name, originalSymbol.pkgID, - new BSequenceType(symTable.typeEnv(), originalSymbol.getType()), originalSymbol.owner, - originalSymbol.pos); + new BSequenceType(originalSymbol.getType()), originalSymbol.owner, originalSymbol.pos); collectEnv.scope.define(name, sequenceSymbol); } } @@ -895,7 +890,7 @@ public void visit(BLangOnConflictClause onConflictClause, TypeChecker.AnalyzerDa if (data.queryData.completeEarlyErrorList != null) { BType possibleErrorType = type.tag == TypeTags.UNION ? types.getErrorType((BUnionType) type) : - types.getErrorType(BUnionType.create(symTable.typeEnv(), null, type)); + types.getErrorType(BUnionType.create(null, type)); data.queryData.completeEarlyErrorList.add(possibleErrorType); } } @@ -915,7 +910,7 @@ public void visit(BLangOrderByClause orderByClause, TypeChecker.AnalyzerData dat orderByClause.env = data.commonAnalyzerData.queryEnvs.peek(); for (OrderKeyNode orderKeyNode : orderByClause.getOrderKeyList()) { BType exprType = checkExpr((BLangExpression) orderKeyNode.getOrderKey(), orderByClause.env, data); - if (exprType.tag != TypeTags.SEMANTIC_ERROR && !types.isOrderedType(exprType)) { + if (!types.isOrderedType(exprType, false)) { dlog.error(((BLangOrderKey) orderKeyNode).expression.pos, DiagnosticErrorCode.ORDER_BY_NOT_SUPPORTED); } } @@ -950,8 +945,7 @@ public void visit(BLangGroupByClause groupByClause, TypeChecker.AnalyzerData dat Name name = new Name(var); BSymbol originalSymbol = symResolver.lookupSymbolInMainSpace(groupByEnv, name); BSequenceSymbol sequenceSymbol = new BSequenceSymbol(originalSymbol.flags, name, originalSymbol.pkgID, - new BSequenceType(symTable.typeEnv(), originalSymbol.getType()), originalSymbol.owner, - originalSymbol.pos); + new BSequenceType(originalSymbol.getType()), originalSymbol.owner, originalSymbol.pos); groupByEnv.scope.define(name, sequenceSymbol); } } @@ -1086,7 +1080,7 @@ public void visit(BLangCollectContextInvocation collectContextInvocation, TypeCh BLangInvocation invocation = collectContextInvocation.invocation; data.resultType = checkExpr(invocation, data.env, data); if (isNilReturnInvocationInCollectClause(invocation, data)) { - data.resultType = BUnionType.create(symTable.typeEnv(), null, data.resultType, symTable.nilType); + data.resultType = BUnionType.create(null, data.resultType, symTable.nilType); } collectContextInvocation.setBType(data.resultType); } @@ -1155,8 +1149,7 @@ public void visit(BLangSimpleVarRef varRefExpr, TypeChecker.AnalyzerData data) { dlog.error(varRefExpr.pos, DiagnosticErrorCode.VARIABLE_IS_SEQUENCED_MORE_THAN_ONCE, varName); } } else if ((symbol.tag & SymTag.TYPE_DEF) == SymTag.TYPE_DEF) { - actualType = symbol.type.tag == TypeTags.TYPEDESC ? symbol.type : - new BTypedescType(symTable.typeEnv(), symbol.type, null); + actualType = symbol.type.tag == TypeTags.TYPEDESC ? symbol.type : new BTypedescType(symbol.type, null); varRefExpr.symbol = symbol; } else if ((symbol.tag & SymTag.CONSTANT) == SymTag.CONSTANT) { BConstantSymbol constSymbol = (BConstantSymbol) symbol; @@ -1206,8 +1199,7 @@ public void visit(BLangListConstructorExpr listConstructor, TypeChecker.Analyzer checkExpr(expr, data.env, symTable.noType, data); data.queryData.withinSequenceContext = false; data.resultType = types.checkType(listConstructor.pos, - new BTupleType(symTable.typeEnv(), null, new ArrayList<>(0), - ((BSequenceType) type).elementType, 0), + new BTupleType(null, new ArrayList<>(0), ((BSequenceType) type).elementType, 0), expType, DiagnosticErrorCode.INCOMPATIBLE_TYPES); listConstructor.setBType(data.resultType); return; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SemTypeHelper.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SemTypeHelper.java deleted file mode 100644 index c1339a43921e..000000000000 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SemTypeHelper.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.wso2.ballerinalang.compiler.semantics.analyzer; - -import io.ballerina.types.BasicTypeBitSet; -import io.ballerina.types.ComplexSemType; -import io.ballerina.types.Context; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypes; -import io.ballerina.types.SubtypeData; -import io.ballerina.types.subtypedata.BooleanSubtype; -import io.ballerina.types.subtypedata.DecimalSubtype; -import io.ballerina.types.subtypedata.FloatSubtype; -import io.ballerina.types.subtypedata.IntSubtype; -import io.ballerina.types.subtypedata.StringSubtype; -import org.ballerinalang.model.types.TypeKind; -import org.wso2.ballerinalang.compiler.semantics.model.SymbolTable; -import org.wso2.ballerinalang.compiler.semantics.model.types.BFiniteType; -import org.wso2.ballerinalang.compiler.semantics.model.types.BType; -import org.wso2.ballerinalang.compiler.semantics.model.types.SemNamedType; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral; - -import java.math.BigDecimal; -import java.util.LinkedHashSet; -import java.util.Optional; -import java.util.Set; - -import static io.ballerina.types.BasicTypeCode.BT_BOOLEAN; -import static io.ballerina.types.BasicTypeCode.BT_DECIMAL; -import static io.ballerina.types.BasicTypeCode.BT_FLOAT; -import static io.ballerina.types.BasicTypeCode.BT_INT; -import static io.ballerina.types.BasicTypeCode.BT_STRING; -import static io.ballerina.types.Core.getComplexSubtypeData; -import static io.ballerina.types.Core.widenToBasicTypes; - -/** - * Contains helper methods related to sem-types. - * - * @since 2201.9.0 - */ -public final class SemTypeHelper { - - private SemTypeHelper() { - } - - public static SemType resolveSingletonType(BLangLiteral literal) { - return resolveSingletonType(literal.value, literal.getDeterminedType().getKind()); - } - - public static SemType resolveSingletonType(Object value, TypeKind targetTypeKind) { - switch (targetTypeKind) { - case FLOAT: - double doubleVal; - if (value instanceof Long) { - doubleVal = ((Long) value).doubleValue(); - } else if (value instanceof Double) { - doubleVal = (double) value; - } else { - // literal value will be a string if it wasn't within the bounds of what is supported by Java Long - // or Double when it was parsed in BLangNodeBuilder. - try { - doubleVal = Double.parseDouble((String) value); - } catch (NumberFormatException e) { - // We reach here when there is a syntax error. Mock the flow with default float value. - return FloatSubtype.floatConst(0); - } - } - return SemTypes.floatConst(doubleVal); - case INT: - case BYTE: - return SemTypes.intConst(((Number) value).longValue()); - case STRING: - return SemTypes.stringConst((String) value); - case BOOLEAN: - return SemTypes.booleanConst((Boolean) value); - case DECIMAL: - return SemTypes.decimalConst((String) value); - case NIL: - return PredefinedType.NIL; - case OTHER: - // We reach here when there is a semantic error - return PredefinedType.NEVER; - default: - throw new UnsupportedOperationException("Finite type not implemented for: " + targetTypeKind); - } - } - - public static boolean isSubtypeSimple(BType bt, BasicTypeBitSet bbs) { - return SemTypes.isSubtypeSimple(bt.semType(), bbs); - } - - public static boolean isSubtypeSimpleNotNever(BType bt, BasicTypeBitSet bbs) { - return SemTypes.isSubtypeSimpleNotNever(bt.semType(), bbs); - } - - public static boolean containsBasicType(BType bt, BasicTypeBitSet bbs) { - return SemTypes.containsBasicType(bt.semType(), bbs); - } - - public static boolean containsType(Context ctx, BType bt, SemType bbs) { - return SemTypes.containsType(ctx, bt.semType(), bbs); - } - - public static boolean isSubtype(Context context, BType bt, SemType st) { - return SemTypes.isSubtype(context, bt.semType(), st); - } - - public static boolean isSimpleOrString(TypeKind kind) { - switch (kind) { - case NIL: - case BOOLEAN: - case INT: - case BYTE: - case FLOAT: - case DECIMAL: - case STRING: - case FINITE: - return true; - default: - return false; - } - } - - /** - * Returns the basic type of singleton. - *

- * This will replace the existing finiteType.getValueSpace().iterator().next().getBType() calls - * - * @param t SemType component of BFiniteType - */ - public static Optional singleShapeBroadType(SemType t, SymbolTable symTable) { - if (PredefinedType.NIL.equals(t)) { - return Optional.of(symTable.nilType); - } else if (t instanceof BasicTypeBitSet) { - return Optional.empty(); - } else if (SemTypes.isSubtypeSimple(t, PredefinedType.INT)) { - SubtypeData sd = getComplexSubtypeData((ComplexSemType) t, BT_INT); - Optional value = IntSubtype.intSubtypeSingleValue(sd); - return value.isEmpty() ? Optional.empty() : Optional.of(symTable.intType); - } else if (SemTypes.isSubtypeSimple(t, PredefinedType.FLOAT)) { - SubtypeData sd = getComplexSubtypeData((ComplexSemType) t, BT_FLOAT); - Optional value = FloatSubtype.floatSubtypeSingleValue(sd); - return value.isEmpty() ? Optional.empty() : Optional.of(symTable.floatType); - } else if (SemTypes.isSubtypeSimple(t, PredefinedType.STRING)) { - SubtypeData sd = getComplexSubtypeData((ComplexSemType) t, BT_STRING); - Optional value = StringSubtype.stringSubtypeSingleValue(sd); - return value.isEmpty() ? Optional.empty() : Optional.of(symTable.stringType); - } else if (SemTypes.isSubtypeSimple(t, PredefinedType.BOOLEAN)) { - SubtypeData sd = getComplexSubtypeData((ComplexSemType) t, BT_BOOLEAN); - Optional value = BooleanSubtype.booleanSubtypeSingleValue(sd); - return value.isEmpty() ? Optional.empty() : Optional.of(symTable.booleanType); - } else if (SemTypes.isSubtypeSimple(t, PredefinedType.DECIMAL)) { - SubtypeData sd = getComplexSubtypeData((ComplexSemType) t, BT_DECIMAL); - Optional value = DecimalSubtype.decimalSubtypeSingleValue(sd); - return value.isEmpty() ? Optional.empty() : Optional.of(symTable.decimalType); - } - return Optional.empty(); - } - - /** - * Returns the basic types of singleton/union of singleton. - *

- * This will replace the existing finiteType.getValueSpace().iterator() calls - * - * @param t SemType component of BFiniteType - */ - public static Set broadTypes(SemType t, SymbolTable symTable) { // Equivalent to getValueTypes() - Set types = new LinkedHashSet<>(7); - BasicTypeBitSet basicTypeBitSet = widenToBasicTypes(t); - if ((basicTypeBitSet.bitset & PredefinedType.NIL.bitset) != 0) { - types.add(symTable.nilType); - } - - if ((basicTypeBitSet.bitset & PredefinedType.BOOLEAN.bitset) != 0) { - types.add(symTable.booleanType); - } - - if ((basicTypeBitSet.bitset & PredefinedType.INT.bitset) != 0) { - types.add(symTable.intType); - } - - if ((basicTypeBitSet.bitset & PredefinedType.FLOAT.bitset) != 0) { - types.add(symTable.floatType); - } - - if ((basicTypeBitSet.bitset & PredefinedType.DECIMAL.bitset) != 0) { - types.add(symTable.decimalType); - } - - if ((basicTypeBitSet.bitset & PredefinedType.STRING.bitset) != 0) { - types.add(symTable.stringType); - } - - return types; - } - - public static Set broadTypes(BFiniteType finiteType, SymbolTable symTable) { - Set types = new LinkedHashSet<>(7); - for (SemNamedType semNamedType: finiteType.valueSpace) { - SemType t = semNamedType.semType(); - BasicTypeBitSet basicTypeBitSet = widenToBasicTypes(t); - if ((basicTypeBitSet.bitset & PredefinedType.NIL.bitset) != 0) { - types.add(symTable.nilType); - } - - if ((basicTypeBitSet.bitset & PredefinedType.BOOLEAN.bitset) != 0) { - types.add(symTable.booleanType); - } - - if ((basicTypeBitSet.bitset & PredefinedType.INT.bitset) != 0) { - types.add(symTable.intType); - } - - if ((basicTypeBitSet.bitset & PredefinedType.FLOAT.bitset) != 0) { - types.add(symTable.floatType); - } - - if ((basicTypeBitSet.bitset & PredefinedType.DECIMAL.bitset) != 0) { - types.add(symTable.decimalType); - } - - if ((basicTypeBitSet.bitset & PredefinedType.STRING.bitset) != 0) { - types.add(symTable.stringType); - } - } - return types; - } - - /** - * Counts number of bits set in bitset. - * Note: this is similar to lib:bitCount() in nBallerina - * This is the Brian Kernighan algorithm. - * This won't work if bits is less than 0. - * - * @param bitset bitset for bits to be counted - * @return the count - */ - public static int bitCount(int bitset) { - int n = 0; - int v = bitset; - while (v != 0) { - v &= v - 1; - n += 1; - } - return n; - } -} diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SemanticAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SemanticAnalyzer.java index 140bb9aa8aa0..5b8566b99307 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SemanticAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SemanticAnalyzer.java @@ -20,8 +20,6 @@ import io.ballerina.compiler.api.symbols.DiagnosticState; import io.ballerina.projects.ModuleDescriptor; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.Env; -import io.ballerina.types.PredefinedType; import org.ballerinalang.compiler.CompilerPhase; import org.ballerinalang.model.TreeBuilder; import org.ballerinalang.model.elements.AttachPoint; @@ -272,7 +270,6 @@ public class SemanticAnalyzer extends SimpleBLangNodeAnalyzer anonTypeNameSuffixes; private final CompilerContext compilerContext; - private final Env typeEnv; public static SemanticAnalyzer getInstance(CompilerContext context) { SemanticAnalyzer semAnalyzer = context.get(SYMBOL_ANALYZER_KEY); @@ -300,7 +297,6 @@ private SemanticAnalyzer(CompilerContext context) { this.anonModelHelper = BLangAnonymousModelHelper.getInstance(context); this.unifier = new Unifier(); this.anonTypeNameSuffixes = new ArrayDeque<>(); - this.typeEnv = types.typeEnv(); } public BLangPackage analyze(BLangPackage pkgNode) { @@ -566,8 +562,8 @@ public void visit(BLangFunction funcNode, AnalyzerData data) { validateIsolatedParamUsage(inIsolatedFunction, restParam, true, data); } - if (hasReturnType && Symbols.isFlagOn(returnTypeNode.getBType().getFlags(), Flags.PARAMETERIZED)) { - unifier.validate(typeEnv, returnTypeNode.getBType(), funcNode, symTable, currentEnv, types, dlog); + if (hasReturnType && Symbols.isFlagOn(returnTypeNode.getBType().flags, Flags.PARAMETERIZED)) { + unifier.validate(returnTypeNode.getBType(), funcNode, symTable, currentEnv, types, dlog); } validateObjectAttachedFunction(funcNode, data); @@ -801,6 +797,8 @@ public void visit(BLangTypeConversionExpr conversionExpr, AnalyzerData data) { @Override public void visit(BLangFiniteTypeNode finiteTypeNode, AnalyzerData data) { + boolean foundUnaryExpr = false; + boolean isErroredExprInFiniteType = false; NodeKind valueKind; BLangExpression value; @@ -809,6 +807,11 @@ public void visit(BLangFiniteTypeNode finiteTypeNode, AnalyzerData data) { valueKind = value.getKind(); if (valueKind == NodeKind.UNARY_EXPR) { + foundUnaryExpr = true; + BType resultType = typeChecker.checkExpr(value, data.env, symTable.noType, data.prevEnvs); + if (resultType == symTable.semanticError) { + isErroredExprInFiniteType = true; + } // Replacing unary expression with numeric literal type for + and - numeric values BLangNumericLiteral newNumericLiteral = Types.constructNumericLiteralFromUnaryExpr((BLangUnaryExpr) value); @@ -821,6 +824,10 @@ public void visit(BLangFiniteTypeNode finiteTypeNode, AnalyzerData data) { analyzeNode(value, data); } } + + if (foundUnaryExpr && isErroredExprInFiniteType) { + finiteTypeNode.setBType(symTable.semanticError); + } } @Override @@ -946,7 +953,7 @@ public void visit(BLangRecordTypeNode recordTypeNode, AnalyzerData data) { if (isRecordType && allReadOnlyFields) { type.tsymbol.flags |= Flags.READONLY; - type.addFlags(Flags.READONLY); + type.flags |= Flags.READONLY; } validateDefaultable(recordTypeNode); @@ -1153,14 +1160,10 @@ public void visit(BLangSimpleVariable varNode, AnalyzerData data) { validateWorkerAnnAttachments(varNode.expr, data); - if (varNode.typeNode != null) { - analyzeNode(varNode.typeNode, data); - } handleWildCardBindingVariable(varNode, currentEnv); BType lhsType = varNode.symbol.type; varNode.setBType(lhsType); - // Configurable variable type must be a subtype of anydata. if (configurable && varNode.typeNode != null && lhsType.tag != TypeTags.SEMANTIC_ERROR) { if (!types.isAssignable(lhsType, symTable.anydataType)) { @@ -1179,6 +1182,10 @@ public void visit(BLangSimpleVariable varNode, AnalyzerData data) { } } + if (varNode.typeNode != null) { + analyzeNode(varNode.typeNode, data); + } + // Analyze the init expression BLangExpression rhsExpr = varNode.expr; if (rhsExpr == null) { @@ -1200,7 +1207,7 @@ public void visit(BLangSimpleVariable varNode, AnalyzerData data) { if (isListenerDecl) { BType rhsType = typeChecker.checkExpr(rhsExpr, varInitEnv, - BUnionType.create(typeEnv, null, lhsType, symTable.errorType), data.prevEnvs, + BUnionType.create(null, lhsType, symTable.errorType), data.prevEnvs, data.commonAnalyzerData); validateListenerCompatibility(varNode, rhsType); } else { @@ -1250,7 +1257,7 @@ private Map getModuleKeys(Set configVars, String } private void validateMapConfigVariable(String configKey, BVarSymbol variable, Map configKeys) { - if (configKeys.containsKey(configKey) && types.isSubTypeOfMapping(variable.type.semType())) { + if (configKeys.containsKey(configKey) && types.isSubTypeOfMapping(variable.type)) { dlog.error(variable.pos, DiagnosticErrorCode.CONFIGURABLE_VARIABLE_MODULE_AMBIGUITY, variable.name.value, configKeys.get(configKey)); } @@ -1340,7 +1347,7 @@ private boolean isSupportedConfigType(BType type, List errors, String va case ANYDATA: break; case FINITE: - return types.isAnydata(type.semType()); + return types.isAnydata(type); case NIL: return !isRequired; case ARRAY: @@ -1417,9 +1424,21 @@ private boolean isSupportedConfigType(BType type, List errors, String va } private boolean isNilableDefaultField(BField field, BType fieldType) { - return !Symbols.isFlagOn(field.symbol.flags, Flags.REQUIRED) && - !Symbols.isFlagOn(field.symbol.flags, Flags.OPTIONAL) && - fieldType.isNullable(); + if (!Symbols.isFlagOn(field.symbol.flags, Flags.REQUIRED) && !Symbols.isFlagOn(field.symbol.flags, + Flags.OPTIONAL)) { + if (fieldType.tag == TypeTags.NIL) { + return true; + } + if (fieldType.tag == TypeTags.UNION) { + BUnionType unionType = (BUnionType) fieldType; + for (BType memberType : unionType.getMemberTypes()) { + if (memberType.tag == TypeTags.NIL) { + return true; + } + } + } + } + return false; } private void validateListenerCompatibility(BLangSimpleVariable varNode, BType rhsType) { @@ -1686,16 +1705,16 @@ private BType resolveTupleType(BLangTupleVariable varNode) { List members = new ArrayList<>(varNode.memberVariables.size()); for (BLangVariable memberVariable : varNode.memberVariables) { BType type = getTupleMemberType(memberVariable); - BVarSymbol varSymbol = new BVarSymbol(type.getFlags(), null, null, type, null, null, null); + BVarSymbol varSymbol = new BVarSymbol(type.flags, null, null, type, null, null, null); members.add(new BTupleMember(type, varSymbol)); } BLangVariable restVariable = varNode.restVariable; if (restVariable == null) { - return new BTupleType(typeEnv, members); + return new BTupleType(members); } - return new BTupleType(typeEnv, null, members, getTupleMemberType(restVariable), 0); + return new BTupleType(null, members, getTupleMemberType(restVariable), 0); } private BType getTupleMemberType(BLangVariable memberVariable) { @@ -1732,7 +1751,7 @@ public void visit(BLangErrorVariable varNode, AnalyzerData data) { // reason must be a const of subtype of string. // then we match the error with this specific reason. if (!varNode.reasonVarPrefixAvailable && varNode.getBType() == null) { - BErrorType errorType = new BErrorType(typeEnv, varNode.getBType().tsymbol, null); + BErrorType errorType = new BErrorType(varNode.getBType().tsymbol, null); if (Types.getImpliedType(varNode.getBType()).tag == TypeTags.UNION) { Set members = types.expandAndGetMemberTypesRecursive(varNode.getBType()); @@ -2011,7 +2030,7 @@ private BType getListenerType(BType bType) { } else if (compatibleTypes.size() == 1) { return compatibleTypes.iterator().next(); } else { - return BUnionType.create(typeEnv, null, compatibleTypes); + return BUnionType.create(null, compatibleTypes); } } @@ -2058,7 +2077,7 @@ void handleDeclaredVarInForeach(BLangVariable variable, BType rhsType, SymbolEnv BLangTupleVariable tupleVariable = (BLangTupleVariable) variable; if ((TypeTags.TUPLE != referredRhsType.tag && TypeTags.ARRAY != referredRhsType.tag && TypeTags.UNION != referredRhsType.tag) || - (variable.isDeclaredWithVar && !types.isSubTypeOfBaseType(rhsType, PredefinedType.LIST))) { + (variable.isDeclaredWithVar && !types.isSubTypeOfBaseType(rhsType, TypeTags.TUPLE))) { dlog.error(variable.pos, DiagnosticErrorCode.INVALID_LIST_BINDING_PATTERN_INFERENCE, rhsType); recursivelyDefineVariables(tupleVariable, blockEnv); return; @@ -2510,7 +2529,7 @@ private void checkArrayVarRefEquivalency(Location pos, BLangTupleVarRef target, BArrayType arraySource = (BArrayType) source; // For unsealed - if (arraySource.getSize() < target.expressions.size() && arraySource.state != BArrayState.OPEN) { + if (arraySource.size < target.expressions.size() && arraySource.state != BArrayState.OPEN) { dlog.error(rhsPos, DiagnosticErrorCode.INCOMPATIBLE_TYPES, target.getBType(), arraySource); } @@ -2680,7 +2699,7 @@ private void checkErrorVarRefEquivalency(BLangErrorVarRef lhsRef, BType rhsType, if (lhsRef.restVar != null && !isIgnoreVar(lhsRef)) { setTypeOfVarRefInErrorBindingAssignment(lhsRef.restVar, data); checkInvalidTypeDef(lhsRef.restVar); - BMapType expRestType = new BMapType(typeEnv, TypeTags.MAP, wideType, null); + BMapType expRestType = new BMapType(TypeTags.MAP, wideType, null); BType restVarType = Types.getImpliedType(lhsRef.restVar.getBType()); if (restVarType.tag != TypeTags.MAP || !types.isAssignable(wideType, ((BMapType) restVarType).constraint)) { dlog.error(lhsRef.restVar.pos, DiagnosticErrorCode.INCOMPATIBLE_TYPES, lhsRef.restVar.getBType(), @@ -2695,7 +2714,7 @@ private void checkErrorVarRefEquivalency(BLangErrorVarRef lhsRef, BType rhsType, private BType interpolateWideType(BRecordType rhsDetailType, List detailType) { Set extractedKeys = detailType.stream().map(detail -> detail.name.value).collect(Collectors.toSet()); - BUnionType wideType = BUnionType.create(typeEnv, null); + BUnionType wideType = BUnionType.create(null); for (BField field : rhsDetailType.fields.values()) { // avoid fields extracted from binding pattern if (!extractedKeys.contains(field.name.value)) { @@ -2816,8 +2835,7 @@ public void visit(BLangIf ifNode, AnalyzerData data) { if (existingNarrowedTypeInfo.containsKey(key)) { BType.NarrowedTypes existingNarrowTypes = existingNarrowedTypeInfo.get(key); BUnionType unionType = - BUnionType.create(typeEnv, null, existingNarrowTypes.trueType, - existingNarrowTypes.falseType); + BUnionType.create(null, existingNarrowTypes.trueType, existingNarrowTypes.falseType); BType.NarrowedTypes newPair = new BType.NarrowedTypes(existingNarrowTypes.trueType, unionType); falseTypesOfNarrowedTypes.put(key, newPair); } @@ -2987,10 +3005,10 @@ private void evaluateMatchPatternsTypeAccordingToMatchGuard(BLangMatchPattern ma for (BLangMatchPattern memberMatchPattern : listMatchPattern.matchPatterns) { evaluateMatchPatternsTypeAccordingToMatchGuard(memberMatchPattern, env); BType type = memberMatchPattern.getBType(); - BVarSymbol varSymbol = new BVarSymbol(type.getFlags(), null, null, type, null, null, null); + BVarSymbol varSymbol = new BVarSymbol(type.flags, null, null, type, null, null, null); members.add(new BTupleMember(type, varSymbol)); } - BTupleType matchPatternType = new BTupleType(typeEnv, members); + BTupleType matchPatternType = new BTupleType(members); if (listMatchPattern.restMatchPattern != null) { evaluateMatchPatternsTypeAccordingToMatchGuard(listMatchPattern.restMatchPattern, env); @@ -3041,7 +3059,7 @@ public void visit(BLangMappingMatchPattern mappingMatchPattern, AnalyzerData dat fields.put(fieldName.getValue(), field); mappingMatchPattern.declaredVars.putAll(fieldMatchPattern.declaredVars); } - BRecordType recordVarType = new BRecordType(typeEnv, recordSymbol); + BRecordType recordVarType = new BRecordType(recordSymbol); recordVarType.fields = fields; recordVarType.restFieldType = symTable.anyOrErrorType; if (mappingMatchPattern.restMatchPattern != null) { @@ -3049,7 +3067,7 @@ public void visit(BLangMappingMatchPattern mappingMatchPattern, AnalyzerData dat symbolEnter.createAnonRecordSymbol(currentEnv, mappingMatchPattern.pos); BLangRestMatchPattern restMatchPattern = mappingMatchPattern.restMatchPattern; BType restType = restMatchPattern.getBType(); - BRecordType matchPatternRecType = new BRecordType(typeEnv, matchPattenRecordSym); + BRecordType matchPatternRecType = new BRecordType(matchPattenRecordSym); matchPatternRecType.restFieldType = restType != null ? restType : symTable.anyOrErrorType; recordVarType.restFieldType = matchPatternRecType.restFieldType; restMatchPattern.setBType(matchPatternRecType); @@ -3101,7 +3119,7 @@ private void assignTypesToMemberPatterns(BLangMatchPattern matchPattern, BType b BType type = arrayType.eType; BVarSymbol varSymbol = Symbols.createVarSymbolForTupleMember(type); BTupleType restTupleType = createTupleForClosedArray( - arrayType.getSize() - listMatchPattern.matchPatterns.size(), + arrayType.size - listMatchPattern.matchPatterns.size(), new BTupleMember(type, varSymbol)); listMatchPattern.restMatchPattern.setBType(restTupleType); BVarSymbol restMatchPatternSymbol = listMatchPattern.restMatchPattern.declaredVars @@ -3125,11 +3143,11 @@ private void assignTypesToMemberPatterns(BLangMatchPattern matchPattern, BType b for (int i = 0; i < matchPatterns.size(); i++) { assignTypesToMemberPatterns(matchPatterns.get(i), members.get(i).type, data); BType type = matchPatterns.get(i).getBType(); - BVarSymbol varSymbol = new BVarSymbol(type.getFlags(), null, null, + BVarSymbol varSymbol = new BVarSymbol(type.flags, null, null, type, null, null, null); newMembers.add(new BTupleMember(type, varSymbol)); } - BTupleType tupleType = new BTupleType(typeEnv, newMembers); + BTupleType tupleType = new BTupleType(newMembers); if (listMatchPattern.restMatchPattern == null) { listMatchPattern.setBType(tupleType); @@ -3182,7 +3200,7 @@ private void assignTypesToMemberPatterns(BLangMatchPattern matchPattern, BType b private BTupleType createTupleForClosedArray(int noOfElements, BTupleMember elementType) { List members = Collections.nCopies(noOfElements, elementType); - return new BTupleType(typeEnv, members); + return new BTupleType(members); } private BType createTypeForTupleRestType(int startIndex, List members, BType patternRestType) { @@ -3191,16 +3209,16 @@ private BType createTypeForTupleRestType(int startIndex, List memb remainingMembers.add(members.get(i)); } if (!remainingMembers.isEmpty()) { - BTupleType restTupleType = new BTupleType(typeEnv, remainingMembers); + BTupleType restTupleType = new BTupleType(remainingMembers); if (patternRestType != null) { restTupleType.restType = patternRestType; } return restTupleType; } else { if (patternRestType != null) { - return new BArrayType(typeEnv, patternRestType); + return new BArrayType(patternRestType); } else { - return new BArrayType(typeEnv, symTable.anyOrErrorType); + return new BArrayType(symTable.anyOrErrorType); } } } @@ -3300,18 +3318,18 @@ public void visit(BLangListBindingPattern listBindingPattern, AnalyzerData data) for (BLangBindingPattern bindingPattern : listBindingPattern.bindingPatterns) { analyzeNode(bindingPattern, data); BType type = bindingPattern.getBType(); - BVarSymbol varSymbol = new BVarSymbol(type.getFlags(), null, null, + BVarSymbol varSymbol = new BVarSymbol(type.flags, null, null, type, null, null, null); listMembers.add(new BTupleMember(type, varSymbol)); listBindingPattern.declaredVars.putAll(bindingPattern.declaredVars); } - BTupleType listBindingPatternType = new BTupleType(typeEnv, listMembers); + BTupleType listBindingPatternType = new BTupleType(listMembers); if (listBindingPattern.restBindingPattern != null) { BLangRestBindingPattern restBindingPattern = listBindingPattern.restBindingPattern; BType restBindingPatternType = restBindingPattern.getBType(); BType restType = restBindingPatternType != null ? restBindingPatternType : symTable.anyOrErrorType; - restBindingPattern.setBType(new BArrayType(typeEnv, restType)); + restBindingPattern.setBType(new BArrayType(restType)); restBindingPattern.accept(this, data); listBindingPattern.declaredVars.put(restBindingPattern.variableName.value, restBindingPattern.symbol); listBindingPatternType.restType = restType; @@ -3408,7 +3426,7 @@ public void visit(BLangErrorFieldBindingPatterns errorFieldBindingPatterns, Anal } if (errorFieldBindingPatterns.restBindingPattern != null) { errorFieldBindingPatterns.restBindingPattern.setBType( - new BMapType(typeEnv, TypeTags.MAP, symTable.anydataType, null)); + new BMapType(TypeTags.MAP, symTable.anydataType, null)); analyzeNode(errorFieldBindingPatterns.restBindingPattern, data); errorFieldBindingPatterns.declaredVars.putAll(errorFieldBindingPatterns.restBindingPattern.declaredVars); } @@ -3522,8 +3540,7 @@ public void visit(BLangErrorFieldMatchPatterns errorFieldMatchPatterns, Analyzer errorFieldMatchPatterns.declaredVars.putAll(namedArgMatchPattern.declaredVars); } if (errorFieldMatchPatterns.restMatchPattern != null) { - errorFieldMatchPatterns.restMatchPattern.setBType(new BMapType(typeEnv, TypeTags.MAP, - symTable.anydataType, null)); + errorFieldMatchPatterns.restMatchPattern.setBType(new BMapType(TypeTags.MAP, symTable.anydataType, null)); analyzeNode(errorFieldMatchPatterns.restMatchPattern, data); errorFieldMatchPatterns.declaredVars.putAll(errorFieldMatchPatterns.restMatchPattern.declaredVars); } @@ -3578,7 +3595,7 @@ public void visit(BLangMappingBindingPattern mappingBindingPattern, AnalyzerData fields.put(fieldName.getValue(), field); mappingBindingPattern.declaredVars.putAll(fieldBindingPattern.declaredVars); } - BRecordType recordVarType = new BRecordType(typeEnv, recordSymbol); + BRecordType recordVarType = new BRecordType(recordSymbol); recordVarType.fields = fields; recordVarType.restFieldType = symTable.anyOrErrorType; if (mappingBindingPattern.restBindingPattern != null) { @@ -3586,7 +3603,7 @@ public void visit(BLangMappingBindingPattern mappingBindingPattern, AnalyzerData BType restType = restBindingPattern.getBType(); BRecordTypeSymbol matchPattenRecordSym = symbolEnter.createAnonRecordSymbol(currentEnv, restBindingPattern.pos); - BRecordType matchPatternRecType = new BRecordType(typeEnv, matchPattenRecordSym); + BRecordType matchPatternRecType = new BRecordType(matchPattenRecordSym); matchPatternRecType.restFieldType = restType != null ? restType : symTable.anyOrErrorType; recordVarType.restFieldType = matchPatternRecType.restFieldType; restBindingPattern.setBType(matchPatternRecType); @@ -3640,18 +3657,18 @@ public void visit(BLangListMatchPattern listMatchPattern, AnalyzerData data) { for (BLangMatchPattern memberMatchPattern : listMatchPattern.matchPatterns) { memberMatchPattern.accept(this, data); BType type = memberMatchPattern.getBType(); - BVarSymbol varSymbol = new BVarSymbol(type.getFlags(), null, null, type, null, null, null); + BVarSymbol varSymbol = new BVarSymbol(type.flags, null, null, type, null, null, null); members.add(new BTupleMember(type, varSymbol)); checkForSimilarVars(listMatchPattern.declaredVars, memberMatchPattern.declaredVars, memberMatchPattern.pos); listMatchPattern.declaredVars.putAll(memberMatchPattern.declaredVars); } - BTupleType matchPatternType = new BTupleType(typeEnv, members); + BTupleType matchPatternType = new BTupleType(members); if (listMatchPattern.getRestMatchPattern() != null) { BLangRestMatchPattern restMatchPattern = (BLangRestMatchPattern) listMatchPattern.getRestMatchPattern(); BType restBindingPatternType = restMatchPattern.getBType(); BType restType = restBindingPatternType != null ? restBindingPatternType : symTable.anyOrErrorType; - restMatchPattern.setBType(new BArrayType(typeEnv, restType)); + restMatchPattern.setBType(new BArrayType(restType)); restMatchPattern.accept(this, data); checkForSimilarVars(listMatchPattern.declaredVars, restMatchPattern.declaredVars, restMatchPattern.pos); listMatchPattern.declaredVars.put(restMatchPattern.variableName.value, restMatchPattern.symbol); @@ -3708,7 +3725,7 @@ private void assignTypesToMemberPatterns(BLangBindingPattern bindingPattern, BTy BType type = arrayType.eType; BVarSymbol varSymbol = Symbols.createVarSymbolForTupleMember(type); BTupleType restTupleType = createTupleForClosedArray( - arrayType.getSize() - listBindingPattern.bindingPatterns.size(), + arrayType.size - listBindingPattern.bindingPatterns.size(), new BTupleMember(type, varSymbol)); listBindingPattern.restBindingPattern.setBType(restTupleType); BVarSymbol restBindingPatternSymbol = listBindingPattern.restBindingPattern.declaredVars @@ -3732,10 +3749,10 @@ private void assignTypesToMemberPatterns(BLangBindingPattern bindingPattern, BTy for (int i = 0; i < bindingPatterns.size(); i++) { assignTypesToMemberPatterns(bindingPatterns.get(i), tupleMemebers.get(i).type, data); BType type = bindingPatterns.get(i).getBType(); - BVarSymbol varSymbol = new BVarSymbol(type.getFlags(), null, null, type, null, null, null); + BVarSymbol varSymbol = new BVarSymbol(type.flags, null, null, type, null, null, null); members.add(new BTupleMember(type, varSymbol)); } - BTupleType tupleType = new BTupleType(typeEnv, members); + BTupleType tupleType = new BTupleType(members); if (listBindingPattern.restBindingPattern == null) { bindingPattern.setBType(tupleType); @@ -3861,7 +3878,7 @@ public void visit(BLangOnFailClause onFailClause, AnalyzerData data) { if (currentOnFailErrTypes.size() == 1) { failErrorType = currentOnFailErrTypes.iterator().next(); } else if (currentOnFailErrTypes.size() > 1) { - failErrorType = BUnionType.create(typeEnv, null, currentOnFailErrTypes); + failErrorType = BUnionType.create(null, currentOnFailErrTypes); } else { failErrorType = symTable.neverType; } @@ -3975,7 +3992,7 @@ public void visit(BLangFail failNode, AnalyzerData data) { } } if (errorExpressionType != symTable.semanticError && - !types.isSubTypeOfBaseType(errorExpressionType, PredefinedType.ERROR)) { + !types.isSubTypeOfBaseType(errorExpressionType, symTable.errorType.tag)) { dlog.error(errorExpression.pos, DiagnosticErrorCode.ERROR_TYPE_EXPECTED, errorExpressionType); } data.notCompletedNormally = true; @@ -4015,6 +4032,8 @@ public void visit(BLangService serviceNode, AnalyzerData data) { dlog.error(attachExpr.pos, DiagnosticErrorCode.INCOMPATIBLE_TYPES, LISTENER_NAME, exprType); } else if (exprType != symTable.semanticError && serviceNode.listenerType == null) { serviceNode.listenerType = exprType; + } else if (exprType != symTable.semanticError) { + this.types.isSameType(exprType, serviceNode.listenerType); } if (attachExpr.getKind() == NodeKind.SIMPLE_VARIABLE_REF) { @@ -4081,7 +4100,7 @@ private void inferServiceTypeFromListeners(BLangService serviceNode, AnalyzerDat for (BType attachType : listenerTypes) { typeIdSet.add(getTypeIds(attachType)); } - inferred = BUnionType.create(typeEnv, null, listenerTypes); + inferred = BUnionType.create(null, listenerTypes); } serviceNode.inferredServiceType = inferred; @@ -4204,7 +4223,7 @@ public void visit(BLangTransaction transactionNode, AnalyzerData data) { @Override public void visit(BLangRollback rollbackNode, AnalyzerData data) { if (rollbackNode.expr != null) { - BType expectedType = BUnionType.create(typeEnv, null, symTable.errorType, symTable.nilType); + BType expectedType = BUnionType.create(null, symTable.errorType, symTable.nilType); this.typeChecker.checkExpr(rollbackNode.expr, data.env, expectedType, data.prevEnvs, data.commonAnalyzerData); } @@ -4769,7 +4788,7 @@ private void validateInclusions(Set referencingTypeFlags, List for (BLangType typeRef : typeRefs) { BType type = typeRef.getBType(); - long flags = type.getFlags(); + long flags = type.flags; List mismatchedFlags = new ArrayList<>(); @@ -4922,7 +4941,7 @@ private void validateIsolatedParamUsage(boolean inIsolatedFunction, BLangSimpleV BType type = isRestParam ? ((BArrayType) variable.getBType()).eType : variable.getBType(); - if (!types.isSubTypeOfBaseType(type, PredefinedType.FUNCTION)) { + if (!types.isSubTypeOfBaseType(type, TypeTags.INVOKABLE)) { dlog.error(variable.pos, DiagnosticErrorCode.ISOLATED_PARAM_USED_WITH_INVALID_TYPE); } @@ -4971,7 +4990,7 @@ private void handleReadOnlyField(boolean isRecordType, LinkedHashMap unresolvedTypes; private Set unresolvedRecordDueToFields; private boolean resolveRecordsUnresolvedDueToFields; + private List unresolvedClasses; private final HashSet unknownTypeRefs; private final List importedPackages; private int typePrecedence; @@ -242,6 +241,7 @@ public class SymbolEnter extends BLangNodeVisitor { private final BLangMissingNodesHelper missingNodesHelper; private final PackageCache packageCache; private final List intersectionTypes; + private Map typeToTypeDef; private SymbolEnv env; private final boolean projectAPIInitiatedCompilation; @@ -274,7 +274,6 @@ public SymbolEnter(CompilerContext context) { this.unknownTypeRefs = new HashSet<>(); this.missingNodesHelper = BLangMissingNodesHelper.getInstance(context); this.packageCache = PackageCache.getInstance(context); - this.constResolver = ConstantValueResolver.getInstance(context); this.intersectionTypes = new ArrayList<>(); CompilerOptions options = CompilerOptions.getInstance(context); @@ -492,6 +491,20 @@ private void defineConstructs(BLangPackage pkgNode, SymbolEnv pkgEnv) { typeResolver.clearUnknowTypeRefs(); } + private void defineDependentFields(List typeDefNodes, SymbolEnv pkgEnv) { + for (BLangNode typeDef : typeDefNodes) { + if (typeDef.getKind() == NodeKind.CLASS_DEFN) { + BLangClassDefinition classDefinition = (BLangClassDefinition) typeDef; + if (isObjectCtor(classDefinition)) { + continue; + } + defineReferencedFieldsOfClassDef(classDefinition, pkgEnv); + } else if (typeDef.getKind() == NodeKind.TYPE_DEFINITION) { + defineReferencedFieldsOfRecordTypeDef((BLangTypeDefinition) typeDef); + } + } + } + public void defineReferencedFieldsOfClassDef(BLangClassDefinition classDefinition, SymbolEnv pkgEnv) { SymbolEnv typeDefEnv = classDefinition.typeDefEnv; BObjectTypeSymbol tSymbol = (BObjectTypeSymbol) classDefinition.symbol; @@ -500,6 +513,13 @@ public void defineReferencedFieldsOfClassDef(BLangClassDefinition classDefinitio defineReferencedClassFields(classDefinition, typeDefEnv, objType, false); } + private void defineIntersectionTypes(SymbolEnv env) { + for (BLangNode typeDescriptor : this.intersectionTypes) { + defineNode(typeDescriptor, env); + } + this.intersectionTypes.clear(); + } + private void defineErrorType(Location pos, BErrorType errorType, SymbolEnv env) { SymbolEnv pkgEnv = symTable.pkgEnvMap.get(env.enclPkg.symbol); BTypeSymbol errorTSymbol = errorType.tsymbol; @@ -508,6 +528,18 @@ private void defineErrorType(Location pos, BErrorType errorType, SymbolEnv env) if (symResolver.checkForUniqueSymbol(pos, pkgEnv, errorTSymbol)) { pkgEnv.scope.define(errorTSymbol.name, errorTSymbol); } + + SymbolEnv prevEnv = this.env; + this.env = pkgEnv; + this.env = prevEnv; + } + + private boolean isObjectCtor(BLangNode node) { + if (node.getKind() == NodeKind.CLASS_DEFN) { + BLangClassDefinition classDefinition = (BLangClassDefinition) node; + return isObjectCtor(classDefinition); + } + return false; } public boolean isObjectCtor(BLangClassDefinition classDefinition) { @@ -861,7 +893,7 @@ public void visit(BLangClassDefinition classDefinition) { typeFlags |= Flags.OBJECT_CTOR; } - BObjectType objectType = new BObjectType(symTable.typeEnv(), tSymbol, typeFlags); + BObjectType objectType = new BObjectType(tSymbol, typeFlags); if (classDefinition.isObjectContructorDecl || flags.contains(Flag.OBJECT_CTOR)) { classDefinition.oceEnvData.objectType = objectType; objectType.classDef = classDefinition; @@ -872,7 +904,7 @@ public void visit(BLangClassDefinition classDefinition) { } if (flags.contains(Flag.CLIENT)) { - objectType.addFlags(Flags.CLIENT); + objectType.flags |= Flags.CLIENT; } tSymbol.type = objectType; @@ -1201,6 +1233,83 @@ public void visit(BLangXMLNSStatement xmlnsStmtNode) { defineNode(xmlnsStmtNode.xmlnsDecl, env); } + private void defineTypeNodes(List typeDefs, SymbolEnv env) { + if (typeDefs.isEmpty()) { + return; + } + + this.unresolvedTypes = new ArrayList<>(typeDefs.size()); + this.unresolvedRecordDueToFields = new HashSet<>(typeDefs.size()); + this.resolveRecordsUnresolvedDueToFields = false; + for (BLangNode typeDef : typeDefs) { + if (isErrorIntersectionTypeCreatingNewType(typeDef, env)) { + populateUndefinedErrorIntersection((BLangTypeDefinition) typeDef, env); + continue; + } +// if (isObjectCtor(typeDef)) { +// continue; +// } + + defineNode(typeDef, env); + } + + if (typeDefs.size() <= unresolvedTypes.size()) { + + this.resolveRecordsUnresolvedDueToFields = true; + unresolvedTypes.removeAll(unresolvedRecordDueToFields); + for (BLangNode unresolvedType : unresolvedRecordDueToFields) { + defineNode(unresolvedType, env); + } + this.resolveRecordsUnresolvedDueToFields = false; + + // This situation can occur due to either a cyclic dependency or at least one of member types in type + // definition node cannot be resolved. So we iterate through each node recursively looking for cyclic + // dependencies or undefined types in type node. + + for (BLangNode unresolvedType : unresolvedTypes) { + Deque references = new ArrayDeque<>(); + NodeKind unresolvedKind = unresolvedType.getKind(); + if (unresolvedKind == NodeKind.TYPE_DEFINITION || unresolvedKind == NodeKind.CONSTANT) { + TypeDefinition def = (TypeDefinition) unresolvedType; + // We need to keep track of all visited types to print cyclic dependency. + references.push(def.getName().getValue()); + checkErrors(env, unresolvedType, (BLangNode) def.getTypeNode(), references, false); + } else if (unresolvedType.getKind() == NodeKind.CLASS_DEFN) { + BLangClassDefinition classDefinition = (BLangClassDefinition) unresolvedType; + references.push(classDefinition.getName().getValue()); + checkErrors(env, unresolvedType, classDefinition, references, true); + } + } + defineAllUnresolvedCyclicTypesInScope(env); + + Set alreadyDefinedTypeDefNames = new HashSet<>(); + int unresolvedTypeCount = unresolvedTypes.size(); + for (int i = 0; i < unresolvedTypeCount; i++) { + for (BLangNode node : this.unresolvedTypes) { + String name = getTypeOrClassName(node); + boolean symbolNotFound = false; + boolean isTypeOrClassDefinition = + node.getKind() == NodeKind.TYPE_DEFINITION || node.getKind() == NodeKind.CLASS_DEFN; + // Skip the type resolving in the first iteration (i == 0) + // as we want to define the type before trying to resolve it. + if (isTypeOrClassDefinition && i != 0) { // Do not skip the first iteration + BSymbol bSymbol = symResolver.lookupSymbolInMainSpace(env, Names.fromString(name)); + symbolNotFound = (bSymbol == symTable.notFoundSymbol); + } + + boolean notFoundInList = alreadyDefinedTypeDefNames.add(name); + + // Prevent defining already defined type names. + if (notFoundInList || symbolNotFound) { + defineNode(node, env); + } + } + } + return; + } + defineTypeNodes(unresolvedTypes, env); + } + private void populateUndefinedErrorIntersection(BLangTypeDefinition typeDef, SymbolEnv env) { long flags = 0; if (typeDef.flagSet.contains(Flag.PUBLIC)) { @@ -1448,7 +1557,7 @@ private void checkErrorsOfUserDefinedType(SymbolEnv env, BLangNode unresolvedTyp } } - public static String getTypeOrClassName(BLangNode node) { + public String getTypeOrClassName(BLangNode node) { if (node.getKind() == NodeKind.TYPE_DEFINITION || node.getKind() == NodeKind.CONSTANT) { return ((TypeDefinition) node).getName().getValue(); } else { @@ -1548,7 +1657,7 @@ public void visit(BLangTypeDefinition typeDefinition) { typeDefSymbol.pkgID, typeDefSymbol.type, typeDefSymbol.owner, typeDefSymbol.pos, typeDefSymbol.origin); typeSymbol.markdownDocumentation = typeDefSymbol.markdownDocumentation; ((BTypeDefinitionSymbol) typeDefSymbol).referenceType = new BTypeReferenceType(definedType, typeSymbol, - typeDefSymbol.type.getFlags()); + typeDefSymbol.type.flags); boolean isLabel = true; //todo remove after type ref introduced to runtime @@ -1609,7 +1718,7 @@ public void visit(BLangTypeDefinition typeDefinition) { dlog.error(typeDefinition.pos, DiagnosticErrorCode.TYPE_PARAM_OUTSIDE_LANG_MODULE); } } - definedType.addFlags(typeDefSymbol.flags); + definedType.flags |= typeDefSymbol.flags; typeDefinition.symbol = typeDefSymbol; if (typeDefinition.hasCyclicReference) { @@ -1646,7 +1755,7 @@ public void handleDistinctDefinition(BLangTypeDefinition typeDefinition, BSymbol if (((BTypeDefinitionSymbol) typeDefSymbol).referenceType != null) { ((BTypeDefinitionSymbol) typeDefSymbol).referenceType.referredType = distinctType; } - definedType.addFlags(Flags.DISTINCT); + definedType.flags |= Flags.DISTINCT; } } @@ -1709,12 +1818,12 @@ public void populateAllReadyDefinedErrorIntersection(BType definedType, BLangTyp alreadyDefinedErrorType.typeIdSet = errorType.typeIdSet; alreadyDefinedErrorType.detailType = errorType.detailType; - alreadyDefinedErrorType.setFlags(errorType.getFlags()); + alreadyDefinedErrorType.flags = errorType.flags; alreadyDefinedErrorType.name = errorType.name; intersectionType.effectiveType = alreadyDefinedErrorType; if (!errorType.typeIdSet.isEmpty()) { - definedType.addFlags(Flags.DISTINCT); + definedType.flags |= Flags.DISTINCT; } } @@ -1752,7 +1861,7 @@ private BObjectType getDistinctObjectType(BLangTypeDefinition typeDefinition, BO // `typeDefSymbol` is different to `definedObjType.tsymbol` in a type definition statement that use // already defined type as the base type. if (definedObjType.tsymbol != tSymbol) { - BObjectType objType = new BObjectType(symTable.typeEnv(), tSymbol); + BObjectType objType = new BObjectType(tSymbol); tSymbol.type = objType; definedObjType = objType; } @@ -1777,13 +1886,13 @@ private BType defineSymbolForCyclicTypeDefinition(BLangTypeDefinition typeDef, S typeDefSymbol = switch (typeDef.typeNode.getKind()) { case TUPLE_TYPE_NODE -> { - newTypeNode = new BTupleType(symTable.typeEnv(), null, new ArrayList<>(), true); + newTypeNode = new BTupleType(null, new ArrayList<>(), true); yield Symbols.createTypeSymbol(SymTag.TUPLE_TYPE, Flags.asMask(typeDef.flagSet), newTypeDefName, env.enclPkg.symbol.pkgID, newTypeNode, env.scope.owner, typeDef.name.pos, SOURCE); } default -> { - newTypeNode = BUnionType.create(symTable.typeEnv(), null, new LinkedHashSet<>(), true); + newTypeNode = BUnionType.create(null, new LinkedHashSet<>(), true); yield Symbols.createTypeSymbol(SymTag.UNION_TYPE, Flags.asMask(typeDef.flagSet), newTypeDefName, env.enclPkg.symbol.pkgID, newTypeNode, env.scope.owner, typeDef.name.pos, SOURCE); @@ -1792,7 +1901,7 @@ private BType defineSymbolForCyclicTypeDefinition(BLangTypeDefinition typeDef, S typeDef.symbol = typeDefSymbol; defineTypeInMainScope(typeDefSymbol, typeDef, env); newTypeNode.tsymbol = typeDefSymbol; - newTypeNode.addFlags(typeDefSymbol.flags); + newTypeNode.flags |= typeDefSymbol.flags; return newTypeNode; } @@ -1867,7 +1976,7 @@ private BErrorType getDistinctErrorType(BLangTypeDefinition typeDefinition, BErr if (definedErrorType.tsymbol != typeDefSymbol) { BTypeSymbol typeSymbol = new BTypeSymbol(SymTag.TYPE_DEF, typeDefSymbol.flags, typeDefSymbol.name, typeDefSymbol.pkgID, null, typeDefSymbol.owner, typeDefSymbol.pos, typeDefSymbol.origin); - BErrorType bErrorType = new BErrorType(symTable.typeEnv(), typeSymbol); + BErrorType bErrorType = new BErrorType(typeSymbol); typeSymbol.type = bErrorType; bErrorType.detailType = definedErrorType.detailType; typeDefSymbol.type = bErrorType; @@ -2375,8 +2484,8 @@ boolean checkTypeAndVarCountConsistency(BLangTupleVariable varNode, BTupleType t } if (memberTypes.size() > 1) { - BType type = BUnionType.create(symTable.typeEnv(), null, memberTypes); - BVarSymbol varSymbol = new BVarSymbol(type.getFlags(), null, null, type, null, + BType type = BUnionType.create(null, memberTypes); + BVarSymbol varSymbol = new BVarSymbol(type.flags, null, null, type, null, null, null); members.add(new BTupleMember(type, varSymbol)); } else { @@ -2385,7 +2494,7 @@ boolean checkTypeAndVarCountConsistency(BLangTupleVariable varNode, BTupleType t Symbols.createVarSymbolForTupleMember(m)))); } } - tupleTypeNode = new BTupleType(symTable.typeEnv(), members); + tupleTypeNode = new BTupleType(members); tupleTypeNode.restType = getPossibleRestTypeForUnion(varNode, possibleTypes); break; } @@ -2403,7 +2512,7 @@ boolean checkTypeAndVarCountConsistency(BLangTupleVariable varNode, BTupleType t BVarSymbol varSymbol = Symbols.createVarSymbolForTupleMember(type); members.add(new BTupleMember(type, varSymbol)); } - tupleTypeNode = new BTupleType(symTable.typeEnv(), members); + tupleTypeNode = new BTupleType(members); tupleTypeNode.restType = getPossibleRestTypeForUnion(varNode, possibleTypes); break; case TypeTags.ANY: @@ -2413,7 +2522,7 @@ boolean checkTypeAndVarCountConsistency(BLangTupleVariable varNode, BTupleType t BVarSymbol varSymbol = Symbols.createVarSymbolForTupleMember(referredType); memberTupleTypes.add(new BTupleMember(referredType, varSymbol)); } - tupleTypeNode = new BTupleType(symTable.typeEnv(), memberTupleTypes); + tupleTypeNode = new BTupleType(memberTupleTypes); if (varNode.restVariable != null) { tupleTypeNode.restType = referredType; } @@ -2424,9 +2533,9 @@ boolean checkTypeAndVarCountConsistency(BLangTupleVariable varNode, BTupleType t case TypeTags.ARRAY: List tupleTypes = new ArrayList<>(); BArrayType arrayType = (BArrayType) referredType; - tupleTypeNode = new BTupleType(symTable.typeEnv(), tupleTypes); + tupleTypeNode = new BTupleType(tupleTypes); BType eType = arrayType.eType; - for (int i = 0; i < arrayType.getSize(); i++) { + for (int i = 0; i < arrayType.size; i++) { BType type = arrayType.eType; BVarSymbol varSymbol = Symbols.createVarSymbolForTupleMember(type); tupleTypes.add(new BTupleMember(type, varSymbol)); @@ -2482,11 +2591,11 @@ boolean checkTypeAndVarCountConsistency(BLangTupleVariable varNode, BTupleType t } } if (!members.isEmpty()) { - BTupleType restTupleType = new BTupleType(symTable.typeEnv(), members); + BTupleType restTupleType = new BTupleType(members); restTupleType.restType = restType; type = restTupleType; } else { - type = restType != null ? new BArrayType(symTable.typeEnv(), restType) : null; + type = restType != null ? new BArrayType(restType) : null; } defineMemberNode(varNode.restVariable, env, type); } @@ -2523,7 +2632,7 @@ private BType getPossibleRestTypeForUnion(BLangTupleVariable varNode, List 1 ? BUnionType.create(symTable.typeEnv(), null, memberRestTypes) : + return memberRestTypes.size() > 1 ? BUnionType.create(null, memberRestTypes) : memberRestTypes.iterator().next(); } else { return varNode.getBType(); @@ -2688,7 +2797,7 @@ private BType createRestFieldFromPossibleTypes(Location pos, SymbolEnv env, List } BType restFieldType = restFieldMemberTypes.size() > 1 ? - BUnionType.create(symTable.typeEnv(), null, restFieldMemberTypes) : + BUnionType.create(null, restFieldMemberTypes) : restFieldMemberTypes.iterator().next(); if (!possibleRecordFieldMapList.isEmpty()) { @@ -2708,7 +2817,7 @@ private BType createRestFieldFromPossibleTypes(Location pos, SymbolEnv env, List } unmappedMembers.putAll(optionalFields); - BRecordType restRecord = new BRecordType(symTable.typeEnv(), null); + BRecordType restRecord = new BRecordType(null); restRecord.fields = unmappedMembers; restRecord.restFieldType = restFieldType; restFieldType = restRecord; @@ -2776,7 +2885,7 @@ private LinkedHashMap populateAndGetPossibleFieldsForRecVar(Loca } BType fieldType = memberTypes.size() > 1 ? - BUnionType.create(symTable.typeEnv(), null, memberTypes) : memberTypes.iterator().next(); + BUnionType.create(null, memberTypes) : memberTypes.iterator().next(); BField field = new BField(Names.fromString(fieldName), pos, new BVarSymbol(0, Names.fromString(fieldName), env.enclPkg.symbol.pkgID, fieldType, recordSymbol, pos, SOURCE)); @@ -2791,7 +2900,7 @@ private BRecordType createSameTypedFieldsRecordType(BLangRecordVariable recordVa if (fieldTypes.isNullable()) { fieldType = fieldTypes; } else { - fieldType = BUnionType.create(symTable.typeEnv(), null, fieldTypes, symTable.nilType); + fieldType = BUnionType.create(null, fieldTypes, symTable.nilType); } BRecordTypeSymbol recordSymbol = Symbols.createRecordSymbol(Flags.ANONYMOUS, @@ -2928,31 +3037,21 @@ public BRecordTypeSymbol createAnonRecordSymbol(SymbolEnv env, Location pos) { return recordSymbol; } - BType getRestParamType(BRecordType recordType) { + BType getRestParamType(BRecordType recordType) { BType memberType; if (recordType.restFieldType != null) { memberType = recordType.restFieldType; - BType referredMemberType = Types.getImpliedType(memberType); - if (referredMemberType.tag == TypeTags.RECORD) { - return getRestParamType((BRecordType) referredMemberType); - } else { - return memberType; - } - } - - SemType s = recordType.semType(); - SemType anydata = types.anydata(); - if (SemTypes.containsBasicType(s, PredefinedType.ERROR)) { - if (types.isSubtype(s, Core.union(anydata, PredefinedType.ERROR))) { - return symTable.pureType; - } else { - return BUnionType.create(symTable.typeEnv(), null, symTable.anyType, symTable.errorType); - } - } else if (types.isSubtype(s, anydata)) { - return symTable.anydataType; + } else if (hasErrorTypedField(recordType)) { + memberType = hasOnlyPureTypedFields(recordType) ? symTable.pureType : + BUnionType.create(null, symTable.anyType, symTable.errorType); } else { - return symTable.anyType; + memberType = hasOnlyAnyDataTypedFields(recordType) ? symTable.anydataType : symTable.anyType; + } + BType referredMemberType = Types.getImpliedType(memberType); + if (referredMemberType.tag == TypeTags.RECORD) { + memberType = getRestParamType((BRecordType) referredMemberType); } + return memberType; } public BType getRestMatchPatternConstraintType(BRecordType recordType, @@ -2976,7 +3075,7 @@ public BType getRestMatchPatternConstraintType(BRecordType recordType, } else if (constraintTypes.size() == 1) { restConstraintType = constraintTypes.iterator().next(); } else { - restConstraintType = BUnionType.create(symTable.typeEnv(), null, constraintTypes); + restConstraintType = BUnionType.create(null, constraintTypes); } return restVarSymbolMapType.tag == TypeTags.NONE ? restConstraintType : this.types.mergeTypes(restVarSymbolMapType, restConstraintType); @@ -2986,7 +3085,7 @@ BRecordType createRecordTypeForRestField(Location pos, SymbolEnv env, BRecordTyp List variableList, BType restConstraint) { BRecordTypeSymbol recordSymbol = createAnonRecordSymbol(env, pos); - BRecordType recordVarType = new BRecordType(symTable.typeEnv(), recordSymbol); + BRecordType recordVarType = new BRecordType(recordSymbol); recordSymbol.type = recordVarType; LinkedHashMap unMappedFields = new LinkedHashMap<>() {{ putAll(recordType.fields); @@ -3068,6 +3167,43 @@ private long setSymbolAsOptional(long existingFlags) { return Flags.asMask(unmaskedFlags); } + private boolean hasOnlyAnyDataTypedFields(BRecordType recordType) { + IsAnydataUniqueVisitor isAnydataUniqueVisitor = new IsAnydataUniqueVisitor(); + return isAnydataUniqueVisitor.visit(recordType); + } + + private boolean hasOnlyPureTypedFields(BRecordType recordType) { + IsPureTypeUniqueVisitor isPureTypeUniqueVisitor = new IsPureTypeUniqueVisitor(); + for (BField field : recordType.fields.values()) { + BType fieldType = field.type; + if (!isPureTypeUniqueVisitor.visit(fieldType)) { + return false; + } + isPureTypeUniqueVisitor.reset(); + } + return recordType.sealed || isPureTypeUniqueVisitor.visit(recordType); + } + + private boolean hasErrorTypedField(BRecordType recordType) { + for (BField field : recordType.fields.values()) { + BType type = field.type; + if (hasErrorType(type)) { + return true; + } + } + return hasErrorType(recordType.restFieldType); + } + + private boolean hasErrorType(BType type) { + BType referredType = Types.getImpliedType(type); + int tag = referredType.tag; + if (tag != TypeTags.UNION) { + return tag == TypeTags.ERROR; + } + + return ((BUnionType) referredType).getMemberTypes().stream().anyMatch(this::hasErrorType); + } + @Override public void visit(BLangErrorVariable errorVar) { if (errorVar.isDeclaredWithVar) { @@ -3146,9 +3282,9 @@ boolean validateErrorVariable(BLangErrorVariable errorVariable, SymbolEnv env) { detailType.add(possibleErrType.detailType); } BType errorDetailType = detailType.size() > 1 - ? BUnionType.create(symTable.typeEnv(), null, detailType) + ? BUnionType.create(null, detailType) : detailType.iterator().next(); - errorType = new BErrorType(symTable.typeEnv(), null, errorDetailType); + errorType = new BErrorType(null, errorDetailType); } else { errorType = possibleTypes.get(0); } @@ -3197,7 +3333,7 @@ boolean validateErrorVariable(BLangErrorVariable errorVariable, SymbolEnv env) { env.enclPkg.packageID, symTable.errorType, env.scope.owner, errorVariable.pos, SOURCE); // TODO: detail type need to be a union representing all details of members of `errorType` - errorVariable.setBType(new BErrorType(symTable.typeEnv(), errorTypeSymbol, symTable.detailType)); + errorVariable.setBType(new BErrorType(errorTypeSymbol, symTable.detailType)); return validateErrorVariable(errorVariable, env); } @@ -3224,7 +3360,7 @@ private boolean validateErrorVariable(BLangErrorVariable errorVariable, BErrorTy BLangVariable boundVar = errorDetailEntry.valueBindingPattern; if (entryField != null) { if ((entryField.symbol.flags & Flags.OPTIONAL) == Flags.OPTIONAL) { - boundVar.setBType(BUnionType.create(symTable.typeEnv(), null, entryField.type, symTable.nilType)); + boundVar.setBType(BUnionType.create(null, entryField.type, symTable.nilType)); } else { boundVar.setBType(entryField.type); } @@ -3236,8 +3372,7 @@ private boolean validateErrorVariable(BLangErrorVariable errorVariable, BErrorTy boundVar.setBType(symTable.semanticError); return false; } else { - boundVar.setBType( - BUnionType.create(symTable.typeEnv(), null, recordType.restFieldType, symTable.nilType)); + boundVar.setBType(BUnionType.create(null, recordType.restFieldType, symTable.nilType)); } } @@ -3253,7 +3388,7 @@ private boolean validateErrorVariable(BLangErrorVariable errorVariable, BErrorTy // union of keys whose values are not matched in error binding/match pattern. BTypeSymbol typeSymbol = createTypeSymbol(SymTag.TYPE, env); BType constraint = getRestMapConstraintType(detailFields, matchedDetailFields, recordType); - BMapType restType = new BMapType(symTable.typeEnv(), TypeTags.MAP, constraint, typeSymbol); + BMapType restType = new BMapType(TypeTags.MAP, constraint, typeSymbol); typeSymbol.type = restType; errorVariable.restDetail.setBType(restType); defineMemberNode(errorVariable.restDetail, env, restType); @@ -3266,7 +3401,7 @@ BRecordType getDetailAsARecordType(BErrorType errorType) { if (detailType.getKind() == TypeKind.RECORD) { return (BRecordType) detailType; } - BRecordType detailRecord = new BRecordType(symTable.typeEnv(), null); + BRecordType detailRecord = new BRecordType(null); BMapType detailMap = (BMapType) detailType; detailRecord.sealed = false; detailRecord.restFieldType = detailMap.constraint; @@ -3275,7 +3410,7 @@ BRecordType getDetailAsARecordType(BErrorType errorType) { private BType getRestMapConstraintType(Map errorDetailFields, Set matchedDetailFields, BRecordType recordType) { - BUnionType restUnionType = BUnionType.create(symTable.typeEnv(), null); + BUnionType restUnionType = BUnionType.create(null); if (!recordType.sealed) { BType referredRestFieldType = Types.getImpliedType(recordType.restFieldType); if (referredRestFieldType.tag == TypeTags.UNION) { @@ -3559,39 +3694,38 @@ private void populateLangLibInSymTable(BPackageSymbol packageSymbol) { } } - /** - * Checks if annotation type descriptor is valid. - *

- * The type must be a subtype of one of the following three types: - *

    - *
  • true
  • - *
  • map<value:Cloneable>
  • - *
  • map<value:Cloneable>[]
  • - *
- * - * @param type type to be checked - * @return boolean - */ public boolean isValidAnnotationType(BType type) { - SemType t = type.semType(); - if (SemTypes.isSubtype(types.semTypeCtx, t, symTable.trueType.semType())) { - return true; + type = Types.getImpliedType(type); + if (type == symTable.semanticError) { + return false; } - SemType cloneable = Core.createCloneable(types.semTypeCtx); - if (SemTypes.isSubtypeSimple(t, PredefinedType.MAPPING)) { - return SemTypes.isSubtype(types.semTypeCtx, t, cloneable); - } + switch (type.tag) { + case TypeTags.MAP: + return types.isAssignable(((BMapType) type).constraint, symTable.cloneableType); + case TypeTags.RECORD: + BRecordType recordType = (BRecordType) type; + for (BField field : recordType.fields.values()) { + if (!types.isAssignable(field.type, symTable.cloneableType)) { + return false; + } + } - if (SemTypes.isSubtypeSimple(t, PredefinedType.LIST)) { - // Using projection to get T from T[] - SemType memberTy = Core.listMemberTypeInnerVal(types.semTypeCtx, t, PredefinedType.INT); - if (SemTypes.isSubtypeSimple(memberTy, PredefinedType.MAPPING)) { - return SemTypes.isSubtype(types.semTypeCtx, memberTy, cloneable); - } + BType recordRestType = recordType.restFieldType; + if (recordRestType == null || recordRestType == symTable.noType) { + return true; + } + + return types.isAssignable(recordRestType, symTable.cloneableType); + case TypeTags.ARRAY: + BType elementType = Types.getImpliedType(((BArrayType) type).eType); + if ((elementType.tag == TypeTags.MAP) || (elementType.tag == TypeTags.RECORD)) { + return isValidAnnotationType(elementType); + } + return false; } - return false; + return types.isAssignable(type, symTable.trueType); } /** @@ -3706,6 +3840,20 @@ private BType getDetailType(SymbolEnv typeDefEnv, BLangErrorType errorTypeNode) .orElse(symTable.detailType); } + public void defineFields(List typeDefNodes, SymbolEnv pkgEnv) { + for (BLangNode typeDef : typeDefNodes) { + if (typeDef.getKind() == NodeKind.CLASS_DEFN) { + BLangClassDefinition classDefinition = (BLangClassDefinition) typeDef; + if (isObjectCtor(classDefinition)) { + continue; + } + defineFieldsOfClassDef(classDefinition, pkgEnv); + } else if (typeDef.getKind() == NodeKind.TYPE_DEFINITION) { + defineFields((BLangTypeDefinition) typeDef, pkgEnv); + } + } + } + public void defineFieldsOfClassDef(BLangClassDefinition classDefinition, SymbolEnv env) { SymbolEnv typeDefEnv = SymbolEnv.createClassEnv(classDefinition, classDefinition.symbol.scope, env); BObjectTypeSymbol tSymbol = (BObjectTypeSymbol) classDefinition.symbol; @@ -4120,7 +4268,7 @@ private void validateFieldsAndSetReadOnlyType(List typeDefNodes, Symb BSymbol symbol = typeDef.symbol; BStructureType structureType = (BStructureType) Types.getImpliedType(symbol.type); - if (Symbols.isFlagOn(structureType.getFlags(), Flags.READONLY)) { + if (Symbols.isFlagOn(structureType.flags, Flags.READONLY)) { if (structureType.tag != TypeTags.OBJECT) { continue; } @@ -4188,7 +4336,7 @@ private void validateFieldsAndSetReadOnlyType(List typeDefNodes, Symb if (allImmutableFields) { structureType.tsymbol.flags |= Flags.READONLY; - structureType.addFlags(Flags.READONLY); + structureType.flags |= Flags.READONLY; } } } @@ -4222,7 +4370,7 @@ private void setReadOnlynessOfClassDef(BLangClassDefinition classDef, SymbolEnv BObjectType objectType = (BObjectType) classDef.getBType(); Location pos = classDef.pos; - if (Symbols.isFlagOn(classDef.getBType().getFlags(), Flags.READONLY)) { + if (Symbols.isFlagOn(classDef.getBType().flags, Flags.READONLY)) { if (!types.isSelectivelyImmutableType(objectType, new HashSet<>(), pkgEnv.enclPkg.packageID)) { dlog.error(pos, DiagnosticErrorCode.INVALID_READONLY_OBJECT_TYPE, objectType); return; @@ -4238,13 +4386,13 @@ private void setReadOnlynessOfClassDef(BLangClassDefinition classDef, SymbolEnv for (BField field : fields) { if (!Symbols.isFlagOn(field.symbol.flags, Flags.FINAL) || - !Symbols.isFlagOn(field.type.getFlags(), Flags.READONLY)) { + !Symbols.isFlagOn(field.type.flags, Flags.READONLY)) { return; } } classDef.getBType().tsymbol.flags |= Flags.READONLY; - classDef.getBType().addFlags(Flags.READONLY); + classDef.getBType().flags |= Flags.READONLY; } } @@ -4256,11 +4404,11 @@ private void defineInvokableSymbol(BLangInvokableNode invokableNode, BInvokableS defineInvokableSymbolParams(invokableNode, funcSymbol, invokableEnv); if (Symbols.isFlagOn(funcSymbol.type.tsymbol.flags, Flags.ISOLATED)) { - funcSymbol.type.addFlags(Flags.ISOLATED); + funcSymbol.type.flags |= Flags.ISOLATED; } if (Symbols.isFlagOn(funcSymbol.type.tsymbol.flags, Flags.TRANSACTIONAL)) { - funcSymbol.type.addFlags(Flags.TRANSACTIONAL); + funcSymbol.type.flags |= Flags.TRANSACTIONAL; } } @@ -4433,7 +4581,7 @@ public void defineInvokableTypeNode(BLangFunctionTypeNode functionTypeNode, long bInvokableType.paramTypes = paramTypes; bInvokableType.retType = retType; bInvokableType.restType = restType; - bInvokableType.addFlags(flags); + bInvokableType.flags |= flags; functionTypeNode.setBType(bInvokableType); List allConstituentTypes = new ArrayList<>(paramTypes); @@ -4476,7 +4624,7 @@ void defineInvokableSymbolParams(BLangInvokableNode invokableNode, BInvokableSym functionTypeSymbol.restParam = invokableSymbol.restParam; restType = invokableSymbol.restParam.type; } - invokableSymbol.type = new BInvokableType(symTable.typeEnv(), paramTypes, restType, retType, null); + invokableSymbol.type = new BInvokableType(paramTypes, restType, retType, null); invokableSymbol.type.tsymbol = functionTypeSymbol; invokableSymbol.type.tsymbol.type = invokableSymbol.type; } @@ -4532,6 +4680,13 @@ public void defineTypeNarrowedSymbol(Location location, SymbolEnv targetEnv, BVa defineShadowedSymbol(location, varSymbol, targetEnv); } + private void defineSymbolWithCurrentEnvOwner(Location pos, BSymbol symbol) { + symbol.scope = new Scope(env.scope.owner); + if (symResolver.checkForUniqueSymbol(pos, env, symbol)) { + env.scope.define(symbol.name, symbol); + } + } + public BVarSymbol defineVarSymbol(Location pos, Set flagSet, BType varType, Name varName, SymbolEnv env, boolean isInternal) { return defineVarSymbol(pos, flagSet, varType, varName, varName, env, isInternal); @@ -4775,6 +4930,39 @@ private void validateResourceFunctionAttachedToObject(BLangFunction funcNode, BO } } + private StatementNode createAssignmentStmt(BLangSimpleVariable variable, BVarSymbol varSym, BSymbol fieldVar) { + //Create LHS reference variable + BLangSimpleVarRef varRef = (BLangSimpleVarRef) TreeBuilder.createSimpleVariableReferenceNode(); + varRef.pos = variable.pos; + varRef.variableName = (BLangIdentifier) createIdentifier(fieldVar.name.getValue()); + varRef.pkgAlias = (BLangIdentifier) TreeBuilder.createIdentifierNode(); + varRef.symbol = fieldVar; + varRef.setBType(fieldVar.type); + + //Create RHS variable reference + BLangSimpleVarRef exprVar = (BLangSimpleVarRef) TreeBuilder.createSimpleVariableReferenceNode(); + exprVar.pos = variable.pos; + exprVar.variableName = (BLangIdentifier) createIdentifier(varSym.name.getValue()); + exprVar.pkgAlias = (BLangIdentifier) TreeBuilder.createIdentifierNode(); + exprVar.symbol = varSym; + exprVar.setBType(varSym.type); + + //Create assignment statement + BLangAssignment assignmentStmt = (BLangAssignment) TreeBuilder.createAssignmentNode(); + assignmentStmt.expr = exprVar; + assignmentStmt.pos = variable.pos; + assignmentStmt.setVariable(varRef); + return assignmentStmt; + } + + private IdentifierNode createIdentifier(String value) { + IdentifierNode node = TreeBuilder.createIdentifierNode(); + if (value != null) { + node.setValue(value); + } + return node; + } + private boolean validateFuncReceiver(BLangFunction funcNode) { if (funcNode.receiver == null) { return true; @@ -4811,6 +4999,11 @@ private Name getFuncSymbolOriginalName(BLangFunction funcNode) { return names.originalNameFromIdNode(funcNode.name); } + private Name getFieldSymbolName(BLangSimpleVariable receiver, BLangSimpleVariable variable) { + return Names.fromString(Symbols.getAttachedFuncSymbolName( + receiver.getBType().tsymbol.name.value, variable.name.value)); + } + public MarkdownDocAttachment getMarkdownDocAttachment(BLangMarkdownDocumentation docNode) { if (docNode == null) { return new MarkdownDocAttachment(0); @@ -5008,8 +5201,8 @@ private void defineReferencedFunction(Location location, Set flagSet, Symb // If not, define the function symbol within the object. // Take a copy of the symbol, with the new name, and the package ID same as the object type. - BInvokableSymbol funcSymbol = ASTBuilderUtil.duplicateFunctionDeclarationSymbol(symTable.typeEnv(), - referencedFuncSymbol, typeDefSymbol, funcName, typeDefSymbol.pkgID, typeRef.pos, getOrigin(funcName)); + BInvokableSymbol funcSymbol = ASTBuilderUtil.duplicateFunctionDeclarationSymbol(referencedFuncSymbol, + typeDefSymbol, funcName, typeDefSymbol.pkgID, typeRef.pos, getOrigin(funcName)); defineSymbol(typeRef.pos, funcSymbol, objEnv); // Create and define the parameters and receiver. This should be done after defining the function symbol. @@ -5123,12 +5316,12 @@ private void setTypeFromLambdaExpr(BLangVariable variable) { BLangFunction function = ((BLangLambdaFunction) variable.expr).function; BInvokableType invokableType = (BInvokableType) function.symbol.type; if (function.flagSet.contains(Flag.ISOLATED)) { - invokableType.addFlags(Flags.ISOLATED); + invokableType.flags |= Flags.ISOLATED; invokableType.tsymbol.flags |= Flags.ISOLATED; } if (function.flagSet.contains(Flag.TRANSACTIONAL)) { - invokableType.addFlags(Flags.TRANSACTIONAL); + invokableType.flags |= Flags.TRANSACTIONAL; invokableType.tsymbol.flags |= Flags.TRANSACTIONAL; } @@ -5177,7 +5370,7 @@ private boolean isInvalidIncludedTypeInClass(BType includedType) { } private boolean isImmutable(BObjectType objectType) { - if (Symbols.isFlagOn(objectType.getFlags(), Flags.READONLY)) { + if (Symbols.isFlagOn(objectType.flags, Flags.READONLY)) { return true; } @@ -5188,7 +5381,7 @@ private boolean isImmutable(BObjectType objectType) { for (BField field : fields) { if (!Symbols.isFlagOn(field.symbol.flags, Flags.FINAL) || - !Symbols.isFlagOn(field.type.getFlags(), Flags.READONLY)) { + !Symbols.isFlagOn(field.type.flags, Flags.READONLY)) { return false; } } @@ -5200,7 +5393,7 @@ private boolean isReadOnlyAndObjectIntersection(BIntersectionType referredType) BType effectiveType = referredType.effectiveType; if (Types.getImpliedType(effectiveType).tag != TypeTags.OBJECT || - !Symbols.isFlagOn(effectiveType.getFlags(), Flags.READONLY)) { + !Symbols.isFlagOn(effectiveType.flags, Flags.READONLY)) { return false; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SymbolResolver.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SymbolResolver.java index c0536ed6796b..449ef9f0c2ad 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SymbolResolver.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SymbolResolver.java @@ -19,7 +19,6 @@ import io.ballerina.tools.diagnostics.DiagnosticCode; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.PredefinedType; import org.ballerinalang.model.TreeBuilder; import org.ballerinalang.model.elements.AttachPoint; import org.ballerinalang.model.elements.Flag; @@ -57,6 +56,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BArrayType; import org.wso2.ballerinalang.compiler.semantics.model.types.BErrorType; import org.wso2.ballerinalang.compiler.semantics.model.types.BField; +import org.wso2.ballerinalang.compiler.semantics.model.types.BFiniteType; import org.wso2.ballerinalang.compiler.semantics.model.types.BFutureType; import org.wso2.ballerinalang.compiler.semantics.model.types.BIntersectionType; import org.wso2.ballerinalang.compiler.semantics.model.types.BInvokableType; @@ -418,7 +418,7 @@ public BSymbol resolveBinaryOperator(OperatorKind opKind, private BSymbol createEqualityOperator(OperatorKind opKind, BType lhsType, BType rhsType) { List paramTypes = Lists.of(lhsType, rhsType); BType retType = symTable.booleanType; - BInvokableType opType = new BInvokableType(symTable.typeEnv(), paramTypes, retType, null); + BInvokableType opType = new BInvokableType(paramTypes, retType, null); return new BOperatorSymbol(Names.fromString(opKind.value()), null, opType, null, symTable.builtinPos, VIRTUAL); } @@ -434,19 +434,19 @@ public BSymbol resolveOperator(Name name, List types) { private BSymbol createBinaryComparisonOperator(OperatorKind opKind, BType lhsType, BType rhsType) { List paramTypes = Lists.of(lhsType, rhsType); - BInvokableType opType = new BInvokableType(symTable.typeEnv(), paramTypes, symTable.booleanType, null); + BInvokableType opType = new BInvokableType(paramTypes, symTable.booleanType, null); return new BOperatorSymbol(Names.fromString(opKind.value()), null, opType, null, symTable.builtinPos, VIRTUAL); } private BSymbol createBinaryOperator(OperatorKind opKind, BType lhsType, BType rhsType, BType retType) { List paramTypes = Lists.of(lhsType, rhsType); - BInvokableType opType = new BInvokableType(symTable.typeEnv(), paramTypes, retType, null); + BInvokableType opType = new BInvokableType(paramTypes, retType, null); return new BOperatorSymbol(Names.fromString(opKind.value()), null, opType, null, symTable.builtinPos, VIRTUAL); } BSymbol createUnaryOperator(OperatorKind kind, BType type, BType retType) { List paramTypes = Lists.of(type); - BInvokableType opType = new BInvokableType(symTable.typeEnv(), paramTypes, retType, null); + BInvokableType opType = new BInvokableType(paramTypes, retType, null); return new BOperatorSymbol(Names.fromString(kind.value()), null, opType, null, symTable.builtinPos, VIRTUAL); } @@ -564,9 +564,9 @@ private BType resolveTypeNode(BLangType typeNode, AnalyzerData data, SymbolEnv e BUnionType unionType = (BUnionType) refType; unionType.add(symTable.nilType); } else if (typeNode.nullable && resultType.tag != TypeTags.JSON && resultType.tag != TypeTags.ANY) { - resultType = BUnionType.create(symTable.typeEnv(), null, resultType, symTable.nilType); + resultType = BUnionType.create(null, resultType, symTable.nilType); } else if (typeNode.nullable && refType.tag != TypeTags.JSON && refType.tag != TypeTags.ANY) { - resultType = BUnionType.create(symTable.typeEnv(), null, resultType, symTable.nilType); + resultType = BUnionType.create(null, resultType, symTable.nilType); } } @@ -1046,13 +1046,12 @@ public void bootstrapAnydataType() { continue; } BUnionType type = (BUnionType) Types.getImpliedType(entry.symbol.type); - symTable.anydataType = new BAnydataType(types.semTypeCtx, type); + symTable.anydataType = new BAnydataType(type); Optional immutableType = Types.getImmutableType(symTable, PackageID.ANNOTATIONS, type); if (immutableType.isPresent()) { Types.addImmutableType(symTable, PackageID.ANNOTATIONS, symTable.anydataType, immutableType.get()); } - symTable.anydataOrReadonly = - BUnionType.create(symTable.typeEnv(), null, symTable.anydataType, symTable.readonlyType); + symTable.anydataOrReadonly = BUnionType.create(null, symTable.anydataType, symTable.readonlyType); entry.symbol.type = symTable.anydataType; entry.symbol.origin = BUILTIN; @@ -1071,7 +1070,7 @@ public void bootstrapJsonType() { continue; } BUnionType type = (BUnionType) Types.getImpliedType(entry.symbol.type); - symTable.jsonType = new BJSONType(types.semTypeCtx, type); + symTable.jsonType = new BJSONType(type); Optional immutableType = Types.getImmutableType(symTable, PackageID.ANNOTATIONS, type); if (immutableType.isPresent()) { @@ -1099,24 +1098,21 @@ public void bootstrapCloneableType() { new BTypeSymbol(SymTag.TYPE, Flags.PUBLIC, Names.CLONEABLE, PackageID.VALUE, symTable.cloneableType, symTable.langValueModuleSymbol, symTable.builtinPos, BUILTIN); - symTable.detailType = new BMapType(symTable.typeEnv(), TypeTags.MAP, symTable.cloneableType, null); - symTable.errorType = new BErrorType(symTable.typeEnv(), null, symTable.detailType); + symTable.detailType = new BMapType(TypeTags.MAP, symTable.cloneableType, null); + symTable.errorType = new BErrorType(null, symTable.detailType); symTable.errorType.tsymbol = new BErrorTypeSymbol(SymTag.ERROR, Flags.PUBLIC, Names.ERROR, symTable.rootPkgSymbol.pkgID, symTable.errorType, symTable.rootPkgSymbol, symTable.builtinPos , BUILTIN); - symTable.errorOrNilType = - BUnionType.create(symTable.typeEnv(), null, symTable.errorType, symTable.nilType); - symTable.anyOrErrorType = - BUnionType.create(symTable.typeEnv(), null, symTable.anyType, symTable.errorType); + symTable.errorOrNilType = BUnionType.create(null, symTable.errorType, symTable.nilType); + symTable.anyOrErrorType = BUnionType.create(null, symTable.anyType, symTable.errorType); - symTable.mapAllType = new BMapType(symTable.typeEnv(), TypeTags.MAP, symTable.anyOrErrorType, null); - symTable.arrayAllType = new BArrayType(symTable.typeEnv(), symTable.anyOrErrorType); + symTable.mapAllType = new BMapType(TypeTags.MAP, symTable.anyOrErrorType, null); + symTable.arrayAllType = new BArrayType(symTable.anyOrErrorType); symTable.typeDesc.constraint = symTable.anyOrErrorType; symTable.futureType.constraint = symTable.anyOrErrorType; - symTable.pureType = - BUnionType.create(symTable.typeEnv(), null, symTable.anydataType, symTable.errorType); + symTable.pureType = BUnionType.create(null, symTable.anydataType, symTable.errorType); return; } throw new IllegalStateException("built-in 'lang.value:Cloneable' type not found"); @@ -1202,7 +1198,7 @@ public BType transform(BLangArrayType arrayTypeNode, AnalyzerData data) { data.env.enclPkg.symbol.pkgID, null, data.env.scope.owner, arrayTypeNode.pos, SOURCE); BArrayType arrType; if (arrayTypeNode.sizes.isEmpty()) { - arrType = new BArrayType(symTable.typeEnv(), resultType, arrayTypeSymbol); + arrType = new BArrayType(resultType, arrayTypeSymbol); } else { BLangExpression size = arrayTypeNode.sizes.get(i); if (size.getKind() == NodeKind.LITERAL || size.getKind() == NodeKind.NUMERIC_LITERAL) { @@ -1215,8 +1211,7 @@ public BType transform(BLangArrayType arrayTypeNode, AnalyzerData data) { } else { arrayState = BArrayState.CLOSED; } - arrType = - new BArrayType(symTable.typeEnv(), resultType, arrayTypeSymbol, sizeIndicator, arrayState); + arrType = new BArrayType(resultType, arrayTypeSymbol, sizeIndicator, arrayState); } else { if (size.getKind() != NodeKind.SIMPLE_VARIABLE_REF) { dlog.error(size.pos, DiagnosticErrorCode.INCOMPATIBLE_TYPES, symTable.intType, @@ -1266,8 +1261,7 @@ public BType transform(BLangArrayType arrayTypeNode, AnalyzerData data) { } else { length = (int) lengthCheck; } - arrType = - new BArrayType(symTable.typeEnv(), resultType, arrayTypeSymbol, length, BArrayState.CLOSED); + arrType = new BArrayType(resultType, arrayTypeSymbol, length, BArrayState.CLOSED); } } arrayTypeSymbol.type = arrType; @@ -1297,7 +1291,7 @@ public BType transform(BLangUnionTypeNode unionTypeNode, AnalyzerData data) { Names.EMPTY, data.env.enclPkg.symbol.pkgID, null, data.env.scope.owner, unionTypeNode.pos, SOURCE); - BUnionType unionType = BUnionType.create(symTable.typeEnv(), unionTypeSymbol, memberTypes); + BUnionType unionType = BUnionType.create(unionTypeSymbol, memberTypes); unionTypeSymbol.type = unionType; markParameterizedType(unionType, memberTypes); @@ -1334,7 +1328,7 @@ public BType transform(BLangObjectTypeNode objectTypeNode, AnalyzerData data) { BTypeSymbol objectSymbol = Symbols.createObjectSymbol(Flags.asMask(flags), Names.EMPTY, data.env.enclPkg.symbol.pkgID, null, data.env.scope.owner, objectTypeNode.pos, SOURCE); - BObjectType objectType = new BObjectType(symTable.typeEnv(), objectSymbol, typeFlags); + BObjectType objectType = new BObjectType(objectSymbol, typeFlags); objectSymbol.type = objectType; objectTypeNode.symbol = objectSymbol; @@ -1354,7 +1348,7 @@ public BType transform(BLangRecordTypeNode recordTypeNode, AnalyzerData data) { data.env.enclPkg.symbol.pkgID, null, data.env.scope.owner, recordTypeNode.pos, recordTypeNode.isAnonymous ? VIRTUAL : SOURCE); - BRecordType recordType = new BRecordType(symTable.typeEnv(), recordSymbol); + BRecordType recordType = new BRecordType(recordSymbol); recordSymbol.type = recordType; recordTypeNode.symbol = recordSymbol; @@ -1381,7 +1375,7 @@ public BType transform(BLangStreamType streamTypeNode, AnalyzerData data) { return symTable.noType; } - BType streamType = new BStreamType(symTable.typeEnv(), TypeTags.STREAM, constraintType, error, null); + BType streamType = new BStreamType(TypeTags.STREAM, constraintType, error, null); BTypeSymbol typeSymbol = type.tsymbol; streamType.tsymbol = Symbols.createTypeSymbol(typeSymbol.tag, typeSymbol.flags, typeSymbol.name, typeSymbol.originalName, typeSymbol.pkgID, streamType, @@ -1404,7 +1398,7 @@ public BType transform(BLangTableTypeNode tableTypeNode, AnalyzerData data) { return symTable.noType; } - BTableType tableType = new BTableType(symTable.typeEnv(), constraintType, null); + BTableType tableType = new BTableType(TypeTags.TABLE, constraintType, null); BTypeSymbol typeSymbol = type.tsymbol; tableType.tsymbol = Symbols.createTypeSymbol(SymTag.TYPE, Flags.asMask(EnumSet.noneOf(Flag.class)), typeSymbol.name, typeSymbol.originalName, typeSymbol.pkgID, @@ -1442,7 +1436,22 @@ public BType transform(BLangTableTypeNode tableTypeNode, AnalyzerData data) { @Override public BType transform(BLangFiniteTypeNode finiteTypeNode, AnalyzerData data) { - return typeResolver.resolveSingletonType(finiteTypeNode, data.env); + BTypeSymbol finiteTypeSymbol = Symbols.createTypeSymbol(SymTag.FINITE_TYPE, + Flags.asMask(EnumSet.of(Flag.PUBLIC)), Names.EMPTY, + data.env.enclPkg.symbol.pkgID, null, data.env.scope.owner, + finiteTypeNode.pos, SOURCE); + + // In case we encounter unary expressions in finite type, we will be replacing them with numeric literals + // Note: calling semanticAnalyzer form symbolResolver is a temporary fix. + semanticAnalyzer.analyzeNode(finiteTypeNode, data.env); + + BFiniteType finiteType = new BFiniteType(finiteTypeSymbol); + for (BLangExpression expressionOrLiteral : finiteTypeNode.valueSpace) { + finiteType.addValue(expressionOrLiteral); + } + finiteTypeSymbol.type = finiteType; + + return finiteType; } @Override @@ -1472,9 +1481,9 @@ public BType transform(BLangTupleTypeNode tupleTypeNode, AnalyzerData data) { } List tupleMembers = new ArrayList<>(); members.forEach(member -> tupleMembers.add(new BTupleMember(member.getBType(), - new BVarSymbol(member.getBType().getFlags(), member.symbol.name, member.symbol.pkgID, member.getBType(), + new BVarSymbol(member.getBType().flags, member.symbol.name, member.symbol.pkgID, member.getBType(), member.symbol.owner, member.pos, SOURCE)))); - BTupleType tupleType = new BTupleType(symTable.typeEnv(), tupleTypeSymbol, tupleMembers); + BTupleType tupleType = new BTupleType(tupleTypeSymbol, tupleMembers); tupleTypeSymbol.type = tupleType; if (tupleTypeNode.restParamType != null) { @@ -1521,8 +1530,8 @@ public BType transform(BLangErrorType errorTypeNode, AnalyzerData data) { symbolEnter.defineSymbol(errorTypeNode.pos, errorTypeSymbol, data.env); } - BErrorType errorType = new BErrorType(symTable.typeEnv(), errorTypeSymbol, detailType); - errorType.addFlags(errorTypeSymbol.flags); + BErrorType errorType = new BErrorType(errorTypeSymbol, detailType); + errorType.flags |= errorTypeSymbol.flags; errorTypeSymbol.type = errorType; markParameterizedType(errorType, detailType); @@ -1548,11 +1557,11 @@ public BType transform(BLangConstrainedType constrainedTypeNode, AnalyzerData da BType constrainedType; if (type.tag == TypeTags.FUTURE) { - constrainedType = new BFutureType(symTable.typeEnv(), constraintType, null); + constrainedType = new BFutureType(TypeTags.FUTURE, constraintType, null); } else if (type.tag == TypeTags.MAP) { - constrainedType = new BMapType(symTable.typeEnv(), TypeTags.MAP, constraintType, null); + constrainedType = new BMapType(TypeTags.MAP, constraintType, null); } else if (type.tag == TypeTags.TYPEDESC) { - constrainedType = new BTypedescType(symTable.typeEnv(), constraintType, null); + constrainedType = new BTypedescType(constraintType, null); } else if (type.tag == TypeTags.XML) { if (Types.getImpliedType(constraintType).tag == TypeTags.PARAMETERIZED_TYPE) { BType typedescType = ((BParameterizedType) constraintType).paramSymbol.type; @@ -1575,11 +1584,32 @@ public BType transform(BLangConstrainedType constrainedTypeNode, AnalyzerData da } public void validateXMLConstraintType(BType type, Location pos) { - if (!SemTypeHelper.isSubtypeSimple(type, PredefinedType.XML)) { + BType constraintType = Types.getImpliedType(type); + int constrainedTag = constraintType.tag; + + if (constrainedTag == TypeTags.UNION) { + checkUnionTypeForXMLSubTypes((BUnionType) constraintType, pos); + return; + } + + if (!TypeTags.isXMLTypeTag(constrainedTag) && constrainedTag != TypeTags.NEVER) { dlog.error(pos, DiagnosticErrorCode.INCOMPATIBLE_TYPE_CONSTRAINT, symTable.xmlType, type); } } + private void checkUnionTypeForXMLSubTypes(BUnionType constraintUnionType, Location pos) { + for (BType memberType : constraintUnionType.getMemberTypes()) { + memberType = Types.getImpliedType(memberType); + if (memberType.tag == TypeTags.UNION) { + checkUnionTypeForXMLSubTypes((BUnionType) memberType, pos); + } + if (!TypeTags.isXMLTypeTag(memberType.tag)) { + dlog.error(pos, DiagnosticErrorCode.INCOMPATIBLE_TYPE_CONSTRAINT, symTable.xmlType, + constraintUnionType); + } + } + } + @Override public BType transform(BLangUserDefinedType userDefinedTypeNode, AnalyzerData data) { String name = userDefinedTypeNode.typeName.value; @@ -1657,7 +1687,7 @@ public BType transform(BLangUserDefinedType userDefinedTypeNode, AnalyzerData da null, func.symbol, tempSymbol.pos, VIRTUAL); tSymbol.type = new BParameterizedType(paramValType, (BVarSymbol) tempSymbol, tSymbol, tempSymbol.name, parameterizedTypeInfo.index); - tSymbol.type.addFlags(Flags.PARAMETERIZED); + tSymbol.type.flags |= Flags.PARAMETERIZED; userDefinedTypeNode.symbol = tSymbol; return tSymbol.type; @@ -1699,7 +1729,7 @@ public BType transform(BLangUserDefinedType userDefinedTypeNode, AnalyzerData da tempSymbol.pos, VIRTUAL); tSymbol.type = new BParameterizedType(paramValType, (BVarSymbol) tempSymbol, tSymbol, tempSymbol.name, parameterizedTypeInfo.index); - tSymbol.type.addFlags(Flags.PARAMETERIZED); + tSymbol.type.flags |= Flags.PARAMETERIZED; userDefinedTypeNode.symbol = tSymbol; return tSymbol.type; } @@ -1729,8 +1759,8 @@ public BType transform(BLangUserDefinedType userDefinedTypeNode, AnalyzerData da if (symbol.kind == SymbolKind.TYPE_DEF && !Symbols.isFlagOn(symbol.flags, Flags.ANONYMOUS) && !isCloneableTypeDef) { BType referenceType = ((BTypeDefinitionSymbol) symbol).referenceType; - referenceType.addFlags(symbol.type.getFlags()); - referenceType.tsymbol.flags |= symbol.type.getFlags(); + referenceType.flags |= symbol.type.flags; + referenceType.tsymbol.flags |= symbol.type.flags; return referenceType; } @@ -1783,8 +1813,8 @@ public BType transform(BLangFunctionTypeNode functionTypeNode, AnalyzerData data BInvokableTypeSymbol invokableTypeSymbol; BInvokableType invokableType; if (functionTypeNode.flagSet.contains(Flag.ANY_FUNCTION)) { - invokableType = new BInvokableType(symTable.typeEnv(), List.of(), null, null, null); - invokableType.setFlags(Flags.asMask(functionTypeNode.flagSet)); + invokableType = new BInvokableType(null, null, null, null); + invokableType.flags = Flags.asMask(functionTypeNode.flagSet); invokableTypeSymbol = Symbols.createInvokableTypeSymbol(SymTag.FUNCTION_TYPE, Flags.asMask(functionTypeNode.flagSet), env.enclPkg.symbol.pkgID, invokableType, @@ -1798,7 +1828,7 @@ public BType transform(BLangFunctionTypeNode functionTypeNode, AnalyzerData data Flags.asMask(functionTypeNode.flagSet), env.enclPkg.symbol.pkgID, functionTypeNode.getBType(), env.scope.owner, functionTypeNode.pos, VIRTUAL); - invokableType = new BInvokableType(symTable.typeEnv(), invokableTypeSymbol); + invokableType = new BInvokableType(invokableTypeSymbol); invokableTypeSymbol.type = invokableType; invokableTypeSymbol.name = Names.fromString(anonymousModelHelper.getNextAnonymousTypeKey(env.enclPkg.packageID)); @@ -1858,7 +1888,9 @@ public BSymbol getBinaryEqualityForTypeSets(OperatorKind opKind, BType lhsType, break; case REF_EQUAL: case REF_NOT_EQUAL: - validEqualityIntersectionExists = types.intersectionExists(lhsType.semType(), rhsType.semType()); + validEqualityIntersectionExists = + types.getTypeIntersection(Types.IntersectionContext.compilerInternalIntersectionTestContext(), + lhsType, rhsType, env) != symTable.semanticError; break; default: return symTable.notFoundSymbol; @@ -1917,7 +1949,7 @@ public BSymbol getBitwiseShiftOpsForTypeSets(OperatorKind opKind, BType lhsType, private BSymbol createShiftOperator(OperatorKind opKind, BType lhsType, BType rhsType) { if (lhsType.isNullable() || rhsType.isNullable()) { - BType intOptional = BUnionType.create(symTable.typeEnv(), null, symTable.intType, symTable.nilType); + BType intOptional = BUnionType.create(null, symTable.intType, symTable.nilType); return createBinaryOperator(opKind, lhsType, rhsType, intOptional); } return createBinaryOperator(opKind, lhsType, rhsType, symTable.intType); @@ -1965,7 +1997,7 @@ public BSymbol getArithmeticOpsForTypeSets(OperatorKind opKind, BType lhsType, B BType returnType = compatibleType1.tag < compatibleType2.tag ? compatibleType2 : compatibleType1; if (lhsType.isNullable() || rhsType.isNullable()) { - returnType = BUnionType.create(symTable.typeEnv(), null, returnType, symTable.nilType); + returnType = BUnionType.create(null, returnType, symTable.nilType); } return createBinaryOperator(opKind, lhsType, rhsType, returnType); @@ -2006,8 +2038,7 @@ public BSymbol getUnaryOpsForTypeSets(OperatorKind opKind, BType type) { } if (type.isNullable()) { BType compatibleType = types.findCompatibleType(types.getSafeType(type, true, false)); - return createUnaryOperator(opKind, type, - BUnionType.create(symTable.typeEnv(), null, compatibleType, symTable.nilType)); + return createUnaryOperator(opKind, type, BUnionType.create(null, compatibleType, symTable.nilType)); } return createUnaryOperator(opKind, type, types.findCompatibleType(type)); } @@ -2036,7 +2067,7 @@ public BSymbol getBinaryBitwiseOpsForTypeSets(OperatorKind opKind, BType lhsType case TypeTags.UNSIGNED32_INT: return createBinaryOperator(opKind, lhsType, rhsType, lhsType); } - + switch (referredRhsType.tag) { case TypeTags.UNSIGNED8_INT: case TypeTags.BYTE: @@ -2044,18 +2075,16 @@ public BSymbol getBinaryBitwiseOpsForTypeSets(OperatorKind opKind, BType lhsType case TypeTags.UNSIGNED32_INT: return createBinaryOperator(opKind, lhsType, rhsType, rhsType); } - + if (referredLhsType.isNullable() || referredRhsType.isNullable()) { - BType intOptional = - BUnionType.create(symTable.typeEnv(), null, symTable.intType, symTable.nilType); + BType intOptional = BUnionType.create(null, symTable.intType, symTable.nilType); return createBinaryOperator(opKind, lhsType, rhsType, intOptional); } return createBinaryOperator(opKind, lhsType, rhsType, symTable.intType); case BITWISE_OR: case BITWISE_XOR: if (referredLhsType.isNullable() || referredRhsType.isNullable()) { - BType intOptional = - BUnionType.create(symTable.typeEnv(), null, symTable.intType, symTable.nilType); + BType intOptional = BUnionType.create(null, symTable.intType, symTable.nilType); return createBinaryOperator(opKind, lhsType, rhsType, intOptional); } return createBinaryOperator(opKind, lhsType, rhsType, symTable.intType); @@ -2079,7 +2108,8 @@ public BSymbol getBinaryComparisonOpForTypeSets(OperatorKind opKind, BType lhsTy case LESS_EQUAL: case GREATER_THAN: case GREATER_EQUAL: - validOrderedTypesExist = types.comparable(lhsType, rhsType); + validOrderedTypesExist = types.isOrderedType(lhsType, false) && + types.isOrderedType(rhsType, false) && types.isSameOrderedType(lhsType, rhsType); break; default: return symTable.notFoundSymbol; @@ -2136,16 +2166,16 @@ public boolean isBinaryComparisonOperator(OperatorKind binaryOpKind) { } public boolean markParameterizedType(BType type, BType constituentType) { - if (Symbols.isFlagOn(constituentType.getFlags(), Flags.PARAMETERIZED)) { + if (Symbols.isFlagOn(constituentType.flags, Flags.PARAMETERIZED)) { type.tsymbol.flags |= Flags.PARAMETERIZED; - type.addFlags(Flags.PARAMETERIZED); + type.flags |= Flags.PARAMETERIZED; return true; } return false; } public void markParameterizedType(BType enclosingType, Collection constituentTypes) { - if (Symbols.isFlagOn(enclosingType.getFlags(), Flags.PARAMETERIZED)) { + if (Symbols.isFlagOn(enclosingType.flags, Flags.PARAMETERIZED)) { return; } @@ -2172,7 +2202,7 @@ private BSymbol resolveOperator(ScopeEntry entry, List typeList) { for (int i = 0; i < typeList.size(); i++) { BType t = Types.getImpliedType(typeList.get(i)); if ((t.getKind() == TypeKind.UNION) && (opType.paramTypes.get(i).getKind() == TypeKind.UNION)) { - if (!this.types.isSameTypeIncludingTags(t, opType.paramTypes.get(i))) { + if (!this.types.isSameType(t, opType.paramTypes.get(i))) { match = false; } } else if (t.tag != opType.paramTypes.get(i).tag) { @@ -2353,11 +2383,11 @@ private BType computeIntersectionType(BLangIntersectionTypeNode intersectionType } if (types.isInherentlyImmutableType(potentialIntersectionType) || - (Symbols.isFlagOn(potentialIntersectionType.getFlags(), Flags.READONLY) && + (Symbols.isFlagOn(potentialIntersectionType.flags, Flags.READONLY) && // For objects, a new type has to be created. !types.isSubTypeOfBaseType(potentialIntersectionType, TypeTags.OBJECT))) { BTypeSymbol effectiveTypeTSymbol = potentialIntersectionType.tsymbol; - return createIntersectionType(potentialIntersectionType, constituentBTypes, effectiveTypeTSymbol.pkgID, + return createIntersectionType(potentialIntersectionType, constituentBTypes, effectiveTypeTSymbol.pkgID, effectiveTypeTSymbol.owner, intersectionTypeNode.pos); } @@ -2427,8 +2457,8 @@ private BIntersectionType createIntersectionType(BType effectiveType, BTypeSymbol intersectionTypeSymbol = Symbols.createTypeSymbol(SymTag.INTERSECTION_TYPE, 0, Names.EMPTY, pkgId, null, owner, pos, VIRTUAL); - BIntersectionType intersectionType = new BIntersectionType(intersectionTypeSymbol, constituentBTypes, - effectiveType, effectiveType.getFlags()); + BIntersectionType intersectionType = + new BIntersectionType(intersectionTypeSymbol, constituentBTypes, effectiveType, effectiveType.flags); intersectionTypeSymbol.type = intersectionType; return intersectionType; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java index 4e6f8e9b4c48..44926d6ef6cf 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java @@ -20,24 +20,6 @@ import io.ballerina.identifier.Utils; import io.ballerina.tools.diagnostics.DiagnosticCode; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.BasicTypeBitSet; -import io.ballerina.types.BasicTypeCode; -import io.ballerina.types.ComplexSemType; -import io.ballerina.types.Core; -import io.ballerina.types.EnumerableCharString; -import io.ballerina.types.EnumerableString; -import io.ballerina.types.EnumerableType; -import io.ballerina.types.Env; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypes; -import io.ballerina.types.SubtypeData; -import io.ballerina.types.subtypedata.AllOrNothingSubtype; -import io.ballerina.types.subtypedata.CharStringSubtype; -import io.ballerina.types.subtypedata.IntSubtype; -import io.ballerina.types.subtypedata.NonCharStringSubtype; -import io.ballerina.types.subtypedata.Range; -import io.ballerina.types.subtypedata.StringSubtype; import org.ballerinalang.model.TreeBuilder; import org.ballerinalang.model.elements.AttachPoint; import org.ballerinalang.model.elements.Flag; @@ -103,7 +85,6 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BUnionType; import org.wso2.ballerinalang.compiler.semantics.model.types.BXMLSubType; import org.wso2.ballerinalang.compiler.semantics.model.types.BXMLType; -import org.wso2.ballerinalang.compiler.semantics.model.types.SemNamedType; import org.wso2.ballerinalang.compiler.tree.BLangAnnotationAttachment; import org.wso2.ballerinalang.compiler.tree.BLangClassDefinition; import org.wso2.ballerinalang.compiler.tree.BLangFunction; @@ -212,11 +193,11 @@ import java.util.ArrayDeque; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.Deque; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; @@ -231,10 +212,6 @@ import javax.xml.XMLConstants; -import static io.ballerina.types.BasicTypeCode.BT_INT; -import static io.ballerina.types.BasicTypeCode.BT_STRING; -import static io.ballerina.types.Core.getComplexSubtypeData; -import static io.ballerina.types.Core.widenToBasicTypes; import static org.ballerinalang.model.symbols.SymbolOrigin.SOURCE; import static org.ballerinalang.model.symbols.SymbolOrigin.VIRTUAL; import static org.ballerinalang.util.diagnostic.DiagnosticErrorCode.INVALID_NUM_INSERTIONS; @@ -277,7 +254,6 @@ public class TypeChecker extends SimpleBLangNodeAnalyzer key) { @@ -368,7 +343,6 @@ public TypeChecker(CompilerContext context, CompilerContext.Key key this.missingNodesHelper = BLangMissingNodesHelper.getInstance(context); this.unifier = new Unifier(); this.queryTypeChecker = null; - this.typeEnv = types.typeEnv(); } private BType checkExpr(BLangExpression expr, SymbolEnv env, AnalyzerData data) { @@ -556,39 +530,52 @@ private void checkXMLNamespacePrefixes(List filters, Anal } private int getPreferredMemberTypeTag(BFiniteType finiteType) { - BasicTypeBitSet basicTypeBitSet = widenToBasicTypes(finiteType.semType()); - if ((basicTypeBitSet.bitset & PredefinedType.INT.bitset) != 0) { - return TypeTags.INT; - } else if ((basicTypeBitSet.bitset & PredefinedType.FLOAT.bitset) != 0) { - return TypeTags.FLOAT; - } else if ((basicTypeBitSet.bitset & PredefinedType.DECIMAL.bitset) != 0) { - return TypeTags.DECIMAL; - } else { - return TypeTags.NONE; + for (int i = TypeTags.INT; i <= TypeTags.DECIMAL; i++) { + for (BLangExpression valueExpr : finiteType.getValueSpace()) { + int typeTag = Types.getImpliedType(valueExpr.getBType()).tag; + if (typeTag > TypeTags.DECIMAL) { + continue; + } + + if (typeTag == i) { + return i; + } + } } + return TypeTags.NONE; } - private BType getFiniteTypeMatchWithIntType(BLangNumericLiteral literalExpr, BFiniteType finiteType, - AnalyzerData data) { + private BType getFiniteTypeMatchWithIntType(BLangLiteral literalExpr, BFiniteType finiteType, AnalyzerData data) { if (literalAssignableToFiniteType(literalExpr, finiteType, TypeTags.INT)) { setLiteralValueForFiniteType(literalExpr, symTable.intType, data); return symTable.intType; + } else if (literalAssignableToFiniteType(literalExpr, finiteType, TypeTags.BYTE)) { + setLiteralValueForFiniteType(literalExpr, symTable.byteType, data); + return symTable.byteType; + + } else { + for (int tag = TypeTags.SIGNED32_INT; tag <= TypeTags.UNSIGNED8_INT; tag++) { + if (literalAssignableToFiniteType(literalExpr, finiteType, tag)) { + setLiteralValueForFiniteType(literalExpr, symTable.getTypeFromTag(tag), data); + return symTable.getTypeFromTag(tag); + } + } } return symTable.noType; } - private BType getFiniteTypeMatchWithIntLiteral(BLangNumericLiteral literalExpr, BFiniteType finiteType, + private BType getFiniteTypeMatchWithIntLiteral(BLangLiteral literalExpr, BFiniteType finiteType, Object literalValue, BType compatibleType, AnalyzerData data) { BType intLiteralType = getFiniteTypeMatchWithIntType(literalExpr, finiteType, data); if (intLiteralType != symTable.noType) { return intLiteralType; } - + int typeTag = getPreferredMemberTypeTag(finiteType); if (typeTag == TypeTags.NONE) { return symTable.intType; } - + if (literalAssignableToFiniteType(literalExpr, finiteType, typeTag)) { BType type = symTable.getTypeFromTag(typeTag); setLiteralValueForFiniteType(literalExpr, type, data); @@ -609,7 +596,7 @@ private BType getFiniteTypeMatchWithIntLiteral(BLangNumericLiteral literalExpr, return compatibleType; } - private BType silentIntTypeCheck(BLangNumericLiteral literalExpr, Object literalValue, BType expType, + private BType silentIntTypeCheck(BLangLiteral literalExpr, Object literalValue, BType expType, AnalyzerData data) { boolean prevNonErrorLoggingCheck = data.commonAnalyzerData.nonErrorLoggingCheck; data.commonAnalyzerData.nonErrorLoggingCheck = true; @@ -628,32 +615,37 @@ private BType silentIntTypeCheck(BLangNumericLiteral literalExpr, Object literal return exprCompatibleType; } - private BType checkIfOutOfRangeAndReturnType(BFiniteType finiteType, BLangNumericLiteral literalExpr, - Object literalValue, AnalyzerData data) { + private BType silentCompatibleLiteralTypeCheck(BFiniteType finiteType, BLangLiteral literalExpr, + Object literalValue, AnalyzerData data) { BType resIntegerLiteralType = symTable.semanticError; List compatibleTypes = new ArrayList<>(); - Set broadTypes = SemTypeHelper.broadTypes(finiteType, symTable); - for (BType broadType : broadTypes) { - resIntegerLiteralType = silentIntTypeCheck(literalExpr, literalValue, broadType, data); + for (BLangExpression valueExpr : finiteType.getValueSpace()) { + resIntegerLiteralType = silentIntTypeCheck(literalExpr, literalValue, valueExpr.getBType(), data); if (resIntegerLiteralType != symTable.semanticError) { compatibleTypes.add(resIntegerLiteralType); } } - for (int i = TypeTags.INT; i <= TypeTags.DECIMAL; i++) { - for (BType type : compatibleTypes) { + for (BType type: compatibleTypes) { if (Types.getReferredType(type).tag == i) { return type; } } } - - dlog.error(literalExpr.pos, DiagnosticErrorCode.OUT_OF_RANGE, literalExpr.originalValue, - literalExpr.getBType()); return resIntegerLiteralType; } - public BType getIntegerLiteralType(BLangNumericLiteral literalExpr, Object literalValue, BType expType, + private BType checkIfOutOfRangeAndReturnType(BFiniteType finiteType, BLangLiteral literalExpr, Object literalValue, + AnalyzerData data) { + BType compatibleType = silentCompatibleLiteralTypeCheck(finiteType, literalExpr, literalValue, data); + if (compatibleType == symTable.semanticError) { + dlog.error(literalExpr.pos, DiagnosticErrorCode.OUT_OF_RANGE, literalExpr.originalValue, + literalExpr.getBType()); + } + return compatibleType; + } + + public BType getIntegerLiteralType(BLangLiteral literalExpr, Object literalValue, BType expType, AnalyzerData data) { BType expectedType = Types.getImpliedType(expType); if (expectedType.tag == TypeTags.BYTE || TypeTags.isIntegerTypeTag(expectedType.tag)) { @@ -670,8 +662,8 @@ public BType getIntegerLiteralType(BLangNumericLiteral literalExpr, Object liter expectedType); return symTable.semanticError; } - if (literalValue instanceof Double) { - literalExpr.value = literalValue; + if (literalValue instanceof Double doubleValue) { + literalExpr.value = doubleValue.doubleValue(); } else { literalExpr.value = ((Long) literalValue).doubleValue(); } @@ -735,7 +727,7 @@ public BType getIntegerLiteralType(BLangNumericLiteral literalExpr, Object liter return symTable.intType; } - public BType getTypeOfLiteralWithFloatDiscriminator(BLangNumericLiteral literalExpr, Object literalValue, + public BType getTypeOfLiteralWithFloatDiscriminator(BLangLiteral literalExpr, Object literalValue, BType expType, AnalyzerData data) { String numericLiteral = NumericLiteralSupport.stripDiscriminator(String.valueOf(literalValue)); if (!types.validateFloatLiteral(literalExpr.pos, numericLiteral)) { @@ -759,7 +751,7 @@ public BType getTypeOfLiteralWithFloatDiscriminator(BLangNumericLiteral literalE return symTable.floatType; } - public BType getTypeOfLiteralWithDecimalDiscriminator(BLangNumericLiteral literalExpr, Object literalValue, + public BType getTypeOfLiteralWithDecimalDiscriminator(BLangLiteral literalExpr, Object literalValue, BType expType, AnalyzerData data) { literalExpr.value = NumericLiteralSupport.stripDiscriminator(String.valueOf(literalValue)); if (!types.isValidDecimalNumber(literalExpr.pos, literalExpr.value.toString())) { @@ -782,8 +774,8 @@ public BType getTypeOfLiteralWithDecimalDiscriminator(BLangNumericLiteral litera return symTable.decimalType; } - public BType getTypeOfDecimalFloatingPointLiteral(BLangNumericLiteral literalExpr, Object literalValue, - BType expType, AnalyzerData data) { + public BType getTypeOfDecimalFloatingPointLiteral(BLangLiteral literalExpr, Object literalValue, BType expType, + AnalyzerData data) { BType expectedType = Types.getImpliedType(expType); String numericLiteral = String.valueOf(literalValue); if (expectedType != null) { @@ -799,22 +791,25 @@ public BType getTypeOfDecimalFloatingPointLiteral(BLangNumericLiteral literalExp } return symTable.floatType; } else if (expectedType.tag == TypeTags.FINITE) { - BType basicType; - BasicTypeBitSet basicTypeBitSet = widenToBasicTypes(expectedType.semType()); - if ((basicTypeBitSet.bitset & PredefinedType.FLOAT.bitset) != 0) { - basicType = symTable.floatType; - } else if ((basicTypeBitSet.bitset & PredefinedType.DECIMAL.bitset) != 0) { - basicType = symTable.decimalType; - } else { - return literalExpr.getBType(); - } - - if (literalAssignableToFiniteType(literalExpr, (BFiniteType) expectedType, basicType.tag)) { - BType valueType = setLiteralValueAndGetType(literalExpr, basicType, data); - setLiteralValueForFiniteType(literalExpr, valueType, data); - return valueType; + BFiniteType finiteType = (BFiniteType) expectedType; + for (int tag = TypeTags.FLOAT; tag <= TypeTags.DECIMAL; tag++) { + BType literalValueType = null; + for (BLangExpression valueExpr : finiteType.getValueSpace()) { + if (valueExpr.getBType().tag == tag) { + if (types.checkLiteralAssignabilityBasedOnType((BLangLiteral) valueExpr, literalExpr)) { + BType valueType = setLiteralValueAndGetType(literalExpr, + symTable.getTypeFromTag(tag), data); + setLiteralValueForFiniteType(literalExpr, valueType, data); + return valueType; + } + literalValueType = valueExpr.getBType(); + } + } + if (literalValueType != null) { + return literalValueType; + } } - return basicType; + return literalExpr.getBType(); } else if (expectedType.tag == TypeTags.UNION) { BUnionType unionType = (BUnionType) expectedType; for (int tag = TypeTags.FLOAT; tag <= TypeTags.DECIMAL; tag++) { @@ -833,7 +828,7 @@ public BType getTypeOfDecimalFloatingPointLiteral(BLangNumericLiteral literalExp ? symTable.floatType : symTable.semanticError; } - public BType getTypeOfHexFloatingPointLiteral(BLangNumericLiteral literalExpr, Object literalValue, BType expType, + public BType getTypeOfHexFloatingPointLiteral(BLangLiteral literalExpr, Object literalValue, BType expType, AnalyzerData data) { String numericLiteral = String.valueOf(literalValue); if (!types.validateFloatLiteral(literalExpr.pos, numericLiteral)) { @@ -863,19 +858,19 @@ public BType setLiteralValueAndGetType(BLangLiteral literalExpr, BType expType, BType expectedType = Types.getImpliedType(expType); if (literalExpr.getKind() == NodeKind.NUMERIC_LITERAL) { - BLangNumericLiteral numericLiteral = (BLangNumericLiteral) literalExpr; - if (numericLiteral.kind == NodeKind.INTEGER_LITERAL) { - return getIntegerLiteralType(numericLiteral, literalValue, expectedType, data); - } else if (numericLiteral.kind == NodeKind.DECIMAL_FLOATING_POINT_LITERAL) { - if (NumericLiteralSupport.isFloatDiscriminated(numericLiteral.originalValue)) { - return getTypeOfLiteralWithFloatDiscriminator(numericLiteral, literalValue, expectedType, data); - } else if (NumericLiteralSupport.isDecimalDiscriminated(numericLiteral.originalValue)) { - return getTypeOfLiteralWithDecimalDiscriminator(numericLiteral, literalValue, expectedType, data); + NodeKind kind = ((BLangNumericLiteral) literalExpr).kind; + if (kind == NodeKind.INTEGER_LITERAL) { + return getIntegerLiteralType(literalExpr, literalValue, expectedType, data); + } else if (kind == NodeKind.DECIMAL_FLOATING_POINT_LITERAL) { + if (NumericLiteralSupport.isFloatDiscriminated(literalExpr.originalValue)) { + return getTypeOfLiteralWithFloatDiscriminator(literalExpr, literalValue, expectedType, data); + } else if (NumericLiteralSupport.isDecimalDiscriminated(literalExpr.originalValue)) { + return getTypeOfLiteralWithDecimalDiscriminator(literalExpr, literalValue, expectedType, data); } else { - return getTypeOfDecimalFloatingPointLiteral(numericLiteral, literalValue, expectedType, data); + return getTypeOfDecimalFloatingPointLiteral(literalExpr, literalValue, expectedType, data); } } else { - return getTypeOfHexFloatingPointLiteral(numericLiteral, literalValue, expectedType, data); + return getTypeOfHexFloatingPointLiteral(literalExpr, literalValue, expectedType, data); } } @@ -933,8 +928,9 @@ public BType setLiteralValueAndGetType(BLangLiteral literalExpr, BType expType, if (referedType.tag == TypeTags.BYTE_ARRAY) { // check whether this is a byte array byte[] byteArray = types.convertToByteArray((String) literalExpr.value); - literalType = new BArrayType(typeEnv, symTable.byteType, null, byteArray.length, BArrayState.CLOSED); - if (Symbols.isFlagOn(expectedType.getFlags(), Flags.READONLY)) { + literalType = new BArrayType(symTable.byteType, null, byteArray.length, + BArrayState.CLOSED); + if (Symbols.isFlagOn(expectedType.flags, Flags.READONLY)) { literalType = ImmutableTypeCloner.getEffectiveImmutableType(literalExpr.pos, types, literalType, data.env, symTable, anonymousModelHelper, names); } @@ -942,7 +938,7 @@ public BType setLiteralValueAndGetType(BLangLiteral literalExpr, BType expType, if (expectedType.tag == TypeTags.ARRAY) { BArrayType arrayType = (BArrayType) expectedType; if (arrayType.state == BArrayState.INFERRED) { - arrayType.setSize(byteArray.length); + arrayType.size = byteArray.length; arrayType.state = BArrayState.CLOSED; } } @@ -973,8 +969,7 @@ private BType getTypeMatchingFloatOrDecimal(BType finiteType, List member } } if (finiteType.tag == TypeTags.FINITE) { - return checkIfOutOfRangeAndReturnType((BFiniteType) finiteType, (BLangNumericLiteral) literalExpr, - literalExpr.value, data); + return checkIfOutOfRangeAndReturnType((BFiniteType) finiteType, literalExpr, literalExpr.value, data); } return symTable.intType; } @@ -1005,9 +1000,15 @@ private BType getAndSetAssignableUnionMember(BLangLiteral literalExpr, BUnionTyp return symTable.noType; } - private boolean literalAssignableToFiniteType(BLangNumericLiteral literalExpr, BFiniteType finiteType, - int targetTypeTag) { - return types.checkLiteralAssignabilityBasedOnType(literalExpr, finiteType, targetTypeTag); + private boolean literalAssignableToFiniteType(BLangLiteral literalExpr, BFiniteType finiteType, + int targetMemberTypeTag) { + for (BLangExpression valueExpr : finiteType.getValueSpace()) { + if (Types.getImpliedType(valueExpr.getBType()).tag == targetMemberTypeTag && + types.checkLiteralAssignabilityBasedOnType((BLangLiteral) valueExpr, literalExpr)) { + return true; + } + } + return false; } public void setLiteralValueForFiniteType(BLangLiteral literalExpr, BType type, AnalyzerData data) { @@ -1017,9 +1018,6 @@ public void setLiteralValueForFiniteType(BLangLiteral literalExpr, BType type, A } private BType getFiniteTypeWithValuesOfSingleType(BUnionType unionType, BType matchType) { - assert matchType.tag == TypeTags.BYTE || matchType.tag == TypeTags.INT || - matchType.tag == TypeTags.FLOAT || matchType.tag == TypeTags.DECIMAL; - List finiteTypeMembers = types.getAllTypes(unionType, true).stream() .filter(memType -> Types.getImpliedType(memType).tag == TypeTags.FINITE) .map(memFiniteType -> (BFiniteType) memFiniteType) @@ -1029,20 +1027,24 @@ private BType getFiniteTypeWithValuesOfSingleType(BUnionType unionType, BType ma return symTable.semanticError; } - List newValueSpace = new ArrayList<>(); + int tag = Types.getImpliedType(matchType).tag; + Set matchedValueSpace = new LinkedHashSet<>(); + for (BFiniteType finiteType : finiteTypeMembers) { - for (SemNamedType semNamedType : finiteType.valueSpace) { - if (SemTypes.isSubtype(types.semTypeCtx, semNamedType.semType(), matchType.semType())) { - newValueSpace.add(semNamedType); + Set set = new HashSet<>(); + for (BLangExpression expression : finiteType.getValueSpace()) { + if (Types.getImpliedType(expression.getBType()).tag == tag) { + set.add(expression); } } + matchedValueSpace.addAll(set); } - if (newValueSpace.isEmpty()) { + if (matchedValueSpace.isEmpty()) { return symTable.semanticError; } - return new BFiniteType(null, newValueSpace.toArray(SemNamedType[]::new)); + return new BFiniteType(null, matchedValueSpace); } private BType getIntLiteralType(BType expType, Object literalValue, AnalyzerData data) { @@ -1153,7 +1155,7 @@ public void visit(BLangTableConstructorExpr tableConstructorExpr, AnalyzerData d recordLiteral.setBType(inherentMemberType); } } - BTableType tableType = new BTableType(typeEnv, inherentMemberType, null); + BTableType tableType = new BTableType(TypeTags.TABLE, inherentMemberType, null); if (!validateTableConstructorExpr(tableConstructorExpr, tableType, data)) { data.resultType = symTable.semanticError; return; @@ -1198,10 +1200,11 @@ public void visit(BLangTableConstructorExpr tableConstructorExpr, AnalyzerData d return; } - BTableType tableType = new BTableType(typeEnv, inferTableMemberType(memTypes, applicableExpType), null); + BTableType tableType = new BTableType(TypeTags.TABLE, inferTableMemberType(memTypes, applicableExpType), + null); - if (Symbols.isFlagOn(applicableExpType.getFlags(), Flags.READONLY)) { - tableType.addFlags(Flags.READONLY); + if (Symbols.isFlagOn(applicableExpType.flags, Flags.READONLY)) { + tableType.flags |= Flags.READONLY; } if (checkKeySpecifier(tableConstructorExpr, tableType, data)) { @@ -1237,7 +1240,7 @@ public void visit(BLangTableConstructorExpr tableConstructorExpr, AnalyzerData d BType resultType = checkExpr(clonedTableExpr, memType, data); if (resultType != symTable.semanticError && dlog.errorCount() == 0 && - types.isUniqueType(matchingTypes, resultType)) { + isUniqueType(matchingTypes, resultType)) { matchingTypes.add(resultType); } } @@ -1285,7 +1288,7 @@ private BType getInferredTableType(BLangTableConstructorExpr exprToLog, Analyzer } } - return new BTableType(typeEnv, inferTableMemberType(memTypes, exprToLog, data), null); + return new BTableType(TypeTags.TABLE, inferTableMemberType(memTypes, exprToLog, data), null); } private boolean checkKeySpecifier(BLangTableConstructorExpr tableConstructorExpr, BTableType tableType, @@ -1311,12 +1314,12 @@ private BType inferTableMemberType(List memTypes, BType expType) { result.add(memTypes.get(0)); - BUnionType unionType = BUnionType.create(typeEnv, null, result); + BUnionType unionType = BUnionType.create(null, result); for (int i = 1; i < memTypes.size(); i++) { BType source = memTypes.get(i); if (!types.isAssignable(source, unionType)) { result.add(source); - unionType = BUnionType.create(typeEnv, null, result); + unionType = BUnionType.create(null, result); } } @@ -1472,7 +1475,7 @@ private BRecordType createTableConstraintRecordType(Set inferredFields, recordSymbol.scope.define(field.name, field.symbol); } - BRecordType recordType = new BRecordType(typeEnv, recordSymbol); + BRecordType recordType = new BRecordType(recordSymbol); recordType.fields = inferredFields.stream().collect(getFieldCollector()); recordSymbol.type = recordType; @@ -1785,7 +1788,7 @@ private BType createTableKeyConstraint(List fieldNames, BType constraint return memTypes.get(0).type; } - return new BTupleType(typeEnv, memTypes); + return new BTupleType(memTypes); } protected BType checkListConstructorCompatibility(BType bType, BLangListConstructorExpr listConstructor, @@ -1823,7 +1826,7 @@ private BType checkListConstructorCompatibility(BType referredType, BType origin BType memCompatibiltyType = checkListConstructorCompatibility(listCompatibleMemType, listConstructor, data); if (memCompatibiltyType != symTable.semanticError && dlog.errorCount() == 0 && - types.isUniqueType(compatibleTypes, memCompatibiltyType)) { + isUniqueType(compatibleTypes, memCompatibiltyType)) { compatibleTypes.add(memCompatibiltyType); } } @@ -1896,14 +1899,14 @@ private BType checkListConstructorCompatibility(BType referredType, BType origin List members = new ArrayList<>(); inferredTupleDetails.fixedMemberTypes.forEach(memberType -> members.add(new BTupleMember(memberType, - new BVarSymbol(memberType.getFlags(), null, null, memberType, null, null, null)))); - BTupleType tupleType = new BTupleType(typeEnv, members); + new BVarSymbol(memberType.flags, null, null, memberType, null, null, null)))); + BTupleType tupleType = new BTupleType(members); if (!inferredTupleDetails.restMemberTypes.isEmpty()) { tupleType.restType = getRepresentativeBroadType(inferredTupleDetails.restMemberTypes); } listConstructor.typedescType = tupleType; - return new BTypedescType(typeEnv, listConstructor.typedescType, null); + return new BTypedescType(listConstructor.typedescType, null); } if (referredType == symTable.semanticError) { @@ -1948,7 +1951,7 @@ private void updateInferredTupleDetailsFromSpreadMember(Location spreadMemberPos } else if (spreadOpExprType.tag == TypeTags.ARRAY) { BArrayType bArrayType = (BArrayType) spreadOpExprType; if (bArrayType.state == BArrayState.CLOSED) { - for (int i = 0; i < bArrayType.getSize(); i++) { + for (int i = 0; i < bArrayType.size; i++) { BType memberType = bArrayType.eType; inferredTupleDetails.fixedMemberTypes.add(memberType); } @@ -1968,14 +1971,13 @@ private BType getListConstructorCompatibleNonUnionType(BType type, AnalyzerData TypeTags.TUPLE, TypeTags.READONLY, TypeTags.TYPEDESC -> type; - case TypeTags.JSON -> !Symbols.isFlagOn(referredType.getFlags(), Flags.READONLY) ? symTable.arrayJsonType : + case TypeTags.JSON -> !Symbols.isFlagOn(referredType.flags, Flags.READONLY) ? symTable.arrayJsonType : ImmutableTypeCloner.getEffectiveImmutableType(null, types, symTable.arrayJsonType, data.env, symTable, anonymousModelHelper, names); - case TypeTags.ANYDATA -> !Symbols.isFlagOn(referredType.getFlags(), Flags.READONLY) ? - symTable.arrayAnydataType : + case TypeTags.ANYDATA -> !Symbols.isFlagOn(referredType.flags, Flags.READONLY) ? symTable.arrayAnydataType : ImmutableTypeCloner.getEffectiveImmutableType(null, types, symTable.arrayAnydataType, data.env, symTable, anonymousModelHelper, names); - case TypeTags.ANY -> !Symbols.isFlagOn(referredType.getFlags(), Flags.READONLY) ? symTable.arrayAllType : + case TypeTags.ANY -> !Symbols.isFlagOn(referredType.flags, Flags.READONLY) ? symTable.arrayAllType : ImmutableTypeCloner.getEffectiveImmutableType(null, types, symTable.arrayAllType, data.env, symTable, anonymousModelHelper, names); default -> symTable.semanticError; @@ -1997,7 +1999,7 @@ private BType checkArrayType(BLangListConstructorExpr listConstructor, BArrayTyp switch (spreadOpType.tag) { case TypeTags.ARRAY: - int arraySize = ((BArrayType) spreadOpType).getSize(); + int arraySize = ((BArrayType) spreadOpType).size; if (arraySize >= 0) { listExprSize += arraySize; continue; @@ -2023,12 +2025,11 @@ private BType checkArrayType(BLangListConstructorExpr listConstructor, BArrayTyp BType eType = arrayType.eType; if (arrayType.state == BArrayState.INFERRED) { - arrayType.setSize(listExprSize); + arrayType.size = listExprSize; arrayType.state = BArrayState.CLOSED; - } else if (arrayType.state != BArrayState.OPEN && arrayType.getSize() != listExprSize) { - if (arrayType.getSize() < listExprSize) { - dlog.error(listConstructor.pos, DiagnosticErrorCode.MISMATCHING_ARRAY_LITERAL_VALUES, - arrayType.getSize(), + } else if (arrayType.state != BArrayState.OPEN && arrayType.size != listExprSize) { + if (arrayType.size < listExprSize) { + dlog.error(listConstructor.pos, DiagnosticErrorCode.MISMATCHING_ARRAY_LITERAL_VALUES, arrayType.size, listExprSize); return symTable.semanticError; } @@ -2102,7 +2103,7 @@ private BType checkTupleType(BLangListConstructorExpr listConstructor, BTupleTyp switch (spreadOpType.tag) { case TypeTags.ARRAY: - int arraySize = ((BArrayType) spreadOpType).getSize(); + int arraySize = ((BArrayType) spreadOpType).size; if (arraySize >= 0) { listExprSize += arraySize; continue; @@ -2156,7 +2157,7 @@ private BType checkTupleType(BLangListConstructorExpr listConstructor, BTupleTyp BLangExpression spreadOpExpr = ((BLangListConstructorSpreadOpExpr) expr).expr; BType spreadOpType; if (restType != null && restType != symTable.noType && remainNonRestCount == 0) { - BType targetType = new BArrayType(typeEnv, restType); + BType targetType = new BArrayType(restType); BType possibleType = silentTypeCheckExpr(spreadOpExpr, targetType, data); if (possibleType == symTable.semanticError) { spreadOpType = checkExpr(spreadOpExpr, data); @@ -2172,7 +2173,7 @@ private BType checkTupleType(BLangListConstructorExpr listConstructor, BTupleTyp case TypeTags.ARRAY: BArrayType spreadOpArray = (BArrayType) spreadOpReferredType; if (spreadOpArray.state == BArrayState.CLOSED) { - for (int i = 0; i < spreadOpArray.getSize() && nonRestTypeIndex < memberTypeSize; + for (int i = 0; i < spreadOpArray.size && nonRestTypeIndex < memberTypeSize; i++, nonRestTypeIndex++) { if (types.typeIncompatible(spreadOpExpr.pos, spreadOpArray.eType, members.get(nonRestTypeIndex).type)) { @@ -2180,7 +2181,7 @@ private BType checkTupleType(BLangListConstructorExpr listConstructor, BTupleTyp } } - if (remainNonRestCount < spreadOpArray.getSize()) { + if (remainNonRestCount < spreadOpArray.size) { if (types.typeIncompatible(spreadOpExpr.pos, spreadOpArray.eType, restType)) { return symTable.semanticError; } @@ -2356,8 +2357,8 @@ protected BType getInferredTupleType(BLangListConstructorExpr listConstructor, B } List members = new ArrayList<>(); fixedMemberTypes.forEach(memberType -> members.add(new BTupleMember(memberType, - new BVarSymbol(memberType.getFlags(), null, null, memberType, null, null, null)))); - BTupleType tupleType = new BTupleType(typeEnv, members); + new BVarSymbol(memberType.flags, null, null, memberType, null, null, null)))); + BTupleType tupleType = new BTupleType(members); if (!restMemberTypes.isEmpty()) { tupleType.restType = getRepresentativeBroadType(restMemberTypes); } @@ -2366,10 +2367,11 @@ protected BType getInferredTupleType(BLangListConstructorExpr listConstructor, B return tupleType; } - tupleType.addFlags(Flags.READONLY); + tupleType.flags |= Flags.READONLY; return tupleType; } + @Override public void visit(BLangRecordLiteral recordLiteral, AnalyzerData data) { BType expType = data.expType; @@ -2391,7 +2393,7 @@ public BType getEffectiveMappingType(BLangRecordLiteral recordLiteral, BType app AnalyzerData data) { BType refType = Types.getImpliedType(applicableMappingType); if (applicableMappingType == symTable.semanticError || - (refType.tag == TypeTags.RECORD && Symbols.isFlagOn(applicableMappingType.getFlags(), + (refType.tag == TypeTags.RECORD && Symbols.isFlagOn(applicableMappingType.flags, Flags.READONLY))) { return applicableMappingType; } @@ -2470,7 +2472,7 @@ public BType getEffectiveMappingType(BLangRecordLiteral recordLiteral, BType app recordSymbol.scope.define(fieldName, fieldSymbol); } - BRecordType recordType = new BRecordType(typeEnv, recordSymbol, recordSymbol.flags); + BRecordType recordType = new BRecordType(recordSymbol, recordSymbol.flags); if (refType.tag == TypeTags.MAP) { recordType.sealed = false; recordType.restFieldType = ((BMapType) refType).constraint; @@ -2504,7 +2506,7 @@ public BType getEffectiveMappingType(BLangRecordLiteral recordLiteral, BType app recordType.restFieldType = applicableRecordType.restFieldType; if (recordType.sealed && allReadOnlyFields) { - recordType.addFlags(Flags.READONLY); + recordType.flags |= Flags.READONLY; recordType.tsymbol.flags |= Flags.READONLY; } @@ -2566,7 +2568,7 @@ public BType checkMappingConstructorCompatibility(BType bType, BLangRecordLitera mappingConstructor, data); if (memCompatibiltyType != symTable.semanticError && dlog.errorCount() == 0 && - types.isUniqueType(compatibleTypes, memCompatibiltyType)) { + isUniqueType(compatibleTypes, memCompatibiltyType)) { compatibleTypes.add(memCompatibiltyType); } } @@ -2656,15 +2658,15 @@ private BType getMappingConstructorCompatibleNonUnionType(BType type, AnalyzerDa case TypeTags.READONLY: return type; case TypeTags.JSON: - return !Symbols.isFlagOn(type.getFlags(), Flags.READONLY) ? symTable.mapJsonType : + return !Symbols.isFlagOn(type.flags, Flags.READONLY) ? symTable.mapJsonType : ImmutableTypeCloner.getEffectiveImmutableType(null, types, symTable.mapJsonType, data.env, symTable, anonymousModelHelper, names); case TypeTags.ANYDATA: - return !Symbols.isFlagOn(type.getFlags(), Flags.READONLY) ? symTable.mapAnydataType : + return !Symbols.isFlagOn(type.flags, Flags.READONLY) ? symTable.mapAnydataType : ImmutableTypeCloner.getEffectiveImmutableType(null, types, symTable.mapAnydataType, data.env, symTable, anonymousModelHelper, names); case TypeTags.ANY: - return !Symbols.isFlagOn(type.getFlags(), Flags.READONLY) ? symTable.mapAllType : + return !Symbols.isFlagOn(type.flags, Flags.READONLY) ? symTable.mapAllType : ImmutableTypeCloner.getEffectiveImmutableType(null, types, symTable.mapAllType, data.env, symTable, anonymousModelHelper, names); case TypeTags.INTERSECTION: @@ -2896,7 +2898,7 @@ public void visit(BLangWorkerFlushExpr workerFlushExpr, AnalyzerData data) { } } } - BType actualType = BUnionType.create(typeEnv, null, symTable.errorType, symTable.nilType); + BType actualType = BUnionType.create(null, symTable.errorType, symTable.nilType); data.resultType = types.checkType(workerFlushExpr, actualType, data.expType); } @@ -3197,10 +3199,11 @@ public void visit(BLangSimpleVarRef varRefExpr, AnalyzerData data) { if (symbol.kind == SymbolKind.TYPE_DEF) { BTypeDefinitionSymbol typeDefSym = (BTypeDefinitionSymbol) symbol; actualType = Types.getImpliedType(symbol.type).tag == TypeTags.TYPEDESC ? - typeDefSym.referenceType : new BTypedescType(typeEnv, typeDefSym.referenceType, null); + typeDefSym.referenceType + : new BTypedescType(typeDefSym.referenceType, null); } else { actualType = symbol.type.tag == TypeTags.TYPEDESC ? symbol.type - : new BTypedescType(typeEnv, symbol.type, null); + : new BTypedescType(symbol.type, null); } varRefExpr.symbol = symbol; } else if ((symbol.tag & SymTag.CONSTANT) == SymTag.CONSTANT) { @@ -3292,7 +3295,7 @@ public void visit(BLangRecordVarRef varRefExpr, AnalyzerData data) { return; } - BRecordType bRecordType = new BRecordType(typeEnv, recordSymbol); + BRecordType bRecordType = new BRecordType(recordSymbol); bRecordType.fields = fields; recordSymbol.type = bRecordType; varRefExpr.symbol = new BVarSymbol(0, recordSymbol.name, recordSymbol.getOriginalName(), @@ -3416,8 +3419,8 @@ public void visit(BLangErrorVarRef varRefExpr, AnalyzerData data) { BType errorDetailType = errorRefRestFieldType == symTable.anydataOrReadonly ? symTable.errorType.detailType - : new BMapType(typeEnv, TypeTags.MAP, errorRefRestFieldType, null, Flags.PUBLIC); - data.resultType = new BErrorType(typeEnv, symTable.errorType.tsymbol, errorDetailType); + : new BMapType(TypeTags.MAP, errorRefRestFieldType, null, Flags.PUBLIC); + data.resultType = new BErrorType(symTable.errorType.tsymbol, errorDetailType); } private void checkIndirectErrorVarRef(BLangErrorVarRef varRefExpr, AnalyzerData data) { @@ -3447,11 +3450,11 @@ public void visit(BLangTupleVarRef varRefExpr, AnalyzerData data) { for (int i = 0; i < varRefExpr.expressions.size(); i++) { ((BLangVariableReference) varRefExpr.expressions.get(i)).isLValue = true; BType memberType = checkExpr(varRefExpr.expressions.get(i), symTable.noType, data); - BVarSymbol varSymbol = new BVarSymbol(memberType.getFlags(), null, null, memberType, null, + BVarSymbol varSymbol = new BVarSymbol(memberType.flags, null, null, memberType, null, null, null); results.add(new BTupleMember(memberType, varSymbol)); } - BTupleType actualType = new BTupleType(typeEnv, results); + BTupleType actualType = new BTupleType(results); if (varRefExpr.restParam != null) { BLangExpression restExpr = varRefExpr.restParam; ((BLangVariableReference) restExpr).isLValue = true; @@ -3601,7 +3604,7 @@ private void checkFieldBasedAccess(BLangFieldBasedAccess fieldAccessExpr, boolea private boolean isAllReadonlyTypes(BType type) { type = Types.getImpliedType(type); if (type.tag != TypeTags.UNION) { - return Symbols.isFlagOn(type.getFlags(), Flags.READONLY); + return Symbols.isFlagOn(type.flags, Flags.READONLY); } for (BType memberType : ((BUnionType) type).getMemberTypes()) { @@ -3623,7 +3626,7 @@ private boolean isInitializationInInit(BType type, AnalyzerData data) { private boolean isInvalidReadonlyFieldUpdate(BType type, String fieldName) { if (Types.getImpliedType(type).tag == TypeTags.RECORD) { - if (Symbols.isFlagOn(type.getFlags(), Flags.READONLY)) { + if (Symbols.isFlagOn(type.flags, Flags.READONLY)) { return true; } @@ -3657,11 +3660,11 @@ private boolean isXmlAccess(BLangFieldBasedAccess fieldAccessExpr) { return true; } - if (expr.getKind() == NodeKind.FIELD_BASED_ACCESS_EXPR && hasLaxOriginalType((BLangFieldBasedAccess) expr) + if (expr.getKind() == NodeKind.FIELD_BASED_ACCESS_EXPR && hasLaxOriginalType((BLangFieldBasedAccess) expr) && exprType.tag == TypeTags.UNION) { - SemType s = exprType.semType(); - return SemTypes.containsType(types.semTypeCtx, s, PredefinedType.XML_ELEMENT); - } + Set memberTypes = ((BUnionType) exprType).getMemberTypes(); + return memberTypes.contains(symTable.xmlType) || memberTypes.contains(symTable.xmlElementType); + } return false; } @@ -3795,7 +3798,7 @@ public void visit(BLangErrorConstructorExpr errorConstructorExpr, AnalyzerData d if (errorDetailTypes.size() == 1) { detailCandidate = errorDetailTypes.get(0); } else { - detailCandidate = BUnionType.create(typeEnv, null, new LinkedHashSet<>(errorDetailTypes)); + detailCandidate = BUnionType.create(null, new LinkedHashSet<>(errorDetailTypes)); } BLangRecordLiteral recordLiteral = createRecordLiteralForErrorConstructor(errorConstructorExpr); @@ -3998,12 +4001,11 @@ private List expandExpectedErrorTypes(BType candidateType) { List expandedCandidates = new ArrayList<>(); if (referredType.tag == TypeTags.UNION) { for (BType memberType : ((BUnionType) referredType).getMemberTypes()) { - if (memberType.tag != TypeTags.SEMANTIC_ERROR && types.isAssignable(memberType, symTable.errorType)) { + if (types.isAssignable(memberType, symTable.errorType)) { expandedCandidates.add(memberType); } } - } else if (candidateType.tag != TypeTags.SEMANTIC_ERROR && - types.isAssignable(candidateType, symTable.errorType)) { + } else if (types.isAssignable(candidateType, symTable.errorType)) { expandedCandidates.add(candidateType); } @@ -4124,7 +4126,7 @@ private BTupleType getResourcePathType(List pathSegm pathSegmentCount--; } - BTupleType resourcePathType = new BTupleType(typeEnv, new ArrayList<>()); + BTupleType resourcePathType = new BTupleType(new ArrayList<>()); if (pathSegmentCount > 0 && lastPathSegmentSym.kind != SymbolKind.RESOURCE_ROOT_PATH_SEGMENT) { for (BResourcePathSegmentSymbol s : pathSegmentSymbols.subList(0, pathSegmentCount)) { BVarSymbol varSymbol = Symbols.createVarSymbolForTupleMember(s.type); @@ -4151,8 +4153,7 @@ public boolean validateResourceAccessPathSegmentTypes(BLangListConstructorExpr r if (clonedPathSegment.getKind() == NodeKind.LIST_CONSTRUCTOR_SPREAD_OP) { BLangExpression spreadOpExpr = ((BLangListConstructorSpreadOpExpr) clonedPathSegment).expr; BType pathSegmentType = checkExpr(spreadOpExpr, data); - if (!types.isAssignable(pathSegmentType, - new BArrayType(typeEnv, symTable.pathParamAllowedType))) { + if (!types.isAssignable(pathSegmentType, new BArrayType(symTable.pathParamAllowedType))) { dlog.error(clonedPathSegment.getPosition(), DiagnosticErrorCode.UNSUPPORTED_RESOURCE_ACCESS_REST_SEGMENT_TYPE, pathSegmentType); isValidResourceAccessPathSegmentTypes = false; @@ -4266,7 +4267,7 @@ private void checkInLangLib(BLangInvocation iExpr, BType varRefType, AnalyzerDat private boolean checkInvalidImmutableValueUpdate(BLangInvocation iExpr, BType varRefType, BSymbol langLibMethodSymbol, AnalyzerData data) { - if (!Symbols.isFlagOn(varRefType.getFlags(), Flags.READONLY)) { + if (!Symbols.isFlagOn(varRefType.flags, Flags.READONLY)) { return false; } @@ -4293,13 +4294,33 @@ private boolean checkInvalidImmutableValueUpdate(BLangInvocation iExpr, BType va return true; } + private boolean isFixedLengthList(BType type) { + type = Types.getImpliedType(type); + switch(type.tag) { + case TypeTags.ARRAY: + return (((BArrayType) type).state != BArrayState.OPEN); + case TypeTags.TUPLE: + return (((BTupleType) type).restType == null); + case TypeTags.UNION: + BUnionType unionType = (BUnionType) type; + for (BType member : unionType.getMemberTypes()) { + if (!isFixedLengthList(member)) { + return false; + } + } + return true; + default: + return false; + } + } + private void checkIllegalStorageSizeChangeMethodCall(BLangInvocation iExpr, BType varRefType, AnalyzerData data) { String invocationName = iExpr.name.getValue(); if (!LIST_LENGTH_MODIFIER_FUNCTIONS.contains(invocationName)) { return; } - if (types.isFixedLengthList(varRefType)) { + if (isFixedLengthList(varRefType)) { dlog.error(iExpr.name.pos, DiagnosticErrorCode.ILLEGAL_FUNCTION_CHANGE_LIST_SIZE, invocationName, varRefType); data.resultType = symTable.semanticError; @@ -4410,9 +4431,9 @@ public void visit(BLangObjectConstructorExpression objectCtorExpression, Analyze classNode.oceEnvData.typeInit = objectCtorExpression.typeInit; dlog.unmute(); - if (Symbols.isFlagOn(data.expType.getFlags(), Flags.READONLY)) { + if (Symbols.isFlagOn(data.expType.flags, Flags.READONLY)) { handleObjectConstrExprForReadOnly(objectCtorExpression, actualObjectType, typeDefEnv, false, data); - } else if (!typeRefs.isEmpty() && Symbols.isFlagOn(typeRefs.get(0).getBType().getFlags(), + } else if (!typeRefs.isEmpty() && Symbols.isFlagOn(typeRefs.get(0).getBType().flags, Flags.READONLY)) { handleObjectConstrExprForReadOnly(objectCtorExpression, actualObjectType, typeDefEnv, true, data); } else { @@ -4667,7 +4688,7 @@ private BType checkObjectType(BType actualType, BLangTypeInit cIExpr, AnalyzerDa } private BUnionType createNextReturnType(Location pos, BStreamType streamType, AnalyzerData data) { - BRecordType recordType = new BRecordType(typeEnv, null, Flags.ANONYMOUS); + BRecordType recordType = new BRecordType(null, Flags.ANONYMOUS); recordType.restFieldType = symTable.noType; recordType.sealed = true; @@ -4688,7 +4709,7 @@ private BUnionType createNextReturnType(Location pos, BStreamType streamType, An retTypeMembers.add(recordType); retTypeMembers.addAll(types.getAllTypes(streamType.completionType, false)); - BUnionType unionType = BUnionType.create(typeEnv, null); + BUnionType unionType = BUnionType.create(null); unionType.addAll(retTypeMembers); unionType.tsymbol = Symbols.createTypeSymbol(SymTag.UNION_TYPE, 0, Names.EMPTY, data.env.enclPkg.symbol.pkgID, unionType, data.env.scope.owner, pos, VIRTUAL); @@ -4718,7 +4739,7 @@ private BType getObjectConstructorReturnType(BType objType, BType initRetType, A retTypeMembers.addAll(((BUnionType) initRetType).getMemberTypes()); retTypeMembers.remove(symTable.nilType); - BUnionType unionType = BUnionType.create(typeEnv, null, retTypeMembers); + BUnionType unionType = BUnionType.create(null, retTypeMembers); unionType.tsymbol = Symbols.createTypeSymbol(SymTag.UNION_TYPE, 0, Names.EMPTY, data.env.enclPkg.symbol.pkgID, unionType, data.env.scope.owner, symTable.builtinPos, VIRTUAL); @@ -4894,24 +4915,24 @@ private void setResultTypeForWaitForAllExpr(BLangWaitForAllExpr waitForAllExpr, checkTypesForMap(waitForAllExpr, ((BMapType) referredType).constraint, data); LinkedHashSet memberTypesForMap = collectWaitExprTypes(waitForAllExpr.keyValuePairs); if (memberTypesForMap.size() == 1) { - data.resultType = new BMapType(typeEnv, TypeTags.MAP, + data.resultType = new BMapType(TypeTags.MAP, memberTypesForMap.iterator().next(), symTable.mapType.tsymbol); break; } - BUnionType constraintTypeForMap = BUnionType.create(typeEnv, null, memberTypesForMap); - data.resultType = new BMapType(typeEnv, TypeTags.MAP, constraintTypeForMap, symTable.mapType.tsymbol); + BUnionType constraintTypeForMap = BUnionType.create(null, memberTypesForMap); + data.resultType = new BMapType(TypeTags.MAP, constraintTypeForMap, symTable.mapType.tsymbol); break; case TypeTags.NONE: case TypeTags.ANY: checkTypesForMap(waitForAllExpr, expType, data); LinkedHashSet memberTypes = collectWaitExprTypes(waitForAllExpr.keyValuePairs); if (memberTypes.size() == 1) { - data.resultType = new BMapType(typeEnv, TypeTags.MAP, memberTypes.iterator().next(), - symTable.mapType.tsymbol); + data.resultType = + new BMapType(TypeTags.MAP, memberTypes.iterator().next(), symTable.mapType.tsymbol); break; } - BUnionType constraintType = BUnionType.create(typeEnv, null, memberTypes); - data.resultType = new BMapType(typeEnv, TypeTags.MAP, constraintType, symTable.mapType.tsymbol); + BUnionType constraintType = BUnionType.create(null, memberTypes); + data.resultType = new BMapType(TypeTags.MAP, constraintType, symTable.mapType.tsymbol); break; default: dlog.error(waitForAllExpr.pos, DiagnosticErrorCode.INCOMPATIBLE_TYPES, expType, @@ -4923,7 +4944,7 @@ private void setResultTypeForWaitForAllExpr(BLangWaitForAllExpr waitForAllExpr, private BRecordType getWaitForAllExprReturnType(BLangWaitForAllExpr waitExpr, Location pos, AnalyzerData data) { - BRecordType retType = new BRecordType(typeEnv, null, Flags.ANONYMOUS); + BRecordType retType = new BRecordType(null, Flags.ANONYMOUS); List keyVals = waitExpr.keyValuePairs; for (BLangWaitForAllExpr.BLangWaitKeyValue keyVal : keyVals) { @@ -5052,7 +5073,7 @@ private void checkWaitKeyValExpr(BLangWaitForAllExpr.BLangWaitKeyValue keyVal, B } else { expr = keyVal.valueExpr; } - BFutureType futureType = new BFutureType(typeEnv, type, null); + BFutureType futureType = new BFutureType(TypeTags.FUTURE, type, null); checkExpr(expr, futureType, data); setEventualTypeForExpression(expr, type, data); } @@ -5079,14 +5100,14 @@ private void setEventualTypeForExpression(BLangExpression expression, return; } - BUnionType eventualType = BUnionType.create(typeEnv, null, currentType, symTable.errorType); + BUnionType eventualType = BUnionType.create(null, currentType, symTable.errorType); BType referredExpType = Types.getImpliedType(currentExpectedType); if (((referredExpType.tag != TypeTags.NONE) && (referredExpType.tag != TypeTags.NIL)) && !types.isAssignable(eventualType, currentExpectedType)) { dlog.error(expression.pos, DiagnosticErrorCode.INCOMPATIBLE_TYPE_WAIT_FUTURE_EXPR, currentExpectedType, eventualType, expression); } - futureType.setConstraint(eventualType); + futureType.constraint = eventualType; } private void setEventualTypeForWaitExpression(BLangExpression expression, Location pos, AnalyzerData data) { @@ -5099,7 +5120,7 @@ private void setEventualTypeForWaitExpression(BLangExpression expression, Locati } BType currentExpectedType = ((BFutureType) data.expType).constraint; BType referredExpType = Types.getImpliedType(currentExpectedType); - BUnionType eventualType = BUnionType.create(typeEnv, null, data.resultType, symTable.errorType); + BUnionType eventualType = BUnionType.create(null, data.resultType, symTable.errorType); if ((referredExpType.tag == TypeTags.NONE) || (referredExpType.tag == TypeTags.NIL)) { data.resultType = eventualType; return; @@ -5114,7 +5135,7 @@ private void setEventualTypeForWaitExpression(BLangExpression expression, Locati BType referredResultType = Types.getImpliedType(data.resultType); if (referredResultType.tag == TypeTags.FUTURE) { - ((BFutureType) data.resultType).setConstraint(eventualType); + ((BFutureType) data.resultType).constraint = eventualType; } else { data.resultType = eventualType; } @@ -5136,7 +5157,7 @@ private void setEventualTypeForAlternateWaitExpression(BLangExpression expressio BType currentExpectedType = ((BFutureType) data.expType).constraint; BType referredExpType = Types.getImpliedType(currentExpectedType); - BUnionType eventualType = BUnionType.create(typeEnv, null, data.resultType, symTable.errorType); + BUnionType eventualType = BUnionType.create(null, data.resultType, symTable.errorType); if ((referredExpType.tag == TypeTags.NONE) || (referredExpType.tag == TypeTags.NIL)) { data.resultType = eventualType; return; @@ -5151,7 +5172,7 @@ private void setEventualTypeForAlternateWaitExpression(BLangExpression expressio BType referredResultType = Types.getImpliedType(data.resultType); if (referredResultType.tag == TypeTags.FUTURE) { - ((BFutureType) referredResultType).setConstraint(eventualType); + ((BFutureType) referredResultType).constraint = eventualType; } else { data.resultType = eventualType; } @@ -5226,12 +5247,12 @@ private BType getConditionalExprType(BType lhsType, BType rhsType) { if (types.isAssignable(lhsType, rhsType)) { return rhsType; } - return BUnionType.create(typeEnv, null, lhsType, rhsType); + return BUnionType.create(null, lhsType, rhsType); } @Override public void visit(BLangWaitExpr waitExpr, AnalyzerData data) { - data.expType = new BFutureType(typeEnv, data.expType, null); + data.expType = new BFutureType(TypeTags.FUTURE, data.expType, null); checkExpr(waitExpr.getExpression(), data.expType, data); // Handle union types in lhs BType referredResultType = Types.getImpliedType(data.resultType); @@ -5241,7 +5262,7 @@ public void visit(BLangWaitExpr waitExpr, AnalyzerData data) { if (memberTypes.size() == 1) { data.resultType = memberTypes.toArray(new BType[0])[0]; } else { - data.resultType = BUnionType.create(typeEnv, null, memberTypes); + data.resultType = BUnionType.create(null, memberTypes); } } else if (data.resultType != symTable.semanticError) { // Handle other types except for semantic errors @@ -5302,7 +5323,7 @@ public void visit(BLangTrapExpr trapExpr, AnalyzerData data) { resultTypes.add(exprType); } resultTypes.add(symTable.errorType); - actualType = BUnionType.create(typeEnv, null, resultTypes); + actualType = BUnionType.create(null, resultTypes); } data.resultType = types.checkType(trapExpr, actualType, data.expType); @@ -5323,7 +5344,7 @@ public void visit(BLangBinaryExpr binaryExpr, AnalyzerData data) { data.resultType = symTable.semanticError; return; } - data.resultType = BUnionType.create(typeEnv, null, lhsResultType, rhsResultType); + data.resultType = BUnionType.create(null, lhsResultType, rhsResultType); return; } @@ -5365,8 +5386,7 @@ public void visit(BLangBinaryExpr binaryExpr, AnalyzerData data) { BType rightConstituent = getXMLConstituents(rhsType); if (leftConstituent != null && rightConstituent != null) { - actualType = - new BXMLType(BUnionType.create(typeEnv, null, leftConstituent, rightConstituent), null); + actualType = new BXMLType(BUnionType.create(null, leftConstituent, rightConstituent), null); break; } else if (leftConstituent != null || rightConstituent != null) { if (leftConstituent != null && types.isAssignable(rhsType, symTable.stringType)) { @@ -5438,19 +5458,23 @@ private BType getXmlStringBinaryOpResultType(BType opType, BType constituentType BTypeSymbol typeSymbol = Symbols.createTypeSymbol(SymTag.UNION_TYPE, 0, Names.EMPTY, env.enclPkg.symbol.pkgID, null, env.scope.owner, pos, VIRTUAL); - BType type = - new BXMLType(BUnionType.create(typeEnv, typeSymbol, constituentType, symTable.xmlTextType), null); + BType type = new BXMLType(BUnionType.create(typeSymbol, constituentType, symTable.xmlTextType), null); typeSymbol.type = type; return type; } public boolean isOptionalFloatOrDecimal(BType expectedType) { - if (!expectedType.isNullable()) { - return false; - } + if (expectedType.tag == TypeTags.UNION && expectedType.isNullable() && expectedType.tag != TypeTags.ANY) { + Iterator memberTypeIterator = ((BUnionType) expectedType).getMemberTypes().iterator(); + while (memberTypeIterator.hasNext()) { + BType memberType = Types.getImpliedType(memberTypeIterator.next()); + if (memberType.tag == TypeTags.FLOAT || memberType.tag == TypeTags.DECIMAL) { + return true; + } + } - SemType t = Core.diff(expectedType.semType(), PredefinedType.NIL); - return PredefinedType.FLOAT.equals(t) || PredefinedType.DECIMAL.equals(t); + } + return false; } private BType checkAndGetType(BLangExpression expr, SymbolEnv env, BLangBinaryExpr binaryExpr, AnalyzerData data) { @@ -5482,7 +5506,7 @@ public void visit(BLangTransactionalExpr transactionalExpr, AnalyzerData data) { @Override public void visit(BLangCommitExpr commitExpr, AnalyzerData data) { - BType actualType = BUnionType.create(typeEnv, null, symTable.errorType, symTable.nilType); + BType actualType = BUnionType.create(null, symTable.errorType, symTable.nilType); data.resultType = types.checkType(commitExpr, actualType, data.expType); } @@ -5531,14 +5555,14 @@ public void visit(BLangTypedescExpr accessExpr, AnalyzerData data) { int resolveTypeTag = Types.getImpliedType(accessExpr.resolvedType).tag; final BType actualType; if (resolveTypeTag != TypeTags.TYPEDESC && resolveTypeTag != TypeTags.NONE) { - actualType = new BTypedescType(typeEnv, accessExpr.resolvedType, null); + actualType = new BTypedescType(accessExpr.resolvedType, null); } else { actualType = accessExpr.resolvedType; } data.resultType = types.checkType(accessExpr, actualType, data.expType); } - public LinkedHashSet getBasicNumericTypes(Set memberTypes) { + public LinkedHashSet getBasicNumericTypes(LinkedHashSet memberTypes) { LinkedHashSet basicNumericTypes = new LinkedHashSet<>(memberTypes.size()); for (BType value : memberTypes) { @@ -5554,7 +5578,8 @@ public LinkedHashSet getBasicNumericTypes(Set memberTypes) { basicNumericTypes.add(symTable.decimalType); break; } else if (typeTag == TypeTags.FINITE) { - basicNumericTypes.addAll(SemTypeHelper.broadTypes((BFiniteType) referredType, symTable)); + LinkedHashSet typesInValueSpace = getTypesInFiniteValueSpace((BFiniteType) referredType); + basicNumericTypes.addAll(getBasicNumericTypes(typesInValueSpace)); } } return basicNumericTypes; @@ -5565,20 +5590,29 @@ public BType createFiniteTypeForNumericUnaryExpr(BLangUnaryExpr unaryExpr, Analy BTypeSymbol finiteTypeSymbol = Symbols.createTypeSymbol(SymTag.FINITE_TYPE, 0, Names.EMPTY, data.env.enclPkg.symbol.pkgID, null, data.env.scope.owner, unaryExpr.pos, SOURCE); - BFiniteType finiteType = BFiniteType.newSingletonBFiniteType(finiteTypeSymbol, - SemTypeHelper.resolveSingletonType(newNumericLiteral)); + BFiniteType finiteType = new BFiniteType(finiteTypeSymbol); + finiteType.addValue(newNumericLiteral); finiteTypeSymbol.type = finiteType; types.setImplicitCastExpr(unaryExpr, unaryExpr.expr.getBType(), data.expType); return finiteType; } - public BType getNewExpectedTypeForFiniteAndUnion(Set numericTypes, BType newExpectedType) { + public LinkedHashSet getTypesInFiniteValueSpace(BFiniteType referredType) { + Set valueSpace = referredType.getValueSpace(); + LinkedHashSet typesInValueSpace = new LinkedHashSet<>(valueSpace.size()); + for (BLangExpression expr : valueSpace) { + typesInValueSpace.add(expr.getBType()); + } + return typesInValueSpace; + } + + public BType getNewExpectedTypeForFiniteAndUnion(LinkedHashSet numericTypes, BType newExpectedType) { LinkedHashSet basicNumericTypes = getBasicNumericTypes(numericTypes); if (basicNumericTypes.size() == 1) { newExpectedType = basicNumericTypes.iterator().next(); } else if (basicNumericTypes.size() > 1) { - newExpectedType = BUnionType.create(typeEnv, null, basicNumericTypes); + newExpectedType = BUnionType.create(null, basicNumericTypes); } return newExpectedType; } @@ -5591,24 +5625,22 @@ public BType setExpectedTypeForSubtractionOperator(AnalyzerData data) { if (TypeTags.isIntegerTypeTag(referredTypeTag)) { newExpectedType = types.getTypeIntersection(Types.IntersectionContext.compilerInternalIntersectionTestContext(), - BUnionType.create(typeEnv, null, symTable.intType, symTable.floatType, - symTable.decimalType), + BUnionType.create(null, symTable.intType, symTable.floatType, symTable.decimalType), symTable.intType, data.env); } else if (referredTypeTag == TypeTags.FLOAT || referredTypeTag == TypeTags.DECIMAL) { newExpectedType = types.getTypeIntersection(Types.IntersectionContext.compilerInternalIntersectionTestContext(), - BUnionType.create(typeEnv, null, symTable.intType, symTable.floatType, - symTable.decimalType), + BUnionType.create(null, symTable.intType, symTable.floatType, symTable.decimalType), referredType, data.env); } else if (referredTypeTag == TypeTags.FINITE) { - Set typesInValueSpace = SemTypeHelper.broadTypes((BFiniteType) referredType, symTable); + LinkedHashSet typesInValueSpace = getTypesInFiniteValueSpace((BFiniteType) referredType); newExpectedType = getNewExpectedTypeForFiniteAndUnion(typesInValueSpace, newExpectedType); } else if (referredTypeTag == TypeTags.UNION) { newExpectedType = getNewExpectedTypeForFiniteAndUnion(((BUnionType) referredType).getMemberTypes(), newExpectedType); } else if (referredTypeTag == TypeTags.JSON || referredTypeTag == TypeTags.ANYDATA || referredTypeTag == TypeTags.ANY) { - newExpectedType = BUnionType.create(typeEnv, null, symTable.intType, symTable.floatType, + newExpectedType = BUnionType.create(null, symTable.intType, symTable.floatType, symTable.decimalType); } return newExpectedType; @@ -5666,7 +5698,7 @@ public BType getActualTypeForOtherUnaryExpr(BLangUnaryExpr unaryExpr, AnalyzerDa // basic type (int) when checking the expression. LinkedHashSet intTypesInUnion = getIntSubtypesInUnionType((BUnionType) referredType); if (!intTypesInUnion.isEmpty()) { - BType newReferredType = BUnionType.create(typeEnv, null, intTypesInUnion); + BType newReferredType = BUnionType.create(null, intTypesInUnion); BType tempActualType = checkCompatibilityWithConstructedNumericLiteral(unaryExpr, newReferredType, data); if (tempActualType != symTable.semanticError) { @@ -5761,7 +5793,7 @@ public void visit(BLangUnaryExpr unaryExpr, AnalyzerData data) { } else if (OperatorKind.TYPEOF.equals(unaryExpr.operator)) { exprType = checkExpr(unaryExpr.expr, data); if (exprType != symTable.semanticError) { - actualType = new BTypedescType(typeEnv, exprType, null); + actualType = new BTypedescType(exprType, null); } } else { actualType = getActualTypeForOtherUnaryExpr(unaryExpr, data); @@ -5826,7 +5858,7 @@ public void visit(BLangTypeConversionExpr conversionExpr, AnalyzerData data) { } BType exprType = expr.getBType(); - if (types.isTypeCastable(exprType, targetType)) { + if (types.isTypeCastable(expr, exprType, targetType, data.env)) { // We reach this block only if the cast is valid, so we set the target type as the actual type. actualType = targetType; } else if (exprType != symTable.semanticError && exprType != symTable.noType) { @@ -5887,7 +5919,7 @@ public void visit(BLangArrowFunction bLangArrowFunction, AnalyzerData data) { expectedType = invokableType; } } - if (expectedType.tag != TypeTags.INVOKABLE || Symbols.isFlagOn(expectedType.getFlags(), Flags.ANY_FUNCTION)) { + if (expectedType.tag != TypeTags.INVOKABLE || Symbols.isFlagOn(expectedType.flags, Flags.ANY_FUNCTION)) { dlog.error(bLangArrowFunction.pos, DiagnosticErrorCode.ARROW_EXPRESSION_CANNOT_INFER_TYPE_FROM_LHS); data.resultType = symTable.semanticError; @@ -6092,7 +6124,7 @@ public void visit(BLangXMLElementLiteral bLangXMLElementLiteral, AnalyzerData da data.resultType = checkXmlSubTypeLiteralCompatibility(bLangXMLElementLiteral.pos, symTable.xmlElementType, data.expType, data); - if (Symbols.isFlagOn(data.resultType.getFlags(), Flags.READONLY)) { + if (Symbols.isFlagOn(data.resultType.flags, Flags.READONLY)) { markChildrenAsImmutable(bLangXMLElementLiteral, data); } } @@ -6309,8 +6341,8 @@ private boolean evaluateRawTemplateExprs(List exprs, if (listType.tag == TypeTags.ARRAY) { BArrayType arrayType = (BArrayType) listType; - if (arrayType.state == BArrayState.CLOSED && (exprs.size() != arrayType.getSize())) { - dlog.error(pos, code, arrayType.getSize(), exprs.size()); + if (arrayType.state == BArrayState.CLOSED && (exprs.size() != arrayType.size)) { + dlog.error(pos, code, arrayType.size, exprs.size()); return false; } @@ -6348,7 +6380,16 @@ private boolean evaluateRawTemplateExprs(List exprs, } private boolean containsAnyType(BType bType) { - return SemTypeHelper.containsType(types.semTypeCtx, bType, PredefinedType.ANY); + BType type = Types.getImpliedType(bType); + if (type == symTable.anyType) { + return true; + } + + if (type.tag == TypeTags.UNION) { + return ((BUnionType) type).getMemberTypes().contains(symTable.anyType); + } + + return false; } private BType getCompatibleRawTemplateType(BType bType, Location pos) { @@ -6446,7 +6487,7 @@ protected void visitCheckAndCheckPanicExpr(BLangCheckedExpr checkedExpr, Analyze } else { BType exprType = getCandidateType(checkedExpr, data.expType, data); if (exprType == symTable.semanticError) { - checkExprCandidateType = BUnionType.create(typeEnv, null, data.expType, symTable.errorType); + checkExprCandidateType = BUnionType.create(null, data.expType, symTable.errorType); } else { checkExprCandidateType = addDefaultErrorIfNoErrorComponentFound(data.expType); } @@ -6468,8 +6509,7 @@ protected void visitCheckAndCheckPanicExpr(BLangCheckedExpr checkedExpr, Analyze } } - boolean isErrorType = exprType.tag != TypeTags.SEMANTIC_ERROR && - types.isAssignable(exprType, symTable.errorType); + boolean isErrorType = types.isAssignable(exprType, symTable.errorType); BType referredExprType = Types.getImpliedType(exprType); if (referredExprType.tag != TypeTags.UNION && !isErrorType) { if (referredExprType.tag == TypeTags.READONLY) { @@ -6537,7 +6577,7 @@ protected void visitCheckAndCheckPanicExpr(BLangCheckedExpr checkedExpr, Analyze } else if (nonErrorTypes.size() == 1) { actualType = nonErrorTypes.get(0); } else { - actualType = BUnionType.create(typeEnv, null, new LinkedHashSet<>(nonErrorTypes)); + actualType = BUnionType.create(null, new LinkedHashSet<>(nonErrorTypes)); } data.resultType = types.checkType(checkedExpr, actualType, data.expType); @@ -6553,12 +6593,12 @@ private void rewriteWithEnsureTypeFunc(BLangCheckedExpr checkedExpr, BType type, if (rhsType == symTable.semanticError) { rhsType = getCandidateType(checkedExpr, rhsType, data); } - SemType candidateLaxType = getCandidateLaxType(checkedExpr.expr, rhsType); + BType candidateLaxType = getCandidateLaxType(checkedExpr.expr, rhsType); if (!types.isLaxFieldAccessAllowed(candidateLaxType)) { return; } ArrayList argExprs = new ArrayList<>(); - BType typedescType = new BTypedescType(typeEnv, data.expType, null); + BType typedescType = new BTypedescType(data.expType, null); BLangTypedescExpr typedescExpr = new BLangTypedescExpr(); typedescExpr.resolvedType = data.expType; typedescExpr.setBType(typedescType); @@ -6570,12 +6610,11 @@ private void rewriteWithEnsureTypeFunc(BLangCheckedExpr checkedExpr, BType type, checkedExpr.expr = invocation; } - private SemType getCandidateLaxType(BLangNode expr, BType rhsType) { - SemType t = rhsType.semType(); + private BType getCandidateLaxType(BLangNode expr, BType rhsType) { if (expr.getKind() == NodeKind.FIELD_BASED_ACCESS_EXPR) { - return types.getErrorLiftType(t); + return types.getSafeType(rhsType, false, true); } - return t; + return rhsType; } private BType getCandidateType(BLangCheckedExpr checkedExpr, BType checkExprCandidateType, AnalyzerData data) { @@ -6607,7 +6646,7 @@ private BType addDefaultErrorIfNoErrorComponentFound(BType type) { return type; } } - return BUnionType.create(typeEnv, null, type, symTable.errorType); + return BUnionType.create(null, type, symTable.errorType); } @Override @@ -6639,7 +6678,7 @@ public void visit(BLangAnnotAccessExpr annotAccessExpr, AnalyzerData data) { annotAccessExpr.annotationSymbol = (BAnnotationSymbol) symbol; BType annotType = ((BAnnotationSymbol) symbol).attachedType == null ? symTable.trueType : ((BAnnotationSymbol) symbol).attachedType; - actualType = BUnionType.create(typeEnv, null, annotType, symTable.nilType); + actualType = BUnionType.create(null, annotType, symTable.nilType); } data.resultType = this.types.checkType(annotAccessExpr, actualType, data.expType); @@ -6701,7 +6740,7 @@ private BType getEffectiveReadOnlyType(Location pos, BType type, AnalyzerData da return type; } - BUnionType nonReadOnlyUnion = BUnionType.create(typeEnv, null, nonReadOnlyTypes); + BUnionType nonReadOnlyUnion = BUnionType.create(null, nonReadOnlyTypes); nonReadOnlyUnion.add(ImmutableTypeCloner.getImmutableIntersectionType(pos, types, data.expType, data.env, symTable, anonymousModelHelper, names, new HashSet<>())); @@ -7118,7 +7157,7 @@ private void checkActionInvocation(BLangInvocation.BLangActionInvocation aInv, B return; } if (Symbols.isFlagOn(remoteFuncSymbol.flags, Flags.REMOTE) && - Symbols.isFlagOn(expType.getFlags(), Flags.CLIENT) && + Symbols.isFlagOn(expType.flags, Flags.CLIENT) && types.isNeverTypeOrStructureTypeWithARequiredNeverMember ((BType) ((InvokableSymbol) remoteFuncSymbol).getReturnType())) { dlog.error(aInv.pos, DiagnosticErrorCode.INVALID_CLIENT_REMOTE_METHOD_CALL); @@ -7207,7 +7246,7 @@ private BVarSymbol checkForIncRecordParamAllowAdditionalFields(BInvokableSymbol } private BType checkInvocationParam(BLangInvocation iExpr, AnalyzerData data) { - if (Symbols.isFlagOn(iExpr.symbol.type.getFlags(), Flags.ANY_FUNCTION)) { + if (Symbols.isFlagOn(iExpr.symbol.type.flags, Flags.ANY_FUNCTION)) { dlog.error(iExpr.pos, DiagnosticErrorCode.INVALID_FUNCTION_POINTER_INVOCATION_WITH_TYPE); return symTable.semanticError; } @@ -7459,7 +7498,7 @@ private BType checkInvocationArgs(BLangInvocation iExpr, List paramTypes, PackageID pkgID = data.env.enclPkg.symbol.pkgID; List tupleMembers = new ArrayList<>(); BRecordTypeSymbol recordSymbol = createRecordTypeSymbol(pkgID, null, VIRTUAL, data); - mappingTypeRestArg = new BRecordType(typeEnv, recordSymbol); + mappingTypeRestArg = new BRecordType(recordSymbol); LinkedHashMap fields = new LinkedHashMap<>(); BType tupleRestType = null; BVarSymbol fieldSymbol; @@ -7491,7 +7530,7 @@ private BType checkInvocationArgs(BLangInvocation iExpr, List paramTypes, } } - BTupleType tupleType = new BTupleType(typeEnv, tupleMembers); + BTupleType tupleType = new BTupleType(tupleMembers); tupleType.restType = tupleRestType; listTypeRestArg = tupleType; referredListTypeRestArg = tupleType; @@ -7527,7 +7566,7 @@ private BType checkInvocationArgs(BLangInvocation iExpr, List paramTypes, LinkedHashSet restTypes = new LinkedHashSet<>(); restTypes.add(listTypeRestArg); restTypes.add(mappingTypeRestArg); - BType actualType = BUnionType.create(typeEnv, null, restTypes); + BType actualType = BUnionType.create(null, restTypes); checkTypeParamExpr(vararg, actualType, iExpr.langLibInvocation, data); } else { checkTypeParamExpr(vararg, listTypeRestArg, iExpr.langLibInvocation, data); @@ -7569,8 +7608,8 @@ private BType checkInvocationArgs(BLangInvocation iExpr, List paramTypes, long invokableSymbolFlags = invokableSymbol.flags; if (restType != symTable.semanticError && (Symbols.isFlagOn(invokableSymbolFlags, Flags.INTERFACE) || Symbols.isFlagOn(invokableSymbolFlags, Flags.NATIVE)) && - Symbols.isFlagOn(retType.getFlags(), Flags.PARAMETERIZED)) { - retType = unifier.build(typeEnv, retType, data.expType, iExpr, types, symTable, dlog); + Symbols.isFlagOn(retType.flags, Flags.PARAMETERIZED)) { + retType = unifier.build(retType, data.expType, iExpr, types, symTable, dlog); } // check argument types in arr:sort function @@ -7639,7 +7678,7 @@ private void checkArrayLibSortFuncArgs(BLangInvocation iExpr) { BLangExpression arrExpr = argExprs.get(0); BType arrType = arrExpr.getBType(); - boolean isOrderedType = types.isOrderedType(arrType); + boolean isOrderedType = types.isOrderedType(arrType, false); if (keyFunction == null) { if (!isOrderedType) { dlog.error(arrExpr.pos, DiagnosticErrorCode.INVALID_SORT_ARRAY_MEMBER_TYPE, arrType); @@ -7679,7 +7718,7 @@ private void checkArrayLibSortFuncArgs(BLangInvocation iExpr) { returnType = keyLambdaFunction.function.getBType().getReturnType(); } - if (!types.isOrderedType(returnType)) { + if (!types.isOrderedType(returnType, false)) { dlog.error(pos, DiagnosticErrorCode.INVALID_SORT_FUNC_RETURN_TYPE, returnType); } } @@ -7713,7 +7752,7 @@ private BVarSymbol checkParameterNameForDefaultArgument(BLangIdentifier argName, private BFutureType generateFutureType(BInvokableSymbol invocableSymbol, BType retType) { boolean isWorkerStart = Symbols.isFlagOn(invocableSymbol.flags, Flags.WORKER); - return new BFutureType(typeEnv, retType, null, isWorkerStart); + return new BFutureType(TypeTags.FUTURE, retType, null, isWorkerStart); } protected void checkTypeParamExpr(BLangExpression arg, BType expectedType, AnalyzerData data) { @@ -8001,7 +8040,7 @@ private TypeSymbolPair checkRecordLiteralKeyExpr(BLangExpression keyExpr, boolea fieldTypes.add(recordType.restFieldType); } - return new TypeSymbolPair(null, BUnionType.create(typeEnv, null, fieldTypes)); + return new TypeSymbolPair(null, BUnionType.create(null, fieldTypes)); } else if (keyExpr.getKind() == NodeKind.SIMPLE_VARIABLE_REF) { BLangSimpleVarRef varRef = (BLangSimpleVarRef) keyExpr; fieldName = names.fromIdNode(varRef.variableName); @@ -8047,7 +8086,7 @@ private BType getAllFieldType(BRecordType recordType) { possibleTypes.add(restFieldType); } - return BUnionType.create(typeEnv, null, possibleTypes); + return BUnionType.create(null, possibleTypes); } private boolean checkValidJsonOrMapLiteralKeyExpr(BLangExpression keyExpr, boolean computedKey, AnalyzerData data) { @@ -8134,12 +8173,12 @@ private BType checkObjectFieldAccess(BLangFieldBasedAccess bLangFieldBasedAccess return symTable.semanticError; } - if (Symbols.isFlagOn(fieldSymbol.type.getFlags(), Flags.ISOLATED) && - !Symbols.isFlagOn(objectType.getFlags(), Flags.ISOLATED)) { - fieldSymbol = ASTBuilderUtil.duplicateInvokableSymbol(typeEnv, (BInvokableSymbol) fieldSymbol); + if (Symbols.isFlagOn(fieldSymbol.type.flags, Flags.ISOLATED) && + !Symbols.isFlagOn(objectType.flags, Flags.ISOLATED)) { + fieldSymbol = ASTBuilderUtil.duplicateInvokableSymbol((BInvokableSymbol) fieldSymbol); fieldSymbol.flags &= ~Flags.ISOLATED; - fieldSymbol.type.setFlags(fieldSymbol.type.getFlags() & ~Flags.ISOLATED); + fieldSymbol.type.flags &= ~Flags.ISOLATED; } // Setting the field symbol. This is used during the code generation phase @@ -8193,7 +8232,7 @@ private void checkStringTemplateExprs(List exprs, Ana if (!types.isNonNilSimpleBasicTypeOrString(type)) { dlog.error(expr.pos, DiagnosticErrorCode.INCOMPATIBLE_TYPES, - BUnionType.create(typeEnv, null, symTable.intType, symTable.floatType, + BUnionType.create(null, symTable.intType, symTable.floatType, symTable.decimalType, symTable.stringType, symTable.booleanType), type); } @@ -8250,7 +8289,7 @@ private List concatSimilarKindXMLNodes(List ex !TypeTags.isIntegerTypeTag(referredType.tag) && !TypeTags.isStringTypeTag(referredType.tag)) { if (referredType != symTable.semanticError && !TypeTags.isXMLTypeTag(referredType.tag)) { dlog.error(expr.pos, DiagnosticErrorCode.INCOMPATIBLE_TYPES, - BUnionType.create(typeEnv, null, symTable.intType, symTable.floatType, + BUnionType.create(null, symTable.intType, symTable.floatType, symTable.decimalType, symTable.stringType, symTable.booleanType, symTable.xmlType), type); } @@ -8327,7 +8366,7 @@ private BType checkObjectFieldAccessExpr(BLangFieldBasedAccess fieldAccessExpr, return fieldTypeMembers.iterator().next(); } - return BUnionType.create(typeEnv, null, fieldTypeMembers); + return BUnionType.create(null, fieldTypeMembers); } private BType checkRecordFieldAccessExpr(BLangFieldBasedAccess fieldAccessExpr, BType type, Name fieldName, @@ -8374,7 +8413,7 @@ private BType checkRecordFieldAccessExpr(BLangFieldBasedAccess fieldAccessExpr, return fieldTypeMembers.iterator().next(); } - return BUnionType.create(typeEnv, null, fieldTypeMembers); + return BUnionType.create(null, fieldTypeMembers); } private boolean isFieldOptionalInRecords(BUnionType unionType, Name fieldName, @@ -8424,7 +8463,7 @@ private BType checkRecordFieldAccessLhsExpr(BLangFieldBasedAccess fieldAccessExp return fieldTypeMembers.iterator().next(); } - return BUnionType.create(typeEnv, null, fieldTypeMembers); + return BUnionType.create(null, fieldTypeMembers); } private BType checkOptionalRecordFieldAccessExpr(BLangFieldBasedAccess fieldAccessExpr, BType varRefType, @@ -8471,7 +8510,7 @@ private BType checkOptionalRecordFieldAccessExpr(BLangFieldBasedAccess fieldAcce if (fieldTypeMembers.size() == 1) { fieldType = fieldTypeMembers.iterator().next(); } else { - fieldType = BUnionType.create(typeEnv, null, fieldTypeMembers); + fieldType = BUnionType.create(null, fieldTypeMembers); } return nonMatchedRecordExists ? types.addNilForNillableAccessType(fieldType) : fieldType; @@ -8595,7 +8634,7 @@ private BType checkFieldAccessExpr(BLangFieldBasedAccess fieldAccessExpr, BType resolveXMLNamespace((BLangFieldBasedAccess.BLangPrefixedFieldBasedAccess) fieldAccessExpr, data); } BType laxFieldAccessType = getLaxFieldAccessType(varRefType); - actualType = BUnionType.create(typeEnv, null, laxFieldAccessType, symTable.errorType); + actualType = BUnionType.create(null, laxFieldAccessType, symTable.errorType); fieldAccessExpr.originalType = laxFieldAccessType; } else if (fieldAccessExpr.expr.getKind() == NodeKind.FIELD_BASED_ACCESS_EXPR && hasLaxOriginalType(((BLangFieldBasedAccess) fieldAccessExpr.expr))) { @@ -8604,7 +8643,7 @@ private BType checkFieldAccessExpr(BLangFieldBasedAccess fieldAccessExpr, BType if (fieldAccessExpr.fieldKind == FieldKind.WITH_NS) { resolveXMLNamespace((BLangFieldBasedAccess.BLangPrefixedFieldBasedAccess) fieldAccessExpr, data); } - actualType = BUnionType.create(typeEnv, null, laxFieldAccessType, symTable.errorType); + actualType = BUnionType.create(null, laxFieldAccessType, symTable.errorType); fieldAccessExpr.errorSafeNavigation = true; fieldAccessExpr.originalType = laxFieldAccessType; } else if (TypeTags.isXMLTypeTag(referredVarRefType.tag)) { @@ -8660,13 +8699,12 @@ private BType getLaxFieldAccessType(BType exprType) { return ((BMapType) exprType).constraint; case TypeTags.UNION: BUnionType unionType = (BUnionType) exprType; - if (types.isSameType(Core.createJson(types.semTypeCtx), unionType.semType())) { + if (types.isSameType(symTable.jsonType, unionType)) { return symTable.jsonType; } LinkedHashSet memberTypes = new LinkedHashSet<>(); unionType.getMemberTypes().forEach(bType -> memberTypes.add(getLaxFieldAccessType(bType))); - return memberTypes.size() == 1 ? memberTypes.iterator().next() : - BUnionType.create(typeEnv, null, memberTypes); + return memberTypes.size() == 1 ? memberTypes.iterator().next() : BUnionType.create(null, memberTypes); } return symTable.semanticError; } @@ -8691,7 +8729,7 @@ private BType checkOptionalFieldAccessExpr(BLangFieldBasedAccess fieldAccessExpr } referredType = nilRemovedSet.size() == 1 ? nilRemovedSet.iterator().next() : - BUnionType.create(typeEnv, null, nilRemovedSet); + BUnionType.create(null, nilRemovedSet); } } @@ -8708,8 +8746,7 @@ private BType checkOptionalFieldAccessExpr(BLangFieldBasedAccess fieldAccessExpr } else if (types.isLaxFieldAccessAllowed(referredType)) { BType laxFieldAccessType = getLaxFieldAccessType(referredType); actualType = accessCouldResultInError(referredType) ? - BUnionType.create(typeEnv, null, laxFieldAccessType, symTable.errorType) : - laxFieldAccessType; + BUnionType.create(null, laxFieldAccessType, symTable.errorType) : laxFieldAccessType; if (fieldAccessExpr.fieldKind == FieldKind.WITH_NS) { resolveXMLNamespace((BLangFieldBasedAccess.BLangPrefixedFieldBasedAccess) fieldAccessExpr, data); } @@ -8721,8 +8758,7 @@ private BType checkOptionalFieldAccessExpr(BLangFieldBasedAccess fieldAccessExpr BType laxFieldAccessType = getLaxFieldAccessType(((BLangFieldBasedAccess) fieldAccessExpr.expr).originalType); actualType = accessCouldResultInError(referredType) ? - BUnionType.create(typeEnv, null, laxFieldAccessType, symTable.errorType) : - laxFieldAccessType; + BUnionType.create(null, laxFieldAccessType, symTable.errorType) : laxFieldAccessType; if (fieldAccessExpr.fieldKind == FieldKind.WITH_NS) { resolveXMLNamespace((BLangFieldBasedAccess.BLangPrefixedFieldBasedAccess) fieldAccessExpr, data); } @@ -8736,16 +8772,31 @@ private BType checkOptionalFieldAccessExpr(BLangFieldBasedAccess fieldAccessExpr } if (nillableExprType && actualType != symTable.semanticError && !actualType.isNullable()) { - actualType = BUnionType.create(typeEnv, null, actualType, symTable.nilType); + actualType = BUnionType.create(null, actualType, symTable.nilType); } return actualType; } private boolean accessCouldResultInError(BType bType) { - SemType s = bType.semType(); - return SemTypes.containsBasicType(s, PredefinedType.XML) || - SemTypes.containsType(types.semTypeCtx, s, Core.createJson(types.semTypeCtx)); + BType type = Types.getImpliedType(bType); + if (type.tag == TypeTags.JSON) { + return true; + } + + if (type.tag == TypeTags.MAP) { + return false; + } + + if (types.isAssignable(bType, symTable.xmlType)) { + return true; + } + + if (type.tag == TypeTags.UNION) { + return ((BUnionType) type).getMemberTypes().stream().anyMatch(this::accessCouldResultInError); + } else { + return false; + } } private BType checkIndexAccessExpr(BLangIndexBasedAccess indexBasedAccessExpr, AnalyzerData data) { @@ -8768,9 +8819,9 @@ private BType checkIndexAccessExpr(BLangIndexBasedAccess indexBasedAccessExpr, A if (nillableExprType) { varRefType = nilRemovedSet.size() == 1 ? nilRemovedSet.iterator().next() : - BUnionType.create(typeEnv, null, nilRemovedSet); + BUnionType.create(null, nilRemovedSet); - if (!types.isSubTypeOfMapping(varRefType.semType())) { + if (!types.isSubTypeOfMapping(varRefType)) { // Member access is allowed on optional types only with mappings. dlog.error(indexBasedAccessExpr.pos, DiagnosticErrorCode.OPERATION_DOES_NOT_SUPPORT_MEMBER_ACCESS, @@ -8792,10 +8843,7 @@ private BType checkIndexAccessExpr(BLangIndexBasedAccess indexBasedAccessExpr, A BLangExpression indexExpr = indexBasedAccessExpr.indexExpr; BType actualType = symTable.semanticError; - if (varRefType == symTable.semanticError) { - indexBasedAccessExpr.indexExpr.setBType(symTable.semanticError); - return symTable.semanticError; - } else if (types.isSubTypeOfMapping(varRefType.semType())) { + if (types.isSubTypeOfMapping(varRefType)) { checkExpr(indexExpr, symTable.stringType, data); if (indexExpr.getBType() == symTable.semanticError) { @@ -8903,6 +8951,9 @@ private BType checkIndexAccessExpr(BLangIndexBasedAccess indexBasedAccessExpr, A actualType = types.addNilForNillableAccessType(constraint); indexBasedAccessExpr.originalType = indexBasedAccessExpr.leafNode || !nillableExprType ? actualType : types.getTypeWithoutNil(actualType); + } else if (varRefType == symTable.semanticError) { + indexBasedAccessExpr.indexExpr.setBType(symTable.semanticError); + return symTable.semanticError; } else { indexBasedAccessExpr.indexExpr.setBType(symTable.semanticError); dlog.error(indexBasedAccessExpr.pos, DiagnosticErrorCode.OPERATION_DOES_NOT_SUPPORT_MEMBER_ACCESS, @@ -8911,7 +8962,7 @@ private BType checkIndexAccessExpr(BLangIndexBasedAccess indexBasedAccessExpr, A } if (nillableExprType && !actualType.isNullable()) { - actualType = BUnionType.create(typeEnv, null, actualType, symTable.nilType); + actualType = BUnionType.create(null, actualType, symTable.nilType); } return actualType; @@ -8932,7 +8983,7 @@ private BType getXmlMemberAccessType(BType varRefType) { effectiveMemberTypes.add(getXMLConstituents(memberType)); } xmlMemberAccessType = effectiveMemberTypes.size() == 1 ? effectiveMemberTypes.iterator().next() : - BUnionType.create(typeEnv, null, effectiveMemberTypes); + BUnionType.create(null, effectiveMemberTypes); } else { xmlMemberAccessType = getXMLConstituents(varRefType); } @@ -8942,7 +8993,7 @@ private BType getXmlMemberAccessType(BType varRefType) { } else if (types.isAssignable(symTable.xmlNeverType, xmlMemberAccessType)) { return xmlMemberAccessType; } - return BUnionType.create(typeEnv, null, xmlMemberAccessType, symTable.xmlNeverType); + return BUnionType.create(null, xmlMemberAccessType, symTable.xmlNeverType); } private Long getConstIndex(BLangExpression indexExpr) { @@ -8984,23 +9035,22 @@ private BType checkArrayIndexBasedAccess(BLangIndexBasedAccess indexBasedAccess, return arrayType.eType; } Long indexVal = getConstIndex(indexExpr); - return indexVal >= arrayType.getSize() || indexVal < 0 ? symTable.semanticError : arrayType.eType; + return indexVal >= arrayType.size || indexVal < 0 ? symTable.semanticError : arrayType.eType; } switch (tag) { case TypeTags.FINITE: - SemType t = indexExprType.semType(); - long maxIndexValue; - if (arrayType.state == BArrayState.OPEN) { - maxIndexValue = Long.MAX_VALUE; - } else { - maxIndexValue = arrayType.getSize() - 1; + BFiniteType finiteIndexExpr = (BFiniteType) indexExprType; + boolean validIndexExists = false; + for (BLangExpression finiteMember : finiteIndexExpr.getValueSpace()) { + int indexValue = ((Long) ((BLangLiteral) finiteMember).value).intValue(); + if (indexValue >= 0 && + (arrayType.state == BArrayState.OPEN || indexValue < arrayType.size)) { + validIndexExists = true; + break; + } } - - SemType allowedInts = PredefinedType.basicSubtype(BasicTypeCode.BT_INT, - IntSubtype.createSingleRangeSubtype(0, maxIndexValue)); - - if (Core.isEmpty(types.semTypeCtx, SemTypes.intersect(t, allowedInts))) { + if (!validIndexExists) { return symTable.semanticError; } actualType = arrayType.eType; @@ -9009,7 +9059,7 @@ private BType checkArrayIndexBasedAccess(BLangIndexBasedAccess indexBasedAccess, // address the case where we have a union of types List finiteTypes = new ArrayList<>(); for (BType memType : ((BUnionType) indexExprType).getMemberTypes()) { - memType = Types.getReferredType(memType); + memType = Types.getImpliedType(memType); if (memType.tag == TypeTags.FINITE) { finiteTypes.add((BFiniteType) memType); } else { @@ -9020,12 +9070,7 @@ private BType checkArrayIndexBasedAccess(BLangIndexBasedAccess indexBasedAccess, } } if (!finiteTypes.isEmpty()) { - List newValueSpace = new ArrayList<>(); - for (BFiniteType ft : finiteTypes) { - newValueSpace.addAll(Arrays.asList(ft.valueSpace)); - } - - BFiniteType finiteType = new BFiniteType(null, newValueSpace.toArray(SemNamedType[]::new)); + BFiniteType finiteType = createFiniteTypeFromFiniteTypeList(finiteTypes); BType possibleType = checkArrayIndexBasedAccess(indexBasedAccess, finiteType, arrayType); if (possibleType == symTable.semanticError) { return symTable.semanticError; @@ -9065,7 +9110,7 @@ private BType checkListIndexBasedAccess(BLangIndexBasedAccess accessExpr, BType if (fieldTypeMembers.size() == 1) { return fieldTypeMembers.iterator().next(); } - return BUnionType.create(typeEnv, null, fieldTypeMembers); + return BUnionType.create(null, fieldTypeMembers); } private BType checkTupleIndexBasedAccess(BLangIndexBasedAccess accessExpr, BTupleType tuple, BType currentType) { @@ -9080,36 +9125,27 @@ private BType checkTupleIndexBasedAccess(BLangIndexBasedAccess accessExpr, BTupl } LinkedHashSet tupleTypes = collectTupleFieldTypes(tuple, new LinkedHashSet<>()); - return tupleTypes.size() == 1 ? tupleTypes.iterator().next() : - BUnionType.create(typeEnv, null, tupleTypes); + return tupleTypes.size() == 1 ? tupleTypes.iterator().next() : BUnionType.create(null, tupleTypes); } switch (tag) { case TypeTags.FINITE: + BFiniteType finiteIndexExpr = (BFiniteType) currentType; LinkedHashSet possibleTypes = new LinkedHashSet<>(); - SemType t = currentType.semType(); - - Optional properSubtypeData = getProperSubtypeData(t, BT_INT); - if (properSubtypeData.isEmpty()) { - return symTable.semanticError; - } - - IntSubtype intSubtype = (IntSubtype) properSubtypeData.get(); - for (Range range : intSubtype.ranges) { - for (long indexVal = range.min; indexVal <= range.max; indexVal++) { - BType fieldType = checkTupleFieldType(tuple, (int) indexVal); - if (fieldType.tag != TypeTags.SEMANTIC_ERROR) { - possibleTypes.add(fieldType); - } + for (BLangExpression finiteMember : finiteIndexExpr.getValueSpace()) { + int indexValue = ((Long) ((BLangLiteral) finiteMember).value).intValue(); + BType fieldType = checkTupleFieldType(tuple, indexValue); + if (fieldType.tag != TypeTags.SEMANTIC_ERROR) { + possibleTypes.add(fieldType); } } - if (possibleTypes.isEmpty()) { return symTable.semanticError; } actualType = possibleTypes.size() == 1 ? possibleTypes.iterator().next() : - BUnionType.create(typeEnv, null, possibleTypes); + BUnionType.create(null, possibleTypes); break; + case TypeTags.UNION: LinkedHashSet possibleTypesByMember = new LinkedHashSet<>(); List finiteTypes = new ArrayList<>(); @@ -9126,14 +9162,8 @@ private BType checkTupleIndexBasedAccess(BLangIndexBasedAccess accessExpr, BTupl } } }); - if (!finiteTypes.isEmpty()) { - List newValueSpace = new ArrayList<>(); - for (BFiniteType ft : finiteTypes) { - newValueSpace.addAll(Arrays.asList(ft.valueSpace)); - } - - BFiniteType finiteType = new BFiniteType(null, newValueSpace.toArray(SemNamedType[]::new)); + BFiniteType finiteType = createFiniteTypeFromFiniteTypeList(finiteTypes); BType possibleType = checkTupleIndexBasedAccess(accessExpr, tuple, finiteType); if (possibleType.tag == TypeTags.UNION) { possibleTypesByMember.addAll(((BUnionType) possibleType).getMemberTypes()); @@ -9141,12 +9171,11 @@ private BType checkTupleIndexBasedAccess(BLangIndexBasedAccess accessExpr, BTupl possibleTypesByMember.add(possibleType); } } - if (possibleTypesByMember.contains(symTable.semanticError)) { return symTable.semanticError; } actualType = possibleTypesByMember.size() == 1 ? possibleTypesByMember.iterator().next() : - BUnionType.create(typeEnv, null, possibleTypesByMember); + BUnionType.create(null, possibleTypesByMember); } return actualType; } @@ -9204,7 +9233,7 @@ private BType checkMappingIndexBasedAccess(BLangIndexBasedAccess accessExpr, BTy if (fieldTypeMembers.size() == 1) { fieldType = fieldTypeMembers.iterator().next(); } else { - fieldType = BUnionType.create(typeEnv, null, fieldTypeMembers); + fieldType = BUnionType.create(null, fieldTypeMembers); } return nonMatchedRecordExists ? types.addNilForNillableAccessType(fieldType) : fieldType; @@ -9256,19 +9285,13 @@ private BType checkRecordIndexBasedAccess(BLangIndexBasedAccess accessExpr, BRec } actualType = fieldTypes.size() == 1 ? fieldTypes.iterator().next() : - BUnionType.create(typeEnv, null, fieldTypes); + BUnionType.create(null, fieldTypes); break; case TypeTags.FINITE: + BFiniteType finiteIndexExpr = (BFiniteType) currentType; LinkedHashSet possibleTypes = new LinkedHashSet<>(); - SemType t = currentType.semType(); - - Optional properSubtypeData = getProperSubtypeData(t, BT_STRING); - if (properSubtypeData.isEmpty()) { - return symTable.semanticError; - } - - Set values = getStringValueSpace((StringSubtype) properSubtypeData.get()); - for (String fieldName : values) { + for (BLangExpression finiteMember : finiteIndexExpr.getValueSpace()) { + String fieldName = (String) ((BLangLiteral) finiteMember).value; BType fieldType = checkRecordRequiredFieldAccess(accessExpr, Names.fromString(fieldName), record, data); if (fieldType == symTable.semanticError) { @@ -9299,7 +9322,7 @@ private BType checkRecordIndexBasedAccess(BLangIndexBasedAccess accessExpr, BRec } actualType = possibleTypes.size() == 1 ? possibleTypes.iterator().next() : - BUnionType.create(typeEnv, null, possibleTypes); + BUnionType.create(null, possibleTypes); break; case TypeTags.UNION: LinkedHashSet possibleTypesByMember = new LinkedHashSet<>(); @@ -9316,14 +9339,8 @@ private BType checkRecordIndexBasedAccess(BLangIndexBasedAccess accessExpr, BRec } } }); - if (!finiteTypes.isEmpty()) { - List newValueSpace = new ArrayList<>(); - for (BFiniteType ft : finiteTypes) { - newValueSpace.addAll(Arrays.asList(ft.valueSpace)); - } - - BFiniteType finiteType = new BFiniteType(null, newValueSpace.toArray(SemNamedType[]::new)); + BFiniteType finiteType = createFiniteTypeFromFiniteTypeList(finiteTypes); BType possibleType = checkRecordIndexBasedAccess(accessExpr, record, finiteType, data); if (possibleType.tag == TypeTags.UNION) { possibleTypesByMember.addAll(((BUnionType) possibleType).getMemberTypes()); @@ -9331,53 +9348,15 @@ private BType checkRecordIndexBasedAccess(BLangIndexBasedAccess accessExpr, BRec possibleTypesByMember.add(possibleType); } } - if (possibleTypesByMember.contains(symTable.semanticError)) { return symTable.semanticError; } actualType = possibleTypesByMember.size() == 1 ? possibleTypesByMember.iterator().next() : - BUnionType.create(typeEnv, null, possibleTypesByMember); + BUnionType.create(null, possibleTypesByMember); } return actualType; } - private Optional getProperSubtypeData(SemType t, BasicTypeCode u) { - if (t instanceof BasicTypeBitSet) { - return Optional.empty(); - } - SubtypeData sd = getComplexSubtypeData((ComplexSemType) t, u); - if (sd instanceof AllOrNothingSubtype) { - return Optional.empty(); - } - return Optional.of(sd); - } - - /** - * Returns the set of values belongs to a given StringSubtype. - *

- * Note: We assume StringSubtype does not contain any diff. i.e. contains only a finite set of values - * - * @param stringSubtype string subtype data - * @return set of string values - */ - private static Set getStringValueSpace(StringSubtype stringSubtype) { - Set values = new HashSet<>(); - CharStringSubtype charStringSubtype = stringSubtype.getChar(); - assert charStringSubtype.allowed; - for (EnumerableType enumerableType : charStringSubtype.values()) { - EnumerableCharString s = (EnumerableCharString) enumerableType; - values.add(s.value); - } - - NonCharStringSubtype nonCharStringSubtype = stringSubtype.getNonChar(); - assert nonCharStringSubtype.allowed; - for (EnumerableType enumerableType : nonCharStringSubtype.values()) { - EnumerableString s = (EnumerableString) enumerableType; - values.add(s.value); - } - return values; - } - private boolean isConstExpr(BLangExpression expression) { switch (expression.getKind()) { case LITERAL: @@ -9437,7 +9416,7 @@ private BType getRepresentativeBroadType(List inferredTypeList) { return inferredTypeList.get(0); } - return BUnionType.create(typeEnv, null, inferredTypeList.toArray(new BType[0])); + return BUnionType.create(null, inferredTypeList.toArray(new BType[0])); } public BType defineInferredRecordType(BLangRecordLiteral recordLiteral, BType expType, AnalyzerData data) { @@ -9457,7 +9436,7 @@ public BType defineInferredRecordType(BLangRecordLiteral recordLiteral, BType ex if (key.computedKey) { checkExpr(keyExpr, symTable.stringType, data); BType exprType = checkExpr(expression, expType, data); - if (types.isUniqueType(restFieldTypes, exprType)) { + if (isUniqueType(restFieldTypes, exprType)) { restFieldTypes.add(exprType); } } else { @@ -9474,7 +9453,7 @@ public BType defineInferredRecordType(BLangRecordLiteral recordLiteral, BType ex if (type.tag == TypeTags.MAP) { BType constraintType = ((BMapType) type).constraint; - if (types.isUniqueType(restFieldTypes, constraintType)) { + if (isUniqueType(restFieldTypes, constraintType)) { restFieldTypes.add(constraintType); } } @@ -9491,7 +9470,7 @@ public BType defineInferredRecordType(BLangRecordLiteral recordLiteral, BType ex if (!recordType.sealed) { BType restFieldType = recordType.restFieldType; - if (types.isUniqueType(restFieldTypes, restFieldType)) { + if (isUniqueType(restFieldTypes, restFieldType)) { restFieldTypes.add(restFieldType); } } @@ -9517,8 +9496,7 @@ public BType defineInferredRecordType(BLangRecordLiteral recordLiteral, BType ex String key = entry.getKey(); Name fieldName = Names.fromString(key); - BType type = types.size() == 1 ? types.get(0) : - BUnionType.create(typeEnv, null, types.toArray(new BType[0])); + BType type = types.size() == 1 ? types.get(0) : BUnionType.create(null, types.toArray(new BType[0])); Set flags = new HashSet<>(); @@ -9540,7 +9518,7 @@ public BType defineInferredRecordType(BLangRecordLiteral recordLiteral, BType ex recordSymbol.scope.define(fieldName, fieldSymbol); } - BRecordType recordType = new BRecordType(typeEnv, recordSymbol); + BRecordType recordType = new BRecordType(recordSymbol); recordType.fields = fields; if (restFieldTypes.contains(symTable.semanticError)) { @@ -9553,14 +9531,13 @@ public BType defineInferredRecordType(BLangRecordLiteral recordLiteral, BType ex } else if (restFieldTypes.size() == 1) { recordType.restFieldType = restFieldTypes.get(0); } else { - recordType.restFieldType = - BUnionType.create(typeEnv, null, restFieldTypes.toArray(new BType[0])); + recordType.restFieldType = BUnionType.create(null, restFieldTypes.toArray(new BType[0])); } recordSymbol.type = recordType; recordType.tsymbol = recordSymbol; if (expType == symTable.readonlyType || (recordType.sealed && allReadOnlyNonRestFields)) { - recordType.addFlags(Flags.READONLY); + recordType.flags |= Flags.READONLY; recordSymbol.flags |= Flags.READONLY; } @@ -9576,7 +9553,7 @@ private BRecordTypeSymbol createRecordTypeSymbol(PackageID pkgID, Location locat SymbolEnv env = data.env; BRecordTypeSymbol recordSymbol = Symbols.createRecordSymbol(Flags.ANONYMOUS, - Names.fromString(anonymousModelHelper.getNextAnonymousTypeKey(pkgID)), + Names.fromString(anonymousModelHelper.getNextAnonymousTypeKey(pkgID)), pkgID, null, env.scope.owner, location, origin); recordSymbol.scope = new Scope(recordSymbol); return recordSymbol; @@ -9598,7 +9575,7 @@ private void addToNonRestFieldTypes(Map nonRestFieldTypes, St FieldInfo fieldInfo = nonRestFieldTypes.get(keyString); List typeList = fieldInfo.types; - if (types.isUniqueType(typeList, exprType)) { + if (isUniqueType(typeList, exprType)) { typeList.add(exprType); } @@ -9607,6 +9584,23 @@ private void addToNonRestFieldTypes(Map nonRestFieldTypes, St } } + private boolean isUniqueType(Iterable typeList, BType type) { + type = Types.getImpliedType(type); + boolean isRecord = type.tag == TypeTags.RECORD; + + for (BType bType : typeList) { + bType = Types.getImpliedType(bType); + if (isRecord) { + if (type == bType) { + return false; + } + } else if (types.isSameType(type, bType)) { + return false; + } + } + return true; + } + private BType checkXmlSubTypeLiteralCompatibility(Location location, BXMLSubType mutableXmlSubType, BType expType, AnalyzerData data) { if (expType == symTable.semanticError) { @@ -9678,7 +9672,7 @@ private BType checkXmlSubTypeLiteralCompatibility(Location location, BXMLSubType private void markChildrenAsImmutable(BLangXMLElementLiteral bLangXMLElementLiteral, AnalyzerData data) { for (BLangExpression modifiedChild : bLangXMLElementLiteral.modifiedChildren) { BType childType = modifiedChild.getBType(); - if (Symbols.isFlagOn(childType.getFlags(), Flags.READONLY) || + if (Symbols.isFlagOn(childType.flags, Flags.READONLY) || !types.isSelectivelyImmutableType(childType, data.env.enclPkg.packageID)) { continue; } @@ -9698,7 +9692,7 @@ public void logUndefinedSymbolError(Location pos, String name) { } private void markTypeAsIsolated(BType actualType) { - actualType.addFlags(Flags.ISOLATED); + actualType.flags |= Flags.ISOLATED; actualType.tsymbol.flags |= Flags.ISOLATED; } @@ -9731,7 +9725,7 @@ private void handleObjectConstrExprForReadOnly( } classDefForConstructor.flagSet.add(Flag.READONLY); - actualObjectType.addFlags(Flags.READONLY); + actualObjectType.flags |= Flags.READONLY; actualObjectType.tsymbol.flags |= Flags.READONLY; ImmutableTypeCloner.markFieldsAsImmutable(classDefForConstructor, env, actualObjectType, types, @@ -9744,7 +9738,7 @@ private void markConstructedObjectIsolatedness(BObjectType actualObjectType) { if (actualObjectType.markedIsolatedness) { return; } - if (Symbols.isFlagOn(actualObjectType.getFlags(), Flags.READONLY)) { + if (Symbols.isFlagOn(actualObjectType.flags, Flags.READONLY)) { markTypeAsIsolated(actualObjectType); return; } @@ -9803,7 +9797,7 @@ private BType validateElvisExprLhsExpr(BLangElvisExpr elvisExpr, BType lhsType) } else if (size == 1) { actualType = memberTypes.iterator().next(); } else { - actualType = BUnionType.create(typeEnv, null, memberTypes); + actualType = BUnionType.create(null, memberTypes); } } else { // We should get here only for `any` and nil. We use the type as is since we don't have a way to @@ -9822,22 +9816,25 @@ private BType validateElvisExprLhsExpr(BLangElvisExpr elvisExpr, BType lhsType) private LinkedHashSet getTypeWithoutNilForNonAnyTypeWithNil(BType type) { BType referredType = Types.getImpliedType(type); if (referredType.tag == TypeTags.FINITE) { - BFiniteType finiteType = (BFiniteType) referredType; - List newValueSpace = new ArrayList<>(finiteType.valueSpace.length); - for (SemNamedType semNamedType : finiteType.valueSpace) { - if (!PredefinedType.NIL.equals(semNamedType.semType())) { - newValueSpace.add(semNamedType);; + Set valueSpace = ((BFiniteType) referredType).getValueSpace(); + LinkedHashSet nonNilValueSpace = new LinkedHashSet<>(); + for (BLangExpression expression : valueSpace) { + if (expression.getBType().tag != TypeTags.NIL) { + nonNilValueSpace.add(expression); } } - if (newValueSpace.isEmpty()) { + int nonNilValueSpaceSize = nonNilValueSpace.size(); + + if (nonNilValueSpaceSize == valueSpace.size()) { + return new LinkedHashSet<>(1) {{ add(referredType); }}; + } + + if (nonNilValueSpaceSize == 0) { return new LinkedHashSet<>(0); } - BFiniteType ft = new BFiniteType(null, newValueSpace.toArray(SemNamedType[]::new)); - return new LinkedHashSet<>(1) {{ - add(ft); - }}; + return new LinkedHashSet<>(1) {{ add(new BFiniteType(null, nonNilValueSpace)); }}; } BUnionType unionType = (BUnionType) referredType; @@ -9858,6 +9855,16 @@ private LinkedHashSet getTypeWithoutNilForNonAnyTypeWithNil(BType type) { return memberTypes; } + private BFiniteType createFiniteTypeFromFiniteTypeList(List finiteTypes) { + if (finiteTypes.size() == 1) { + return finiteTypes.get(0); + } else { + Set valueSpace = new LinkedHashSet<>(); + finiteTypes.forEach(constituent -> valueSpace.addAll(constituent.getValueSpace())); + return new BFiniteType(null, valueSpace); + } + } + private static class FieldInfo { List types; boolean required; @@ -9871,7 +9878,6 @@ private FieldInfo(List types, boolean required, boolean readonly) { } private static class TypeSymbolPair { - private final BVarSymbol fieldSymbol; private final BType determinedType; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeHashVisitor.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeHashVisitor.java index 5e54c8a473a3..28769a48e816 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeHashVisitor.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeHashVisitor.java @@ -24,6 +24,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BAnyType; import org.wso2.ballerinalang.compiler.semantics.model.types.BAnydataType; import org.wso2.ballerinalang.compiler.semantics.model.types.BArrayType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BBuiltInRefType; import org.wso2.ballerinalang.compiler.semantics.model.types.BErrorType; import org.wso2.ballerinalang.compiler.semantics.model.types.BField; import org.wso2.ballerinalang.compiler.semantics.model.types.BFiniteType; @@ -35,6 +36,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BJSONType; import org.wso2.ballerinalang.compiler.semantics.model.types.BMapType; import org.wso2.ballerinalang.compiler.semantics.model.types.BNeverType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BNilType; import org.wso2.ballerinalang.compiler.semantics.model.types.BNoType; import org.wso2.ballerinalang.compiler.semantics.model.types.BObjectType; import org.wso2.ballerinalang.compiler.semantics.model.types.BPackageType; @@ -51,6 +53,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BUnionType; import org.wso2.ballerinalang.compiler.semantics.model.types.BXMLSubType; import org.wso2.ballerinalang.compiler.semantics.model.types.BXMLType; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangExpression; import org.wso2.ballerinalang.compiler.util.Names; import org.wso2.ballerinalang.compiler.util.TypeTags; @@ -70,7 +73,7 @@ * * @since 2.0.0 */ -public class TypeHashVisitor extends UniqueTypeVisitor { +public class TypeHashVisitor implements UniqueTypeVisitor { private final Map visited; private final Set unresolvedTypes; private final Map cache; @@ -103,7 +106,7 @@ public Integer getHash(BType type) { } @Override - public Integer visit(BType type) { // TODO: can move to the abstract class? + public Integer visit(BType type) { if (type == null) { return 0; } @@ -112,7 +115,7 @@ public Integer visit(BType type) { // TODO: can move to the abstract class? case TypeTags.ANY: return visit((BAnyType) type); case TypeTags.NIL: - return visitNilType(type); + return visit((BNilType) type); case TypeTags.NEVER: return visit((BNeverType) type); case TypeTags.ANYDATA: @@ -199,12 +202,12 @@ public Integer visit(BArrayType type) { if (isCyclic(type)) { return 0; } - Integer hash = hash(baseHash(type), type.getSize(), type.state.getValue(), visit(type.eType)); + Integer hash = hash(baseHash(type), type.size, type.state.getValue(), visit(type.eType)); return addToVisited(type, hash); } @Override - public Integer visit(BReadonlyType type) { + public Integer visit(BBuiltInRefType type) { if (isVisited(type)) { return visited.get(type); } @@ -366,7 +369,7 @@ public Integer visit(BNeverType type) { } @Override - public Integer visitNilType(BType type) { + public Integer visit(BNilType type) { if (isVisited(type)) { return visited.get(type); } @@ -403,7 +406,7 @@ public Integer visit(BTupleType type) { return 0; } List tupleTypesHashes = getOrderedTypesHashes(type.getTupleTypes()); - Integer hash = hash(baseHash(type), tupleTypesHashes, visit(type.restType), type.getFlags(), type.tsymbol); + Integer hash = hash(baseHash(type), tupleTypesHashes, visit(type.restType), type.flags, type.tsymbol); return addToVisited(type, hash); } @@ -452,8 +455,18 @@ public Integer visit(BFiniteType type) { if (isCyclic(type)) { return 0; } - - Integer hash = hash(baseHash(type), type.toString().hashCode()); + List toSort = new ArrayList<>(); + for (BLangExpression bLangExpression : type.getValueSpace()) { + String toString = bLangExpression.toString(); + toSort.add(toString); + } + toSort.sort(null); + List valueSpaceHashes = new ArrayList<>(); + for (String toString : toSort) { + Integer hashCode = toString.hashCode(); + valueSpaceHashes.add(hashCode); + } + Integer hash = hash(baseHash(type), valueSpaceHashes); return addToVisited(type, hash); } @@ -467,7 +480,7 @@ public Integer visit(BStructureType type) { } List fieldsHashes = getFieldsHashes(type.fields); List typeInclHashes = getTypesHashes(type.typeInclusions); - Integer hash = hash(baseHash(type), type.getFlags(), fieldsHashes, typeInclHashes); + Integer hash = hash(baseHash(type), type.flags, fieldsHashes, typeInclHashes); return addToVisited(type, hash); } @@ -482,7 +495,7 @@ public Integer visit(BObjectType type) { List fieldsHashes = getFieldsHashes(type.fields); List typeInclHashes = getTypesHashes(type.typeInclusions); List attachedFunctionsHashes = getFunctionsHashes(((BObjectTypeSymbol) type.tsymbol).attachedFuncs); - Integer hash = hash(baseHash(type), type.getFlags(), fieldsHashes, typeInclHashes, + Integer hash = hash(baseHash(type), type.flags, fieldsHashes, typeInclHashes, attachedFunctionsHashes, type.typeIdSet); return addToVisited(type, hash); } @@ -497,7 +510,7 @@ public Integer visit(BRecordType type) { } List fieldsHashes = getFieldsHashes(type.fields); List typeInclHashes = getTypesHashes(type.typeInclusions); - Integer hash = hash(baseHash(type), type.getFlags(), type.sealed, fieldsHashes, typeInclHashes, + Integer hash = hash(baseHash(type), type.flags, type.sealed, fieldsHashes, typeInclHashes, visit(type.restFieldType)); return addToVisited(type, hash); } @@ -510,7 +523,7 @@ public Integer visit(BUnionType type) { if (isCyclic(type)) { return 0; } - Integer hash = hash(baseHash(type), type.isCyclic, getTypesHashes(type.getMemberTypes()), type.getFlags()); + Integer hash = hash(baseHash(type), type.isCyclic, getTypesHashes(type.getMemberTypes()), type.flags); return addToVisited(type, hash); } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeNarrower.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeNarrower.java index 35ec2e2e95c7..d2ee81e5d206 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeNarrower.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeNarrower.java @@ -18,7 +18,6 @@ package org.wso2.ballerinalang.compiler.semantics.analyzer; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.SemType; import org.ballerinalang.model.elements.Flag; import org.ballerinalang.model.symbols.SymbolKind; import org.ballerinalang.model.tree.NodeKind; @@ -40,7 +39,6 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangBinaryExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangGroupExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangSimpleVarRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangTypeTestExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangUnaryExpr; @@ -393,7 +391,7 @@ private BType getTypeUnion(BType currentType, BType targetType) { } else if (union.size() == 1) { return union.toArray(new BType[1])[0]; } - return BUnionType.create(symTable.typeEnv(), null, union); + return BUnionType.create(null, union); } BVarSymbol getOriginalVarSymbol(BVarSymbol varSymbol) { @@ -421,17 +419,15 @@ private BFiniteType createFiniteType(BLangExpression expr) { Flags.asMask(EnumSet.noneOf(Flag.class)), Names.EMPTY, env.enclPkg.symbol.pkgID, null, env.scope.owner, expr.pos, SOURCE); - SemType semType; + BFiniteType finiteType = new BFiniteType(finiteTypeSymbol); if (expr.getKind() == NodeKind.UNARY_EXPR) { - semType = SemTypeHelper.resolveSingletonType(Types.constructNumericLiteralFromUnaryExpr( - (BLangUnaryExpr) expr)); + finiteType.addValue(Types.constructNumericLiteralFromUnaryExpr((BLangUnaryExpr) expr)); } else { expr.setBType(symTable.getTypeFromTag(expr.getBType().tag)); - semType = SemTypeHelper.resolveSingletonType((BLangLiteral) expr); + finiteType.addValue(expr); } - - BFiniteType finiteType = BFiniteType.newSingletonBFiniteType(finiteTypeSymbol, semType); finiteTypeSymbol.type = finiteType; + return finiteType; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeParamAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeParamAnalyzer.java index 7b3eda99d419..731978cb27fc 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeParamAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeParamAnalyzer.java @@ -18,7 +18,6 @@ package org.wso2.ballerinalang.compiler.semantics.analyzer; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.PredefinedType; import org.ballerinalang.model.Name; import org.ballerinalang.model.elements.PackageID; import org.ballerinalang.model.tree.NodeKind; @@ -131,7 +130,7 @@ private TypeParamAnalyzer(CompilerContext context) { static boolean isTypeParam(BType expType) { - return Symbols.isFlagOn(expType.getFlags(), Flags.TYPE_PARAM) + return Symbols.isFlagOn(expType.flags, Flags.TYPE_PARAM) || (expType.tsymbol != null && Symbols.isFlagOn(expType.tsymbol.flags, Flags.TYPE_PARAM)); } @@ -174,7 +173,7 @@ public BType getNominalType(BType type, Name name, long flag) { BType createTypeParam(BSymbol symbol) { BType type = symbol.type; - var flag = type.getFlags() | Flags.TYPE_PARAM; + var flag = type.flags | Flags.TYPE_PARAM; return createTypeParamType(symbol, type, symbol.name, flag); } @@ -223,7 +222,7 @@ private static boolean containsTypeParam(BType type, HashSet resolvedType return false; case TypeTags.INVOKABLE: BInvokableType invokableType = (BInvokableType) type; - if (Symbols.isFlagOn(invokableType.getFlags(), Flags.ANY_FUNCTION)) { + if (Symbols.isFlagOn(invokableType.flags, Flags.ANY_FUNCTION)) { return false; } for (BType paramType : invokableType.paramTypes) { @@ -278,9 +277,9 @@ private BType createBuiltInType(BType type, Name name, long flags) { TypeTags.DECIMAL, TypeTags.STRING, TypeTags.BOOLEAN -> new BType(tag, null, name, flags); - case TypeTags.ANY -> new BAnyType(name, flags); + case TypeTags.ANY -> new BAnyType(tag, null, name, flags); case TypeTags.ANYDATA -> createAnydataType((BUnionType) referredType, name, flags); - case TypeTags.READONLY -> new BReadonlyType(flags); + case TypeTags.READONLY -> new BReadonlyType(tag, null, name, flags); // For others, we will use TSymbol. default -> type; }; @@ -298,17 +297,16 @@ private BType createTypeParamType(BSymbol symbol, BType type, Name name, long fl case TypeTags.BOOLEAN: return new BType(type.tag, null, name, flags); case TypeTags.ANY: - return new BAnyType(name, flags); + return new BAnyType(type.tag, null, name, flags); case TypeTags.ANYDATA: return createAnydataType((BUnionType) type, name, flags); case TypeTags.READONLY: - return new BReadonlyType(flags); + return new BReadonlyType(type.tag, null, name, flags); case TypeTags.UNION: if (types.isCloneableType((BUnionType) refType)) { - BUnionType cloneableType = - BUnionType.create(symTable.typeEnv(), null, symTable.readonlyType, symTable.xmlType); + BUnionType cloneableType = BUnionType.create(null, symTable.readonlyType, symTable.xmlType); addCyclicArrayMapTableOfMapMembers(cloneableType); - cloneableType.setFlags(flags); + cloneableType.flags = flags; cloneableType.tsymbol = new BTypeSymbol(SymTag.TYPE, refType.tsymbol.flags, symbol.name, refType.tsymbol.pkgID, cloneableType, refType.tsymbol.owner, type.tsymbol.pos, @@ -325,20 +323,20 @@ private BType createTypeParamType(BSymbol symbol, BType type, Name name, long fl } private BAnydataType createAnydataType(BUnionType unionType, Name name, long flags) { - BAnydataType anydataType = new BAnydataType(types.typeCtx(), unionType); + BAnydataType anydataType = new BAnydataType(unionType); Optional immutableType = Types.getImmutableType(symTable, PackageID.ANNOTATIONS, unionType); immutableType.ifPresent(bIntersectionType -> Types.addImmutableType(symTable, PackageID.ANNOTATIONS, anydataType, bIntersectionType)); anydataType.name = name; - anydataType.addFlags(flags); + anydataType.flags |= flags; return anydataType; } private void addCyclicArrayMapTableOfMapMembers(BUnionType unionType) { - BArrayType arrayCloneableType = new BArrayType(symTable.typeEnv(), unionType); - BMapType mapCloneableType = new BMapType(symTable.typeEnv(), TypeTags.MAP, unionType, null); - BType tableMapCloneableType = new BTableType(symTable.typeEnv(), mapCloneableType, null); + BArrayType arrayCloneableType = new BArrayType(unionType); + BMapType mapCloneableType = new BMapType(TypeTags.MAP, unionType, null); + BType tableMapCloneableType = new BTableType(TypeTags.TABLE, mapCloneableType, null); unionType.add(arrayCloneableType); unionType.add(mapCloneableType); unionType.add(tableMapCloneableType); @@ -592,10 +590,10 @@ private void findTypeParamInStreamForUnion(Location loc, BStreamType expType, BU } } - BUnionType cUnionType = BUnionType.create(symTable.typeEnv(), null, constraintTypes); + BUnionType cUnionType = BUnionType.create(null, constraintTypes); findTypeParam(loc, expType.constraint, cUnionType, env, resolvedTypes, result); if (!completionTypes.isEmpty()) { - BUnionType eUnionType = BUnionType.create(symTable.typeEnv(), null, completionTypes); + BUnionType eUnionType = BUnionType.create(null, completionTypes); findTypeParam(loc, expType.completionType, eUnionType, env, resolvedTypes, result); } else { findTypeParam(loc, expType.completionType, symTable.nilType, env, resolvedTypes, result); @@ -617,7 +615,7 @@ private void findTypeParamInTable(Location loc, BTableType expType, BTableType a if (members.size() == 1) { findTypeParam(loc, expType.keyTypeConstraint, members.get(0).type, env, resolvedTypes, result); } else { - BTupleType tupleType = new BTupleType(symTable.typeEnv(), members); + BTupleType tupleType = new BTupleType(members); findTypeParam(loc, expType.keyTypeConstraint, tupleType, env, resolvedTypes, result); } } @@ -634,7 +632,7 @@ private void findTypeParamInTupleForArray(Location loc, BArrayType expType, BTup int size = tupleTypes.size(); BType type = size == 0 ? symTable.neverType : - (size == 1 ? tupleTypes.iterator().next() : BUnionType.create(symTable.typeEnv(), null, tupleTypes)); + (size == 1 ? tupleTypes.iterator().next() : BUnionType.create(null, tupleTypes)); findTypeParam(loc, expType.eType, type, env, resolvedTypes, result); } @@ -665,7 +663,7 @@ private void findTypeParamInUnion(Location loc, BType expType, BUnionType actual ((BTupleType) referredType).getTupleTypes().forEach(member -> members.add(member)); } } - BUnionType tupleElementType = BUnionType.create(symTable.typeEnv(), null, members); + BUnionType tupleElementType = BUnionType.create(null, members); findTypeParam(loc, expType, tupleElementType, env, resolvedTypes, result); } @@ -705,7 +703,7 @@ private void findTypeParamInMapForRecord(Location loc, BMapType expType, BRecord if (reducedTypeSet.size() == 1) { commonFieldType = reducedTypeSet.iterator().next(); } else { - commonFieldType = BUnionType.create(symTable.typeEnv(), null, reducedTypeSet); + commonFieldType = BUnionType.create(null, reducedTypeSet); } findTypeParam(loc, expType.constraint, commonFieldType, env, resolvedTypes, result); @@ -714,7 +712,7 @@ private void findTypeParamInMapForRecord(Location loc, BMapType expType, BRecord private void findTypeParamInInvokableType(Location loc, BInvokableType expType, BInvokableType actualType, SymbolEnv env, HashSet resolvedTypes, FindTypeParamResult result) { - if (Symbols.isFlagOn(expType.getFlags(), Flags.ANY_FUNCTION)) { + if (Symbols.isFlagOn(expType.flags, Flags.ANY_FUNCTION)) { return; } for (int i = 0; i < expType.paramTypes.size() && i < actualType.paramTypes.size(); i++) { @@ -770,14 +768,14 @@ private void findTypeParamInError(Location loc, BErrorType expType, BType actual findTypeParam(loc, expType.detailType, ((BErrorType) actualType).detailType, env, resolvedTypes, result); } - if (actualType.tag == TypeTags.UNION && types.isSubTypeOfBaseType(actualType, PredefinedType.ERROR)) { + if (actualType.tag == TypeTags.UNION && types.isSubTypeOfBaseType(actualType, TypeTags.ERROR)) { BUnionType errorUnion = (BUnionType) actualType; LinkedHashSet errorDetailTypes = new LinkedHashSet<>(); for (BType errorType : errorUnion.getMemberTypes()) { BType member = Types.getImpliedType(errorType); errorDetailTypes.add(((BErrorType) member).detailType); } - BUnionType errorDetailUnionType = BUnionType.create(symTable.typeEnv(), null, errorDetailTypes); + BUnionType errorDetailUnionType = BUnionType.create(null, errorDetailTypes); findTypeParam(loc, expType.detailType, errorDetailUnionType, env, resolvedTypes, result); } } @@ -804,15 +802,14 @@ private BType getMatchingBoundType(BType expType, SymbolEnv env, HashSet if (!isDifferentTypes(elementType, matchingBoundElementType)) { return expType; } - return new BArrayType(symTable.typeEnv(), matchingBoundElementType); + return new BArrayType(matchingBoundElementType); case TypeTags.MAP: BType constraint = ((BMapType) expType).constraint; BType matchingBoundMapConstraintType = getMatchingBoundType(constraint, env, resolvedTypes); if (!isDifferentTypes(constraint, matchingBoundMapConstraintType)) { return expType; } - return new BMapType(symTable.typeEnv(), TypeTags.MAP, matchingBoundMapConstraintType, - symTable.mapType.tsymbol); + return new BMapType(TypeTags.MAP, matchingBoundMapConstraintType, symTable.mapType.tsymbol); case TypeTags.STREAM: BStreamType expStreamType = (BStreamType) expType; BType expStreamConstraint = expStreamType.constraint; @@ -829,8 +826,7 @@ private BType getMatchingBoundType(BType expType, SymbolEnv env, HashSet return expStreamType; } - return new BStreamType(symTable.typeEnv(), TypeTags.STREAM, constraintType, completionType, - symTable.streamType.tsymbol); + return new BStreamType(TypeTags.STREAM, constraintType, completionType, symTable.streamType.tsymbol); case TypeTags.TABLE: BTableType expTableType = (BTableType) expType; BType expTableConstraint = expTableType.constraint; @@ -848,8 +844,7 @@ private BType getMatchingBoundType(BType expType, SymbolEnv env, HashSet return expTableType; } - BTableType tableType = new BTableType(symTable.typeEnv(), tableConstraint, - symTable.tableType.tsymbol); + BTableType tableType = new BTableType(TypeTags.TABLE, tableConstraint, symTable.tableType.tsymbol); if (expTableKeyTypeConstraint != null) { tableType.keyTypeConstraint = keyTypeConstraint; } @@ -873,7 +868,7 @@ private BType getMatchingBoundType(BType expType, SymbolEnv env, HashSet return expType; } - return new BTypedescType(symTable.typeEnv(), matchingBoundType, symTable.typeDesc.tsymbol); + return new BTypedescType(matchingBoundType, symTable.typeDesc.tsymbol); case TypeTags.INTERSECTION: return getMatchingReadonlyIntersectionBoundType((BIntersectionType) expType, env, resolvedTypes); case TypeTags.TYPEREFDESC: @@ -915,7 +910,7 @@ private BType getMatchingReadonlyIntersectionBoundType(BIntersectionType interse } if (types.isInherentlyImmutableType(matchingBoundNonReadOnlyType) || - Symbols.isFlagOn(matchingBoundNonReadOnlyType.getFlags(), Flags.READONLY)) { + Symbols.isFlagOn(matchingBoundNonReadOnlyType.flags, Flags.READONLY)) { return matchingBoundNonReadOnlyType; } @@ -935,7 +930,7 @@ private BTupleType getMatchingTupleBoundType(BTupleType expType, SymbolEnv env, if (!hasDifferentType && isDifferentTypes(type, matchingBoundType)) { hasDifferentType = true; } - BVarSymbol varSymbol = new BVarSymbol(matchingBoundType.getFlags(), null, null, matchingBoundType, + BVarSymbol varSymbol = new BVarSymbol(matchingBoundType.flags, null, null, matchingBoundType, null, null, null); members.add(new BTupleMember(matchingBoundType, varSymbol)); } @@ -952,7 +947,7 @@ private BTupleType getMatchingTupleBoundType(BTupleType expType, SymbolEnv env, return expType; } - return new BTupleType(symTable.typeEnv(), members); + return new BTupleType(members); } private BRecordType getMatchingRecordBoundType(BRecordType expType, SymbolEnv env, HashSet resolvedTypes) { @@ -981,10 +976,10 @@ private BRecordType getMatchingRecordBoundType(BRecordType expType, SymbolEnv en recordSymbol.scope.define(expField.name, field.symbol); } - BRecordType bRecordType = new BRecordType(symTable.typeEnv(), recordSymbol); + BRecordType bRecordType = new BRecordType(recordSymbol); bRecordType.fields = fields; recordSymbol.type = bRecordType; - bRecordType.setFlags(expType.getFlags()); + bRecordType.flags = expType.flags; if (expType.sealed) { bRecordType.sealed = true; @@ -1015,7 +1010,7 @@ private BInvokableType getMatchingFunctionBoundType(BInvokableType expType, Symb } BType restType = expType.restType; - var flags = expType.getFlags(); + var flags = expType.flags; BInvokableTypeSymbol invokableTypeSymbol = Symbols.createInvokableTypeSymbol(SymTag.FUNCTION_TYPE, flags, env.enclPkg.symbol.pkgID, expType, env.scope.owner, expType.tsymbol.pos, VIRTUAL); @@ -1032,7 +1027,7 @@ private BInvokableType getMatchingFunctionBoundType(BInvokableType expType, Symb return expType; } - BInvokableType invokableType = new BInvokableType(symTable.typeEnv(), paramTypes, restType, + BInvokableType invokableType = new BInvokableType(paramTypes, restType, matchingBoundType, invokableTypeSymbol); invokableTypeSymbol.returnType = invokableType.retType; @@ -1040,7 +1035,7 @@ private BInvokableType getMatchingFunctionBoundType(BInvokableType expType, Symb invokableType.tsymbol.isTypeParamResolved = true; invokableType.tsymbol.typeParamTSymbol = expType.tsymbol; if (Symbols.isFlagOn(flags, Flags.ISOLATED)) { - invokableType.addFlags(Flags.ISOLATED); + invokableType.flags |= Flags.ISOLATED; } return invokableType; @@ -1057,7 +1052,7 @@ private BType getMatchingObjectBoundType(BObjectType expType, SymbolEnv env, Has actObjectSymbol.isTypeParamResolved = true; actObjectSymbol.typeParamTSymbol = expType.tsymbol; - BObjectType objectType = new BObjectType(symTable.typeEnv(), actObjectSymbol); + BObjectType objectType = new BObjectType(actObjectSymbol); actObjectSymbol.type = objectType; actObjectSymbol.scope = new Scope(actObjectSymbol); @@ -1139,7 +1134,7 @@ private BType getMatchingOptionalBoundType(BUnionType expType, SymbolEnv env, Ha return expType; } - return BUnionType.create(symTable.typeEnv(), null, members); + return BUnionType.create(null, members); } private BType getMatchingErrorBoundType(BErrorType expType, SymbolEnv env, HashSet resolvedTypes) { @@ -1161,7 +1156,7 @@ private BType getMatchingErrorBoundType(BErrorType expType, SymbolEnv env, HashS null, null, symTable.builtinPos, VIRTUAL); typeSymbol.isTypeParamResolved = true; typeSymbol.typeParamTSymbol = expType.tsymbol; - BErrorType errorType = new BErrorType(symTable.typeEnv(), typeSymbol, detailType); + BErrorType errorType = new BErrorType(typeSymbol, detailType); typeSymbol.type = errorType; return errorType; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeResolver.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeResolver.java index 9812114fd3fb..189a1504468d 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeResolver.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeResolver.java @@ -18,7 +18,6 @@ package org.wso2.ballerinalang.compiler.semantics.analyzer; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.SemType; import org.ballerinalang.model.elements.Flag; import org.ballerinalang.model.elements.PackageID; import org.ballerinalang.model.symbols.SymbolKind; @@ -69,7 +68,6 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BTypedescType; import org.wso2.ballerinalang.compiler.semantics.model.types.BUnionType; import org.wso2.ballerinalang.compiler.semantics.model.types.BXMLType; -import org.wso2.ballerinalang.compiler.semantics.model.types.SemNamedType; import org.wso2.ballerinalang.compiler.tree.BLangClassDefinition; import org.wso2.ballerinalang.compiler.tree.BLangConstantValue; import org.wso2.ballerinalang.compiler.tree.BLangFunction; @@ -131,7 +129,6 @@ import static org.ballerinalang.model.symbols.SymbolOrigin.BUILTIN; import static org.ballerinalang.model.symbols.SymbolOrigin.SOURCE; import static org.ballerinalang.model.symbols.SymbolOrigin.VIRTUAL; -import static org.wso2.ballerinalang.compiler.semantics.analyzer.SemTypeHelper.singleShapeBroadType; import static org.wso2.ballerinalang.compiler.util.Constants.INFERRED_ARRAY_INDICATOR; import static org.wso2.ballerinalang.compiler.util.Constants.OPEN_ARRAY_INDICATOR; @@ -380,7 +377,7 @@ public void defineClassDef(BLangClassDefinition classDefinition, SymbolEnv env) typeFlags |= Flags.OBJECT_CTOR; } - BObjectType objectType = new BObjectType(symTable.typeEnv(), tSymbol, typeFlags); + BObjectType objectType = new BObjectType(tSymbol, typeFlags); resolvingStructureTypes.add(objectType); if (classDefinition.isObjectContructorDecl || flags.contains(Flag.OBJECT_CTOR)) { classDefinition.oceEnvData.objectType = objectType; @@ -392,7 +389,7 @@ public void defineClassDef(BLangClassDefinition classDefinition, SymbolEnv env) } if (flags.contains(Flag.CLIENT)) { - objectType.addFlags(Flags.CLIENT); + objectType.flags |= Flags.CLIENT; } tSymbol.type = objectType; @@ -495,7 +492,7 @@ private void handleDistinctDefinitionOfErrorIntersection(BLangTypeDefinition typ } if (!effectiveType.typeIdSet.isEmpty()) { - definedType.addFlags(Flags.DISTINCT); + definedType.flags |= Flags.DISTINCT; } } } @@ -577,7 +574,7 @@ private void updateIsCyclicFlag(BType type) { ((BUnionType) type).isCyclic = true; break; case INTERSECTION: - updateIsCyclicFlag(((BIntersectionType) type).effectiveType); + updateIsCyclicFlag(((BIntersectionType) type).getEffectiveType()); break; } } @@ -649,8 +646,8 @@ public BType validateModuleLevelDef(String name, Name pkgAlias, Name typeName, B td.symbol = symbol; if (symbol.kind == SymbolKind.TYPE_DEF && !Symbols.isFlagOn(symbol.flags, Flags.ANONYMOUS)) { BType referenceType = ((BTypeDefinitionSymbol) symbol).referenceType; - referenceType.addFlags(symbol.type.getFlags()); - referenceType.tsymbol.flags |= symbol.type.getFlags(); + referenceType.flags |= symbol.type.flags; + referenceType.tsymbol.flags |= symbol.type.flags; return referenceType; } return resolvedType; @@ -764,7 +761,7 @@ private BType resolveTypedescTypeDesc(BLangConstrainedType td, ResolverData data SymbolEnv symEnv = data.env; BType type = resolveTypeDesc(symEnv, data.typeDefinition, data.depth + 1, td.type, data); - BTypedescType constrainedType = new BTypedescType(symTable.typeEnv(), symTable.empty, null); + BTypedescType constrainedType = new BTypedescType(symTable.empty, null); BTypeSymbol typeSymbol = type.tsymbol; constrainedType.tsymbol = Symbols.createTypeSymbol(typeSymbol.tag, typeSymbol.flags, typeSymbol.name, typeSymbol.originalName, symEnv.enclPkg.symbol.pkgID, constrainedType, typeSymbol.owner, @@ -783,7 +780,7 @@ private BType resolveFutureTypeDesc(BLangConstrainedType td, ResolverData data) SymbolEnv symEnv = data.env; BType type = resolveTypeDesc(symEnv, data.typeDefinition, data.depth + 1, td.type, data); - BFutureType constrainedType = new BFutureType(symTable.typeEnv(), symTable.empty, null); + BFutureType constrainedType = new BFutureType(TypeTags.FUTURE, symTable.empty, null); BTypeSymbol typeSymbol = type.tsymbol; constrainedType.tsymbol = Symbols.createTypeSymbol(typeSymbol.tag, typeSymbol.flags, typeSymbol.name, typeSymbol.originalName, symEnv.enclPkg.symbol.pkgID, constrainedType, typeSymbol.owner, @@ -838,7 +835,7 @@ private BType resolveMapTypeDesc(BLangConstrainedType td, ResolverData data) { BTypeSymbol tSymbol = Symbols.createTypeSymbol(SymTag.TYPE, typeSymbol.flags, Names.EMPTY, typeSymbol.originalName, symEnv.enclPkg.symbol.pkgID, null, symEnv.scope.owner, td.pos, BUILTIN); - BMapType constrainedType = new BMapType(symTable.typeEnv(), TypeTags.MAP, symTable.empty, tSymbol); + BMapType constrainedType = new BMapType(TypeTags.MAP, symTable.empty, tSymbol); td.setBType(constrainedType); tSymbol.type = type; resolvingTypes.push(constrainedType); @@ -867,7 +864,7 @@ private BType resolveTypeDesc(BLangArrayType td, ResolverData data) { symEnv.enclPkg.symbol.pkgID, null, symEnv.scope.owner, td.pos, BUILTIN); BArrayType arrType; if (td.sizes.isEmpty()) { - arrType = new BArrayType(symTable.typeEnv(), resultType, arrayTypeSymbol); + arrType = new BArrayType(resultType, arrayTypeSymbol); } else { BLangExpression size = td.sizes.get(i); if (size.getKind() == NodeKind.LITERAL || size.getKind() == NodeKind.NUMERIC_LITERAL) { @@ -880,8 +877,7 @@ private BType resolveTypeDesc(BLangArrayType td, ResolverData data) { } else { arrayState = BArrayState.CLOSED; } - arrType = - new BArrayType(symTable.typeEnv(), resultType, arrayTypeSymbol, sizeIndicator, arrayState); + arrType = new BArrayType(resultType, arrayTypeSymbol, sizeIndicator, arrayState); } else { if (size.getKind() != NodeKind.SIMPLE_VARIABLE_REF) { dlog.error(size.pos, DiagnosticErrorCode.INCOMPATIBLE_TYPES, symTable.intType, @@ -932,8 +928,7 @@ private BType resolveTypeDesc(BLangArrayType td, ResolverData data) { } else { length = (int) lengthCheck; } - arrType = - new BArrayType(symTable.typeEnv(), resultType, arrayTypeSymbol, length, BArrayState.CLOSED); + arrType = new BArrayType(resultType, arrayTypeSymbol, length, BArrayState.CLOSED); } } arrayTypeSymbol.type = arrType; @@ -970,7 +965,7 @@ private BType resolveTypeDesc(BLangTupleTypeNode td, ResolverData data) { Names.EMPTY, symEnv.enclPkg.symbol.pkgID, null, symEnv.scope.owner, td.pos, BUILTIN); List memberTypes = new ArrayList<>(); - BTupleType tupleType = new BTupleType(symTable.typeEnv(), tupleTypeSymbol, memberTypes); + BTupleType tupleType = new BTupleType(tupleTypeSymbol, memberTypes); tupleTypeSymbol.type = tupleType; td.setBType(tupleType); resolvingTypes.push(tupleType); @@ -979,7 +974,7 @@ private BType resolveTypeDesc(BLangTupleTypeNode td, ResolverData data) { BType type = resolveTypeDesc(symEnv, data.typeDefinition, data.depth + 1, memberNode.typeNode, data); SymbolEnv tupleEnv = SymbolEnv.createTypeEnv(td, new Scope(tupleTypeSymbol), symEnv); symEnter.defineNode(memberNode, tupleEnv); - BVarSymbol varSymbol = new BVarSymbol(memberNode.getBType().getFlags(), memberNode.symbol.name, + BVarSymbol varSymbol = new BVarSymbol(memberNode.getBType().flags, memberNode.symbol.name, memberNode.symbol.pkgID, memberNode.getBType(), memberNode.symbol.owner, memberNode.pos, SOURCE); memberTypes.add(new BTupleMember(type, varSymbol)); } @@ -1014,7 +1009,7 @@ private BType resolveTypeDesc(BLangRecordTypeNode td, ResolverData data) { symEnv.enclPkg.symbol.pkgID, null, symEnv.scope.owner, td.pos, td.isAnonymous ? VIRTUAL : BUILTIN); - BRecordType recordType = new BRecordType(symTable.typeEnv(), recordSymbol); + BRecordType recordType = new BRecordType(recordSymbol); resolvingStructureTypes.add(recordType); recordSymbol.type = recordType; td.symbol = recordSymbol; @@ -1081,7 +1076,7 @@ private BType resolveTypeDesc(BLangObjectTypeNode td, ResolverData data) { BTypeSymbol objectSymbol = Symbols.createObjectSymbol(Flags.asMask(flags), Names.EMPTY, symEnv.enclPkg.symbol.pkgID, null, symEnv.scope.owner, td.pos, BUILTIN); - BObjectType objectType = new BObjectType(symTable.typeEnv(), objectSymbol, typeFlags); + BObjectType objectType = new BObjectType(objectSymbol, typeFlags); resolvingStructureTypes.add(objectType); objectSymbol.type = objectType; td.symbol = objectSymbol; @@ -1118,7 +1113,7 @@ private BType resolveTypeDesc(BLangFunctionTypeNode td, ResolverData data) { SymbolEnv symEnv = data.env; Location pos = td.pos; - BInvokableType bInvokableType = new BInvokableType(symTable.typeEnv(), List.of(), null, null, null); + BInvokableType bInvokableType = new BInvokableType(null, null, null, null); BInvokableTypeSymbol tsymbol = Symbols.createInvokableTypeSymbol(SymTag.FUNCTION_TYPE, Flags.asMask(td.flagSet), symEnv.enclPkg.symbol.pkgID, bInvokableType, symEnv.scope.owner, pos, BUILTIN); @@ -1151,7 +1146,7 @@ public BType createInvokableType(List paramVars, List paramNames = new ArrayList<>(); BInvokableTypeSymbol tsymbol = (BInvokableTypeSymbol) bInvokableType.tsymbol; if (Symbols.isFlagOn(flags, Flags.ANY_FUNCTION)) { - bInvokableType.setFlags(flags); + bInvokableType.flags = flags; tsymbol.params = null; tsymbol.restParam = null; tsymbol.returnType = null; @@ -1207,7 +1202,7 @@ public BType createInvokableType(List paramVars, bInvokableType.paramTypes = paramTypes; bInvokableType.restType = restType; bInvokableType.retType = retType; - bInvokableType.addFlags(flags); + bInvokableType.flags |= flags; tsymbol.params = params; tsymbol.restParam = restParam; tsymbol.returnType = retType; @@ -1227,7 +1222,7 @@ private BType resolveTypeDesc(BLangErrorType td, ResolverData data) { } if (td.detailType == null) { - BType errorType = new BErrorType(symTable.typeEnv(), null, symTable.detailType); + BType errorType = new BErrorType(null, symTable.detailType); errorType.tsymbol = new BErrorTypeSymbol(SymTag.ERROR, Flags.PUBLIC, Names.ERROR, symTable.rootPkgSymbol.pkgID, errorType, symTable.rootPkgSymbol, symTable.builtinPos, BUILTIN); return errorType; @@ -1236,7 +1231,7 @@ private BType resolveTypeDesc(BLangErrorType td, ResolverData data) { // Define user define error type. BErrorTypeSymbol errorTypeSymbol = Symbols.createErrorSymbol(Flags.asMask(td.flagSet), Names.EMPTY, data.env.enclPkg.packageID, null, data.env.scope.owner, td.pos, BUILTIN); - BErrorType errorType = new BErrorType(symTable.typeEnv(), errorTypeSymbol, symTable.empty); + BErrorType errorType = new BErrorType(errorTypeSymbol, symTable.empty); td.setBType(errorType); resolvingTypes.push(errorType); @@ -1267,7 +1262,7 @@ private BType resolveTypeDesc(BLangErrorType td, ResolverData data) { symEnter.defineSymbol(td.pos, errorTypeSymbol, data.env); } - errorType.addFlags(errorTypeSymbol.flags); + errorType.flags |= errorTypeSymbol.flags; errorTypeSymbol.type = errorType; symResolver.markParameterizedType(errorType, detailType); @@ -1291,7 +1286,7 @@ private BType resolveTypeDesc(BLangUnionTypeNode td, ResolverData data) { BTypeSymbol unionTypeSymbol = Symbols.createTypeSymbol(SymTag.UNION_TYPE, Flags.asMask(EnumSet.of(Flag.PUBLIC)), Names.EMPTY, symEnv.enclPkg.symbol.pkgID, null, symEnv.scope.owner, td.pos, BUILTIN); - BUnionType unionType = new BUnionType(types.typeEnv(), unionTypeSymbol, memberTypes, false); + BUnionType unionType = new BUnionType(unionTypeSymbol, memberTypes, false, false); unionTypeSymbol.type = unionType; td.setBType(unionType); resolvingTypes.push(unionType); @@ -1303,37 +1298,63 @@ private BType resolveTypeDesc(BLangUnionTypeNode td, ResolverData data) { continue; } + if (resolvedType.isNullable()) { + unionType.setNullable(true); + } memberTypes.add(resolvedType); } - updateReadOnlyFlag(unionType); + updateReadOnlyAndNullableFlag(unionType); symResolver.markParameterizedType(unionType, memberTypes); resolvingTypes.pop(); return unionType; } - private void updateReadOnlyFlag(BUnionType type) { + private void updateReadOnlyAndNullableFlag(BUnionType type) { LinkedHashSet memberTypes = type.getMemberTypes(); LinkedHashSet flattenMemberTypes = new LinkedHashSet<>(memberTypes.size()); boolean isImmutable = true; + boolean hasNilableType = false; for (BType memBType : BUnionType.toFlatTypeSet(memberTypes)) { if (Types.getImpliedType(memBType).tag != TypeTags.NEVER) { flattenMemberTypes.add(memBType); } - if (isImmutable && !Symbols.isFlagOn(memBType.getFlags(), Flags.READONLY)) { + if (isImmutable && !Symbols.isFlagOn(memBType.flags, Flags.READONLY)) { isImmutable = false; } } if (isImmutable) { - type.addFlags(Flags.READONLY); + type.flags |= Flags.READONLY; if (type.tsymbol != null) { type.tsymbol.flags |= Flags.READONLY; } } + for (BType memberType : flattenMemberTypes) { + if (memberType.isNullable() && memberType.tag != TypeTags.NIL) { + hasNilableType = true; + break; + } + } + + if (hasNilableType) { + LinkedHashSet bTypes = new LinkedHashSet<>(flattenMemberTypes.size()); + for (BType t : flattenMemberTypes) { + if (t.tag != TypeTags.NIL) { + bTypes.add(t); + } + } + flattenMemberTypes = bTypes; + } + + for (BType memberType : flattenMemberTypes) { + if (memberType.isNullable()) { + type.setNullable(true); + } + } type.setOriginalMemberTypes(memberTypes); memberTypes.clear(); memberTypes.addAll(flattenMemberTypes); @@ -1375,7 +1396,7 @@ private BType resolveTypeDesc(BLangIntersectionTypeNode td, ResolverData data, b intersectionType.setConstituentTypes(constituentTypes); if (hasReadonly) { - intersectionType.addFlags(Flags.READONLY); + intersectionType.flags |= Flags.READONLY; } // Differ cyclic intersection between more than 2 non-readonly types. @@ -1406,7 +1427,7 @@ private void fillEffectiveType(BIntersectionType intersectionType, while (iterator.hasNext()) { BType bLangEffectiveImpliedType = Types.getImpliedType(effectiveType); if (bLangEffectiveImpliedType.tag == TypeTags.READONLY) { - intersectionType.addFlags(TypeTags.READONLY); + intersectionType.flags = intersectionType.flags | TypeTags.READONLY; effectiveType = iterator.next(); bLangEffectiveType = bLangTypeItr.next(); continue; @@ -1415,7 +1436,7 @@ private void fillEffectiveType(BIntersectionType intersectionType, BLangType bLangType = bLangTypeItr.next(); BType typeReferenceType = Types.getImpliedType(type); if (typeReferenceType.tag == TypeTags.READONLY) { - intersectionType.addFlags(TypeTags.READONLY); + intersectionType.flags = intersectionType.flags | TypeTags.READONLY; continue; } effectiveType = calculateEffectiveType(td, bLangEffectiveType, bLangType, effectiveType, type, @@ -1426,9 +1447,9 @@ private void fillEffectiveType(BIntersectionType intersectionType, } } intersectionType.effectiveType = effectiveType; - intersectionType.addFlags(effectiveType.getFlags()); + intersectionType.flags |= effectiveType.flags; - if ((intersectionType.getFlags() & Flags.READONLY) == Flags.READONLY) { + if ((intersectionType.flags & Flags.READONLY) == Flags.READONLY) { if (types.isInherentlyImmutableType(effectiveType)) { return; } @@ -1523,7 +1544,7 @@ private BType resolveTypeDesc(BLangUserDefinedType td, ResolverData data) { null, func.symbol, tempSymbol.pos, VIRTUAL); tSymbol.type = new BParameterizedType(paramValType, (BVarSymbol) tempSymbol, tSymbol, tempSymbol.name, parameterizedTypeInfo.index); - tSymbol.type.addFlags(Flags.PARAMETERIZED); + tSymbol.type.flags |= Flags.PARAMETERIZED; td.symbol = tSymbol; return tSymbol.type; @@ -1549,8 +1570,8 @@ private BType resolveTypeDesc(BLangUserDefinedType td, ResolverData data) { if (symbol.kind == SymbolKind.TYPE_DEF && !Symbols.isFlagOn(symbol.flags, Flags.ANONYMOUS)) { BType referenceType = ((BTypeDefinitionSymbol) symbol).referenceType; - referenceType.addFlags(symbol.type.getFlags()); - referenceType.tsymbol.flags |= symbol.type.getFlags(); + referenceType.flags |= symbol.type.flags; + referenceType.tsymbol.flags |= symbol.type.flags; return referenceType; } @@ -1584,8 +1605,8 @@ private BType resolveTypeDesc(BLangUserDefinedType td, ResolverData data) { td.symbol = symbol; if (symbol.kind == SymbolKind.TYPE_DEF && !Symbols.isFlagOn(symbol.flags, Flags.ANONYMOUS)) { BType referenceType = ((BTypeDefinitionSymbol) symbol).referenceType; - referenceType.addFlags(symbol.type.getFlags()); - referenceType.tsymbol.flags |= symbol.type.getFlags(); + referenceType.flags |= symbol.type.flags; + referenceType.tsymbol.flags |= symbol.type.flags; return referenceType; } return resolvedType; @@ -1603,43 +1624,50 @@ private BType resolveTypeDesc(BLangBuiltInRefTypeNode td, SymbolEnv symEnv) { return visitBuiltInTypeNode(td, data, td.typeKind); } - protected BType resolveSingletonType(BLangFiniteTypeNode td, SymbolEnv symEnv) { + private BType resolveSingletonType(BLangFiniteTypeNode td, SymbolEnv symEnv) { BTypeSymbol finiteTypeSymbol = Symbols.createTypeSymbol(SymTag.FINITE_TYPE, (Flags.asMask(EnumSet.of(Flag.PUBLIC))), Names.EMPTY, symEnv.enclPkg.symbol.pkgID, null, symEnv.scope.owner, td.pos, BUILTIN); - List vs = td.valueSpace; - SemNamedType[] valueSpace = new SemNamedType[vs.size()]; - for (int i = 0; i < vs.size(); i++) { - BLangExpression exprOrLiteral = vs.get(i); - BType type = blangTypeUpdate(exprOrLiteral); + // In case we encounter unary expressions in finite type, we will be replacing them with numeric literals. + replaceUnaryExprWithNumericLiteral(td); + + BFiniteType finiteType = new BFiniteType(finiteTypeSymbol); + for (BLangExpression literal : td.valueSpace) { + BType type = blangTypeUpdate(literal); if (type != null && type.tag == TypeTags.SEMANTIC_ERROR) { return type; } if (type != null) { - exprOrLiteral.setBType(symTable.getTypeFromTag(type.tag)); - } - - if (SemTypeHelper.isSimpleOrString(exprOrLiteral.getBType().getKind())) { - if (exprOrLiteral.getKind() == NodeKind.UNARY_EXPR) { - exprOrLiteral = Types.constructNumericLiteralFromUnaryExpr((BLangUnaryExpr) exprOrLiteral); - // Replacing here as Semantic Analyzer BLangFiniteTypeNode visit may not invoke for all finite nodes - td.valueSpace.set(i, exprOrLiteral); - } - - SemType s = SemTypeHelper.resolveSingletonType((BLangLiteral) exprOrLiteral); - valueSpace[i] = new SemNamedType(s, Optional.ofNullable(exprOrLiteral.toString())); - } else { - throw new IllegalStateException("non-sem value found in BLangFiniteType!"); + literal.setBType(symTable.getTypeFromTag(type.tag)); } + finiteType.addValue(literal); } - - BFiniteType finiteType = new BFiniteType(finiteTypeSymbol, valueSpace); finiteTypeSymbol.type = finiteType; td.setBType(finiteType); return finiteType; } + private void replaceUnaryExprWithNumericLiteral(BLangFiniteTypeNode finiteTypeNode) { + List valueSpace = finiteTypeNode.valueSpace; + for (int i = 0; i < valueSpace.size(); i++) { + BLangExpression value; + NodeKind valueKind; + value = valueSpace.get(i); + valueKind = value.getKind(); + + if (valueKind == NodeKind.UNARY_EXPR) { + BLangUnaryExpr unaryExpr = (BLangUnaryExpr) value; + if (unaryExpr.expr.getKind() == NodeKind.NUMERIC_LITERAL) { + // Replacing unary expression with numeric literal type for + and - numeric values. + BLangNumericLiteral newNumericLiteral = + Types.constructNumericLiteralFromUnaryExpr(unaryExpr); + valueSpace.set(i, newNumericLiteral); + } + } + } + } + private BType blangTypeUpdate(BLangExpression expression) { BType type; switch (expression.getKind()) { @@ -1679,7 +1707,7 @@ private BType resolveTypeDesc(BLangTableTypeNode td, ResolverData data) { SymbolEnv symEnv = data.env; BType type = resolveTypeDesc(symEnv, data.typeDefinition, data.depth + 1, td.type, data); - BTableType tableType = new BTableType(symTable.typeEnv(), symTable.empty, null); + BTableType tableType = new BTableType(TypeTags.TABLE, symTable.empty, null); BTypeSymbol typeSymbol = type.tsymbol; tableType.tsymbol = Symbols.createTypeSymbol(SymTag.TYPE, Flags.asMask(EnumSet.noneOf(Flag.class)), typeSymbol.name, typeSymbol.originalName, symEnv.enclPkg.symbol.pkgID, @@ -1735,7 +1763,7 @@ private BType resolveTypeDesc(BLangStreamType td, ResolverData data) { BType error = td.error != null ? resolveTypeDesc(symEnv, data.typeDefinition, data.depth + 1, td.error, data) : symTable.nilType; - BStreamType streamType = new BStreamType(symTable.typeEnv(), TypeTags.STREAM, symTable.empty, error, null); + BStreamType streamType = new BStreamType(TypeTags.STREAM, symTable.empty, error, null); BTypeSymbol typeSymbol = type.tsymbol; streamType.tsymbol = Symbols.createTypeSymbol(typeSymbol.tag, typeSymbol.flags, typeSymbol.name, typeSymbol.originalName, symEnv.enclPkg.symbol.pkgID, streamType, @@ -1794,7 +1822,7 @@ public BType defineTypeDefinition(BLangTypeDefinition typeDefinition, BType reso typeDefSymbol.pkgID, typeDefSymbol.type, typeDefSymbol.owner, typeDefSymbol.pos, typeDefSymbol.origin); typeSymbol.markdownDocumentation = typeDefSymbol.markdownDocumentation; ((BTypeDefinitionSymbol) typeDefSymbol).referenceType = new BTypeReferenceType(resolvedType, typeSymbol, - typeDefSymbol.type.getFlags()); + typeDefSymbol.type.flags); if (resolvedType == symTable.semanticError && resolvedType.tsymbol == null) { typeDefinition.symbol = typeDefSymbol; @@ -1866,7 +1894,7 @@ public BType defineTypeDefinition(BLangTypeDefinition typeDefinition, BType reso dlog.error(typeDefinition.pos, DiagnosticErrorCode.TYPE_PARAM_OUTSIDE_LANG_MODULE); } } - resolvedType.addFlags(typeDefSymbol.flags); + resolvedType.flags |= typeDefSymbol.flags; typeDefinition.symbol = typeDefSymbol; @@ -1983,6 +2011,12 @@ private void defineConstant(SymbolEnv symEnv, Map modTable, B BConstantSymbol constantSymbol = symEnter.getConstantSymbol(constant); constant.symbol = constantSymbol; BLangTypeDefinition typeDef = constant.associatedTypeDefinition; + NodeKind nodeKind = constant.expr.getKind(); + boolean isLiteral = nodeKind == NodeKind.LITERAL || nodeKind == NodeKind.NUMERIC_LITERAL + || nodeKind == NodeKind.UNARY_EXPR; + if (typeDef != null && isLiteral) { + resolveTypeDefinition(symEnv, modTable, typeDef, 0); + } if (constant.typeNode != null) { // Type node is available. ResolverData data = new ResolverData(); @@ -2002,17 +2036,6 @@ private void defineConstant(SymbolEnv symEnv, Map modTable, B BType resolvedType = constantTypeChecker.checkConstExpr(constant.expr, staticType, data); data.anonTypeNameSuffixes.pop(); - NodeKind nodeKind = constant.expr.getKind(); - boolean isLiteral = nodeKind == NodeKind.LITERAL || nodeKind == NodeKind.NUMERIC_LITERAL - || nodeKind == NodeKind.UNARY_EXPR; - if (typeDef != null && isLiteral) { - typeDef.typeNode.setBType(resolvedType); - // Define the typeDefinition. Add symbol, flags etc. - resolvedType = defineTypeDefinition(typeDef, resolvedType, symEnv); - typeDef.setBType(resolvedType); - typeDef.cycleDepth = -1; - } - if (resolvedType == symTable.semanticError) { // Constant expression contains errors. constant.setBType(symTable.semanticError); @@ -2036,7 +2059,7 @@ private void defineConstant(SymbolEnv symEnv, Map modTable, B // Update the final type in necessary fields. constantSymbol.type = intersectionType; if (intersectionType.tag == TypeTags.FINITE) { - constantSymbol.literalType = singleShapeBroadType(intersectionType.semType(), symTable).get(); + constantSymbol.literalType = ((BFiniteType) intersectionType).getValueSpace().iterator().next().getBType(); } else { constantSymbol.literalType = intersectionType; } 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 308347df0d2b..de443d69b5be 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 @@ -20,25 +20,7 @@ import io.ballerina.runtime.api.flags.SymbolFlags; import io.ballerina.tools.diagnostics.DiagnosticCode; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.Atom; -import io.ballerina.types.BasicTypeBitSet; -import io.ballerina.types.Bdd; -import io.ballerina.types.CombinedRange; -import io.ballerina.types.ComplexSemType; -import io.ballerina.types.Context; -import io.ballerina.types.Core; -import io.ballerina.types.Env; -import io.ballerina.types.ListMemberTypes; -import io.ballerina.types.MappingAtomicType; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypePair; -import io.ballerina.types.SemTypes; -import io.ballerina.types.SubtypeData; -import io.ballerina.types.subtypedata.BddAllOrNothing; -import io.ballerina.types.subtypedata.BddNode; -import io.ballerina.types.subtypedata.IntSubtype; -import io.ballerina.types.subtypedata.Range; +import org.ballerinalang.model.Name; import org.ballerinalang.model.TreeBuilder; import org.ballerinalang.model.elements.Flag; import org.ballerinalang.model.elements.PackageID; @@ -59,7 +41,10 @@ import org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableTypeSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BObjectTypeSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BRecordTypeSymbol; +import org.wso2.ballerinalang.compiler.semantics.model.symbols.BResourceFunction; +import org.wso2.ballerinalang.compiler.semantics.model.symbols.BResourcePathSegmentSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BStructureTypeSymbol; +import org.wso2.ballerinalang.compiler.semantics.model.symbols.BSymbol; 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.SymTag; @@ -67,16 +52,20 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BAnyType; import org.wso2.ballerinalang.compiler.semantics.model.types.BAnydataType; import org.wso2.ballerinalang.compiler.semantics.model.types.BArrayType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BBuiltInRefType; import org.wso2.ballerinalang.compiler.semantics.model.types.BErrorType; import org.wso2.ballerinalang.compiler.semantics.model.types.BField; import org.wso2.ballerinalang.compiler.semantics.model.types.BFiniteType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BFutureType; import org.wso2.ballerinalang.compiler.semantics.model.types.BIntersectionType; import org.wso2.ballerinalang.compiler.semantics.model.types.BInvokableType; import org.wso2.ballerinalang.compiler.semantics.model.types.BJSONType; 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.BParameterizedType; import org.wso2.ballerinalang.compiler.semantics.model.types.BReadonlyType; import org.wso2.ballerinalang.compiler.semantics.model.types.BRecordType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BSequenceType; import org.wso2.ballerinalang.compiler.semantics.model.types.BStreamType; import org.wso2.ballerinalang.compiler.semantics.model.types.BTableType; import org.wso2.ballerinalang.compiler.semantics.model.types.BTupleMember; @@ -84,9 +73,10 @@ 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.BTypeVisitor; +import org.wso2.ballerinalang.compiler.semantics.model.types.BTypedescType; import org.wso2.ballerinalang.compiler.semantics.model.types.BUnionType; import org.wso2.ballerinalang.compiler.semantics.model.types.BXMLType; -import org.wso2.ballerinalang.compiler.semantics.model.types.SemNamedType; import org.wso2.ballerinalang.compiler.tree.BLangFunction; import org.wso2.ballerinalang.compiler.tree.BLangNode; import org.wso2.ballerinalang.compiler.tree.BLangTypeDefinition; @@ -112,12 +102,13 @@ import org.wso2.ballerinalang.compiler.tree.types.BLangRecordTypeNode; import org.wso2.ballerinalang.compiler.util.BArrayState; import org.wso2.ballerinalang.compiler.util.CompilerContext; +import org.wso2.ballerinalang.compiler.util.CompilerUtils; import org.wso2.ballerinalang.compiler.util.ImmutableTypeCloner; -import org.wso2.ballerinalang.compiler.util.Name; import org.wso2.ballerinalang.compiler.util.Names; import org.wso2.ballerinalang.compiler.util.NumericLiteralSupport; import org.wso2.ballerinalang.compiler.util.TypeDefBuilderHelper; import org.wso2.ballerinalang.compiler.util.TypeTags; +import org.wso2.ballerinalang.compiler.util.Unifier; import org.wso2.ballerinalang.util.Flags; import org.wso2.ballerinalang.util.Lists; @@ -142,11 +133,6 @@ import java.util.Set; import static io.ballerina.runtime.api.constants.RuntimeConstants.UNDERSCORE; -import static io.ballerina.types.BasicTypeCode.BT_OBJECT; -import static io.ballerina.types.Core.combineRanges; -import static io.ballerina.types.Core.createIsolatedObject; -import static io.ballerina.types.Core.createServiceObject; -import static io.ballerina.types.Core.isSubtypeSimple; import static org.ballerinalang.model.symbols.SymbolOrigin.SOURCE; import static org.ballerinalang.model.symbols.SymbolOrigin.VIRTUAL; import static org.wso2.ballerinalang.compiler.semantics.model.SymbolTable.BBYTE_MAX_VALUE; @@ -160,9 +146,11 @@ import static org.wso2.ballerinalang.compiler.semantics.model.SymbolTable.UNSIGNED16_MAX_VALUE; import static org.wso2.ballerinalang.compiler.semantics.model.SymbolTable.UNSIGNED32_MAX_VALUE; import static org.wso2.ballerinalang.compiler.semantics.model.SymbolTable.UNSIGNED8_MAX_VALUE; +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.UNION; +import static org.wso2.ballerinalang.compiler.util.TypeTags.isSimpleBasicType; /** * This class consists of utility methods which operate on types. @@ -175,15 +163,17 @@ public class Types { private static final CompilerContext.Key TYPES_KEY = new CompilerContext.Key<>(); + private final Unifier unifier; private final SymbolTable symTable; private final SymbolResolver symResolver; private final BLangDiagnosticLog dlog; private final Names names; private int finiteTypeCount = 0; + private final BUnionType expandedXMLBuiltinSubtypes; private final BLangAnonymousModelHelper anonymousModelHelper; + private final int recordCount = 0; private SymbolEnv env; - protected final Context semTypeCtx; - + private boolean ignoreObjectTypeIds = false; private static final String BASE_16 = "base16"; private static final BigDecimal DECIMAL_MAX = @@ -195,8 +185,6 @@ public class Types { private static final BigDecimal MIN_DECIMAL_MAGNITUDE = new BigDecimal("1.000000000000000000000000000000000e-6143", MathContext.DECIMAL128); - public static final String AND_READONLY_SUFFIX = " & readonly"; - public static Types getInstance(CompilerContext context) { Types types = context.get(TYPES_KEY); if (types == null) { @@ -207,20 +195,29 @@ public static Types getInstance(CompilerContext context) { } public Types(CompilerContext context) { - this(context, new Env()); - } - - public Types(CompilerContext context, Env typeEnv) { context.put(TYPES_KEY, this); - this.semTypeCtx = Context.from(typeEnv); this.symTable = SymbolTable.getInstance(context); this.symResolver = SymbolResolver.getInstance(context); this.dlog = BLangDiagnosticLog.getInstance(context); this.names = Names.getInstance(context); + this.expandedXMLBuiltinSubtypes = BUnionType.create(null, + symTable.xmlElementType, symTable.xmlCommentType, + symTable.xmlPIType, symTable.xmlTextType); + this.unifier = new Unifier(); this.anonymousModelHelper = BLangAnonymousModelHelper.getInstance(context); } + public List checkTypes(BLangExpression node, + List actualTypes, + List expTypes) { + List resTypes = new ArrayList<>(); + for (int i = 0; i < actualTypes.size(); i++) { + resTypes.add(checkType(node, actualTypes.get(i), expTypes.size() > i ? expTypes.get(i) : symTable.noType)); + } + return resTypes; + } + public BType checkType(BLangExpression node, BType actualType, BType expType) { @@ -233,7 +230,7 @@ public BType addNilForNillableAccessType(BType actualType) { return actualType; } - return BUnionType.create(typeEnv(), null, actualType, symTable.nilType); + return BUnionType.create(null, actualType, symTable.nilType); } public BType checkType(BLangExpression expr, @@ -257,10 +254,6 @@ public boolean typeIncompatible(Location pos, BType actualType, BType expType) { return checkType(pos, actualType, expType, DiagnosticErrorCode.INCOMPATIBLE_TYPES) == symTable.semanticError; } - public SemType getErrorIntersection(SemType t) { - return SemTypes.intersect(t, PredefinedType.ERROR); - } - public BType getErrorTypes(BType bType) { bType = Types.getImpliedType(bType); if (bType == null) { @@ -296,8 +289,7 @@ public BType getErrorTypes(BType bType) { return errorType; } - return errTypes.size() == 1 ? errTypes.iterator().next() : - BUnionType.create(typeEnv(), null, errTypes); + return errTypes.size() == 1 ? errTypes.iterator().next() : BUnionType.create(null, errTypes); } public BType checkType(Location pos, @@ -320,100 +312,131 @@ public BType checkType(Location pos, } public boolean isLaxFieldAccessAllowed(BType type) { - if (type.tag == TypeTags.SEMANTIC_ERROR) { - return false; - } - return isLaxFieldAccessAllowed(type.semType()); + type = Types.getImpliedType(type); + Set visited = new HashSet<>(); + return isLaxType(type, visited) == 1 || isAssignable(type, symTable.xmlType); } - public boolean isLaxFieldAccessAllowed(SemType t) { - if (Core.isNever(t)) { - return false; + // TODO : clean + public int isLaxType(BType type, Set visited) { + type = getImpliedType(type); + if (!visited.add(type)) { + return -1; } - return isSubtypeSimple(t, PredefinedType.XML) || isLaxType(t); - } - - /** - * Checks if the type is a lax type. - *

- * Rules: - *

    - *
  • json and readonly-json are lax
  • - *
  • map<T> is lax if T is lax
  • - *
  • U = T1|T2...|Tn is lax, if Ti is lax for all i.
  • - *
- * - * @param t type to be checked - * @return true if t is lax - */ - private boolean isLaxType(SemType t) { - SemType json = Core.createJson(semTypeCtx); - if (SemTypes.isSameType(semTypeCtx, t, json) || - SemTypes.isSameType(semTypeCtx, t, SemTypes.intersect(json, PredefinedType.VAL_READONLY))) { - return true; + switch (type.tag) { + case TypeTags.JSON: + return 1; + case TypeTags.MAP: + return isLaxType(((BMapType) type).constraint, visited); + case TypeTags.UNION: + if (isSameType(type, symTable.jsonType)) { + visited.add(type); + return 1; + } + boolean atleastOneLaxType = false; + for (BType member : ((BUnionType) type).getMemberTypes()) { + int result = isLaxType(member, visited); + if (result == -1) { + continue; + } + if (result == 0) { + return 0; + } + atleastOneLaxType = true; + } + return atleastOneLaxType ? 1 : 0; } + return 0; + } - Optional> optMatList = Core.mappingAtomicTypesInUnion(semTypeCtx, t); - if (optMatList.isEmpty()) { - return false; + public boolean isLaxType(BType type, Map visited) { + type = getImpliedType(type); + if (visited.containsKey(type)) { + return visited.get(type); } + switch (type.tag) { + case TypeTags.JSON: + visited.put(type, true); + return true; + case TypeTags.MAP: + boolean result = isLaxType(((BMapType) type).constraint, visited); + visited.put(type, result); + return result; + case TypeTags.UNION: + // TODO: remove + if (type == symTable.jsonType || isSameType(type, symTable.jsonType)) { + visited.put(type, true); + return true; + } + for (BType member : ((BUnionType) type).getMemberTypes()) { + if (!isLaxType(member, visited)) { + visited.put(type, false); + return false; + } + } + visited.put(type, true); + return true; + } + visited.put(type, false); + return false; + } - List matList = optMatList.get(); - return matList.stream().allMatch(mat -> mat.names().length == 0 && isLaxType(Core.cellInnerVal(mat.rest()))); + public boolean isSameType(BType source, BType target) { + return isSameType(source, target, new HashSet<>()); } - boolean isUniqueType(Iterable typeList, BType type) { - type = Types.getImpliedType(type); - boolean isRecord = type.tag == TypeTags.RECORD; + public boolean isSameOrderedType(BType source, BType target) { + return isSameOrderedType(source, target, new HashSet<>()); + } - for (BType bType : typeList) { - bType = Types.getImpliedType(bType); - if (isRecord) { - // Seems defaultable values too are considered when checking uniqueness. - if (type == bType) { - return false; - } - } else if (isSameType(type, bType)) { - return false; - } + private boolean isSameOrderedType(BType source, BType target, Set unresolvedTypes) { + source = getImpliedType(source); + target = getImpliedType(target); + if (isNil(source) || isNil(target)) { + // If type T is ordered, then type T? Is also ordered. + // Both source and target are ordered types since they were checked in previous stage. + // Ex. Let take target -> T, source -> (). T? is ordered type where the static type of both operands belong. + return true; } - return true; + if (!unresolvedTypes.add(new TypePair(source, target))) { + return true; + } + BTypeVisitor orderedTypeVisitor = new BOrderedTypeVisitor(unresolvedTypes); + return target.accept(orderedTypeVisitor, source); } - public boolean isSameType(BType source, BType target) { - return isSameType(source.semType(), target.semType()); + public boolean isPureType(BType type) { + IsPureTypeUniqueVisitor visitor = new IsPureTypeUniqueVisitor(); + return visitor.visit(type); } - public boolean isSameTypeIncludingTags(BType source, BType target) { - if (source.tag != target.tag) { - return false; - } + public boolean isAnydata(BType type) { + IsAnydataUniqueVisitor visitor = new IsAnydataUniqueVisitor(); + return visitor.visit(type); + } - if (source.tag == UNION) { - boolean notSameType = ((BUnionType) source).getMemberTypes() - .stream() - .map(sT -> ((BUnionType) target).getMemberTypes() - .stream() - .anyMatch(it -> Types.getReferredType(it).tag == Types.getReferredType(sT).tag)) - .anyMatch(foundSameType -> !foundSameType); - if (notSameType) { - return false; + private boolean isSameType(BType source, BType target, Set unresolvedTypes) { + // If we encounter two types that we are still resolving, then skip it. + // This is done to avoid recursive checking of the same type. + TypePair pair = null; + if (!isValueType(source) && !isValueType(target)) { + pair = new TypePair(source, target); + if (!unresolvedTypes.add(pair)) { + return true; } } - return isSameType(source.semType(), target.semType()); - } + BTypeVisitor sameTypeVisitor = new BSameTypeVisitor(unresolvedTypes, this::isSameType); - public boolean isSameType(SemType source, SemType target) { - return SemTypes.isSameType(semTypeCtx, source, target); - } + if (target.accept(sameTypeVisitor, source)) { + return true; + } - public SemType anydata() { - return Core.createAnydata(semTypeCtx); - } + if (pair != null) { + unresolvedTypes.remove(pair); + } - public boolean isAnydata(SemType t) { - return isSubtype(t, anydata()); + return false; } public boolean isValueType(BType type) { @@ -440,16 +463,49 @@ boolean isBasicNumericType(BType bType) { return type.tag < TypeTags.STRING || TypeTags.isIntegerTypeTag(type.tag); } + boolean finiteTypeContainsNumericTypeValues(BFiniteType finiteType) { + return finiteType.getValueSpace().stream().anyMatch(valueExpr -> isBasicNumericType(valueExpr.getBType())); + } + public boolean containsErrorType(BType bType) { - return SemTypeHelper.containsBasicType(bType, PredefinedType.ERROR); + BType type = getImpliedType(bType); + if (type.tag == TypeTags.UNION) { + return ((BUnionType) type).getMemberTypes().stream() + .anyMatch(this::containsErrorType); + } + + if (type.tag == TypeTags.READONLY) { + return true; + } + + return type.tag == TypeTags.ERROR; } public boolean containsNilType(BType bType) { - return SemTypeHelper.containsBasicType(bType, PredefinedType.NIL); + BType type = getImpliedType(bType); + if (type.tag == TypeTags.UNION) { + for (BType memberType : ((BUnionType) type).getMemberTypes()) { + if (containsNilType(memberType)) { + return true; + } + } + return false; + } + + if (type.tag == TypeTags.READONLY) { + return true; + } + + return type.tag == TypeTags.NIL; } public boolean isSubTypeOfList(BType bType) { - return SemTypeHelper.isSubtypeSimpleNotNever(bType, PredefinedType.LIST); + BType type = getImpliedType(bType); + if (type.tag != TypeTags.UNION) { + return isSubTypeOfBaseType(type, TypeTags.ARRAY) || isSubTypeOfBaseType(type, TypeTags.TUPLE); + } + + return ((BUnionType) type).getMemberTypes().stream().allMatch(this::isSubTypeOfList); } BType resolvePatternTypeFromMatchExpr(BLangErrorBindingPattern errorBindingPattern, BLangExpression matchExpr, @@ -680,11 +736,31 @@ public BType resolvePatternTypeFromMatchExpr(BLangMappingBindingPattern mappingB } private boolean containsAnyType(BType type) { - return SemTypeHelper.containsType(semTypeCtx, type, PredefinedType.ANY); + type = getImpliedType(type); + if (type.tag != TypeTags.UNION) { + return type.tag == TypeTags.ANY; + } + + for (BType memberTypes : ((BUnionType) type).getMemberTypes()) { + if (getImpliedType(memberTypes).tag == TypeTags.ANY) { + return true; + } + } + return false; } private boolean containsAnyDataType(BType type) { - return SemTypeHelper.containsType(semTypeCtx, type, Core.createAnydata(semTypeCtx)); + type = getImpliedType(type); + if (type.tag != TypeTags.UNION) { + return type.tag == TypeTags.ANYDATA; + } + + for (BType memberTypes : ((BUnionType) type).getMemberTypes()) { + if (getImpliedType(memberTypes).tag == TypeTags.ANYDATA) { + return true; + } + } + return false; } BType mergeTypes(BType typeFirst, BType typeSecond) { @@ -703,21 +779,17 @@ BType mergeTypes(BType typeFirst, BType typeSecond) { if (isSameBasicType(typeFirst, typeSecond)) { return typeFirst; } - return BUnionType.create(typeEnv(), null, typeFirst, typeSecond); - } - - public boolean isSubTypeOfMapping(SemType s) { - return SemTypes.isSubtypeSimpleNotNever(s, PredefinedType.MAPPING); + return BUnionType.create(null, typeFirst, typeSecond); } - public boolean isSubTypeOfBaseType(BType bType, BasicTypeBitSet bbs) { - return SemTypeHelper.isSubtypeSimpleNotNever(bType, bbs); + public boolean isSubTypeOfMapping(BType bType) { + BType type = getImpliedType(bType); + if (type.tag != TypeTags.UNION) { + return isSubTypeOfBaseType(type, TypeTags.MAP) || isSubTypeOfBaseType(type, TypeTags.RECORD); + } + return ((BUnionType) type).getMemberTypes().stream().allMatch(this::isSubTypeOfMapping); } - /** - * @deprecated Use {@link #isSubTypeOfBaseType(BType, BasicTypeBitSet)} instead. - */ - @Deprecated public boolean isSubTypeOfBaseType(BType bType, int baseTypeTag) { BType type = getImpliedType(bType); @@ -756,1027 +828,3032 @@ private boolean isUnionMemberTypesSubTypeOfBaseType(LinkedHashSet memberT /** * Checks whether source type is assignable to the target type. + *

+ * Source type is assignable to the target type if, + * 1) the target type is any and the source type is not a value type. + * 2) there exists an implicit cast symbol from source to target. + * 3) both types are JSON and the target constraint is no type. + * 4) both types are array type and both array types are assignable. + * 5) both types are MAP and the target constraint is any type or constraints are structurally equivalent. * * @param source type. * @param target type. * @return true if source type is assignable to the target type. */ public boolean isAssignable(BType source, BType target) { - return isSubtype(source.semType(), target.semType()); + return isAssignable(source, target, new HashSet<>()); } public boolean isAssignableIgnoreObjectTypeIds(BType source, BType target) { - SemType s = typeIgnoringObjectTypeIds(source.semType()); - SemType t = typeIgnoringObjectTypeIds(target.semType()); - return isSubtype(s, t); + this.ignoreObjectTypeIds = true; + boolean result = isAssignable(source, target); + this.ignoreObjectTypeIds = false; + return result; } - public SemType typeIgnoringObjectTypeIds(SemType t) { - SubtypeData objSubTypeData = Core.subtypeData(t, BT_OBJECT); - if (!(objSubTypeData instanceof Bdd b)) { - return t; - } - Bdd bdd = replaceObjectDistinctAtoms(b); - SemType newObjSemType = Core.createBasicSemType(BT_OBJECT, bdd); - SemType diff = Core.diff(t, PredefinedType.OBJECT); - return Core.union(diff, newObjSemType); - } + private boolean isAssignable(BType source, BType target, Set unresolvedTypes) { - /** - * Replaces all distinct atoms in object type's bdd with full object equivalent atom. - * ({@link PredefinedType#ATOM_MAPPING_OBJECT}). - *
- * This is to suppress effect coming from distinct atoms. - * The return bdd will be equivalent to object bdd with no distinct atoms. - * - * @param b a bdd belong to object type - * @return bdd with no distinct atoms - */ - private Bdd replaceObjectDistinctAtoms(Bdd b) { - if (b instanceof BddAllOrNothing) { - return b; + if (isSameType(source, target)) { + return true; } - BddNode bn = (BddNode) b; - Atom atom = bn.atom(); - if (bn.atom().kind() == Atom.Kind.DISTINCT_ATOM) { - atom = PredefinedType.ATOM_MAPPING_OBJECT; + int sourceTag = source.tag; + int targetTag = target.tag; + + if (sourceTag == TypeTags.TYPEREFDESC || targetTag == TypeTags.TYPEREFDESC) { + return isAssignable(getImpliedType(source), getImpliedType(target), + unresolvedTypes); } - Bdd left = replaceObjectDistinctAtoms(bn.left()); - Bdd middle = replaceObjectDistinctAtoms(bn.middle()); - Bdd right = replaceObjectDistinctAtoms(bn.right()); - return BddNode.create(atom, left, middle, right); - } - public boolean isSubtype(SemType t1, SemType t2) { - return SemTypes.isSubtype(semTypeCtx, t1, t2); - } + if (isNeverTypeOrStructureTypeWithARequiredNeverMember(source)) { + return true; + } - public boolean isSubtype(BType t1, SemType t2) { - return SemTypeHelper.isSubtype(semTypeCtx, t1, t2); - } + if (sourceTag == TypeTags.SEQUENCE) { + BSequenceType seqType = (BSequenceType) source; + if (targetTag == TypeTags.ARRAY) { + return isAssignable(seqType.elementType, ((BArrayType) target).eType, unresolvedTypes); + } + } - BField getTableConstraintField(BType constraintType, String fieldName) { - constraintType = getImpliedType(constraintType); - switch (constraintType.tag) { - case TypeTags.RECORD: - Map fieldList = ((BRecordType) constraintType).getFields(); - return fieldList.get(fieldName); - case TypeTags.UNION: - BUnionType unionType = (BUnionType) constraintType; - Set memTypes = unionType.getMemberTypes(); - List fields = memTypes.stream().map(type -> getTableConstraintField(type, fieldName)) - .filter(Objects::nonNull).toList(); + if (!Symbols.isFlagOn(source.flags, Flags.PARAMETERIZED) && + !isInherentlyImmutableType(target) && Symbols.isFlagOn(target.flags, Flags.READONLY) && + !isInherentlyImmutableType(source) && isMutable(source)) { + return false; + } - if (fields.size() != memTypes.size()) { - return null; - } + if (sourceTag == TypeTags.INTERSECTION) { + return isAssignable(((BIntersectionType) source).effectiveType, + targetTag != TypeTags.INTERSECTION ? target : + ((BIntersectionType) target).effectiveType, unresolvedTypes); + } - if (fields.stream().allMatch(field -> isAssignable(field.type, fields.get(0).type) && - isAssignable(fields.get(0).type, field.type))) { - return fields.get(0); - } + if (targetTag == TypeTags.INTERSECTION) { + return isAssignable(source, ((BIntersectionType) target).effectiveType, unresolvedTypes); } - return null; - } + if (sourceTag == TypeTags.PARAMETERIZED_TYPE) { + return isParameterizedTypeAssignable(source, target, unresolvedTypes); + } - public boolean isInherentlyImmutableType(BType type) { - type = getImpliedType(type); - if (isValueType(type)) { + if (sourceTag == TypeTags.BYTE && targetTag == TypeTags.INT) { return true; } - return switch (type.tag) { - case TypeTags.XML_TEXT, - TypeTags.FINITE, // Assuming a finite type will only have members from simple basic types. - TypeTags.READONLY, - TypeTags.NIL, - TypeTags.NEVER, - TypeTags.ERROR, - TypeTags.INVOKABLE, - TypeTags.TYPEDESC, - TypeTags.HANDLE, - TypeTags.REGEXP -> true; - case TypeTags.XML -> getImpliedType(((BXMLType) type).constraint).tag == TypeTags.NEVER; - default -> false; - }; - } + if (TypeTags.isXMLTypeTag(sourceTag) && TypeTags.isXMLTypeTag(targetTag)) { + return isXMLTypeAssignable(source, target, unresolvedTypes); + } - /** - * Retrieve the referred type if a given type is a type reference type or - * retrieve the effective type if the given type is an intersection type. - * - * @param type type to retrieve the implied type - * @return the implied type if provided with a type reference type or an intersection type, - * else returns the original type - */ - public static BType getImpliedType(BType type) { - type = getReferredType(type); - if (type != null && type.tag == TypeTags.INTERSECTION) { - return getImpliedType(((BIntersectionType) type).effectiveType); + if (sourceTag == TypeTags.CHAR_STRING && targetTag == TypeTags.STRING) { + return true; } - return type; - } + if (sourceTag == TypeTags.ERROR && targetTag == TypeTags.ERROR) { + return isErrorTypeAssignable((BErrorType) source, (BErrorType) target, unresolvedTypes); + } else if (sourceTag == TypeTags.ERROR && targetTag == TypeTags.ANY) { + return false; + } - public static BType getReferredType(BType type) { - if (type != null && type.tag == TypeTags.TYPEREFDESC) { - return getReferredType(((BTypeReferenceType) type).referredType); + if (sourceTag == TypeTags.NIL && (isNullable(target) || targetTag == TypeTags.JSON)) { + return true; } - return type; - } + // TODO: Remove the isValueType() check + if (targetTag == TypeTags.ANY && !containsErrorType(source) && !isValueType(source)) { + return true; + } - public BLangExpression addConversionExprIfRequired(BLangExpression expr, BType lhsType) { - if (lhsType.tag == TypeTags.NONE) { - return expr; + if (targetTag == TypeTags.ANYDATA && !containsErrorType(source) && isAnydata(source)) { + return true; } - BType rhsType = expr.getBType(); + if (targetTag == TypeTags.READONLY) { + if ((isInherentlyImmutableType(source) || Symbols.isFlagOn(source.flags, Flags.READONLY))) { + return true; + } + if (isAssignable(source, symTable.anyAndReadonlyOrError, unresolvedTypes)) { + return true; + } + } - if (lhsType.tag == TypeTags.TYPEREFDESC && rhsType.tag != TypeTags.TYPEREFDESC) { - return addConversionExprIfRequired(expr, Types.getReferredType(lhsType)); + if (sourceTag == TypeTags.READONLY && isAssignable(symTable.anyAndReadonlyOrError, target, unresolvedTypes)) { + return true; } - if (rhsType.tag == lhsType.tag && isSameType(rhsType, lhsType)) { - return expr; + if (targetTag == TypeTags.MAP && sourceTag == TypeTags.RECORD) { + BRecordType recordType = (BRecordType) source; + return isAssignableRecordType(recordType, target, unresolvedTypes); } - setImplicitCastExpr(expr, rhsType, lhsType); - if (expr.impConversionExpr != null) { - BLangExpression impConversionExpr = expr.impConversionExpr; - expr.impConversionExpr = null; - return impConversionExpr; + if (targetTag == TypeTags.RECORD && sourceTag == TypeTags.MAP) { + return isAssignableMapType((BMapType) source, (BRecordType) target); } - if (lhsType.tag == TypeTags.JSON && rhsType.tag == TypeTags.NIL) { - return expr; + if (targetTag == TypeTags.TYPEDESC && sourceTag == TypeTags.TYPEDESC) { + return isAssignable(((BTypedescType) source).constraint, (((BTypedescType) target).constraint), + unresolvedTypes); } - if (lhsType.tag == TypeTags.NIL && rhsType.isNullable()) { - return expr; + if (targetTag == TypeTags.TABLE && sourceTag == TypeTags.TABLE) { + return isAssignableTableType((BTableType) source, (BTableType) target, unresolvedTypes); } - if (lhsType.tag == TypeTags.ARRAY && rhsType.tag == TypeTags.TUPLE) { - return expr; + if (targetTag == TypeTags.STREAM && sourceTag == TypeTags.STREAM) { + return isAssignableStreamType((BStreamType) source, (BStreamType) target, unresolvedTypes); } - // Create a type cast expression - BLangTypeConversionExpr conversionExpr = (BLangTypeConversionExpr) - TreeBuilder.createTypeConversionNode(); - conversionExpr.expr = expr; - conversionExpr.targetType = lhsType; - conversionExpr.setBType(lhsType); - conversionExpr.pos = expr.pos; - conversionExpr.checkTypes = false; - conversionExpr.internal = true; - return conversionExpr; - } + if (isBuiltInTypeWidenPossible(source, target) == TypeTestResult.TRUE) { + return true; + } - boolean isSelectivelyImmutableType(BType type, PackageID packageID) { - return isSelectivelyImmutableType(type, new HashSet<>(), false, packageID); - } + if (sourceTag == TypeTags.FINITE) { + return isFiniteTypeAssignable((BFiniteType) source, target, unresolvedTypes); + } - boolean isSelectivelyImmutableType(BType type, boolean forceCheck, PackageID packageID) { - return isSelectivelyImmutableType(type, new HashSet<>(), forceCheck, packageID); - } + if ((targetTag == TypeTags.UNION || sourceTag == TypeTags.UNION) && + isAssignableToUnionType(source, target, unresolvedTypes)) { + return true; + } - public boolean isSelectivelyImmutableType(BType type, Set unresolvedTypes, PackageID packageID) { - return isSelectivelyImmutableType(type, unresolvedTypes, false, packageID); + if (targetTag == TypeTags.JSON) { + if (sourceTag == TypeTags.JSON) { + return true; + } + + if (sourceTag == TypeTags.TUPLE) { + return isTupleTypeAssignable(source, target, unresolvedTypes); + } + + if (sourceTag == TypeTags.ARRAY) { + return isArrayTypesAssignable((BArrayType) source, target, unresolvedTypes); + } + + if (sourceTag == TypeTags.MAP) { + return isAssignable(((BMapType) source).constraint, target, unresolvedTypes); + } + + if (sourceTag == TypeTags.RECORD) { + return isAssignableRecordType((BRecordType) source, target, unresolvedTypes); + } + } + + if (targetTag == TypeTags.FUTURE && sourceTag == TypeTags.FUTURE) { + if (((BFutureType) target).constraint.tag == TypeTags.NONE) { + return true; + } + return isAssignable(((BFutureType) source).constraint, ((BFutureType) target).constraint, unresolvedTypes); + } + + if (targetTag == TypeTags.MAP && sourceTag == TypeTags.MAP) { + // Here source condition is added for prevent assigning map union constrained + // to map any constrained. + if (((BMapType) target).constraint.tag == TypeTags.ANY && + ((BMapType) source).constraint.tag != TypeTags.UNION) { + return true; + } + + return isAssignable(((BMapType) source).constraint, ((BMapType) target).constraint, unresolvedTypes); + } + + if ((sourceTag == TypeTags.OBJECT || sourceTag == TypeTags.RECORD) + && (targetTag == TypeTags.OBJECT || targetTag == TypeTags.RECORD)) { + return checkStructEquivalency(source, target, unresolvedTypes); + } + + if (sourceTag == TypeTags.TUPLE && targetTag == TypeTags.ARRAY) { + return isTupleTypeAssignableToArrayType((BTupleType) source, (BArrayType) target, unresolvedTypes); + } + + if (sourceTag == TypeTags.ARRAY && targetTag == TypeTags.TUPLE) { + return isArrayTypeAssignableToTupleType((BArrayType) source, (BTupleType) target, unresolvedTypes); + } + + if (sourceTag == TypeTags.TUPLE || targetTag == TypeTags.TUPLE) { + return isTupleTypeAssignable(source, target, unresolvedTypes); + } + + if (sourceTag == TypeTags.INVOKABLE && targetTag == TypeTags.INVOKABLE) { + return isFunctionTypeAssignable((BInvokableType) source, (BInvokableType) target, new HashSet<>()); + } + + return (sourceTag == TypeTags.ARRAY || sourceTag == TypeTags.BYTE_ARRAY) + && targetTag == TypeTags.ARRAY + && isArrayTypesAssignable((BArrayType) source, target, unresolvedTypes); } - private boolean isSelectivelyImmutableType(BType input, Set unresolvedTypes, boolean forceCheck, - PackageID packageID) { - BType type = getImpliedType(input); + private boolean isMutable(BType type) { + if (Symbols.isFlagOn(type.flags, Flags.READONLY)) { + return false; + } - if (isInherentlyImmutableType(type) || !(type instanceof SelectivelyImmutableReferenceType)) { - // Always immutable. + type = getImpliedType(type); + if (type.tag != TypeTags.UNION) { + return true; + } + + BUnionType unionType = (BUnionType) type; + for (BType memberType : unionType.getMemberTypes()) { + if (!Symbols.isFlagOn(memberType.flags, Flags.READONLY)) { + return true; + } + } + + unionType.flags |= Flags.READONLY; + BTypeSymbol tsymbol = unionType.tsymbol; + if (tsymbol != null) { + tsymbol.flags |= Flags.READONLY; + } + return false; + } + + private boolean isParameterizedTypeAssignable(BType source, BType target, Set unresolvedTypes) { + BType resolvedSourceType = unifier.build(source); + target = getImpliedType(target); + if (target.tag != TypeTags.PARAMETERIZED_TYPE) { + return isAssignable(resolvedSourceType, target, unresolvedTypes); + } + + if (((BParameterizedType) source).paramIndex != ((BParameterizedType) target).paramIndex) { return false; } - if (!unresolvedTypes.add(type)) { + return isAssignable(resolvedSourceType, unifier.build(target), unresolvedTypes); + } + + private boolean isAssignableRecordType(BRecordType recordType, BType type, Set unresolvedTypes) { + TypePair pair = new TypePair(recordType, type); + if (!unresolvedTypes.add(pair)) { return true; } - if (!forceCheck && - getImmutableType(symTable, packageID, (SelectivelyImmutableReferenceType) type).isPresent()) { + type = getImpliedType(type); + BType targetType = switch (type.tag) { + case TypeTags.MAP -> ((BMapType) type).constraint; + case TypeTags.JSON -> type; + default -> throw new IllegalArgumentException("Incompatible target type: " + type); + }; + return recordFieldsAssignableToType(recordType, targetType, unresolvedTypes); + } + + private boolean isAssignableStreamType(BStreamType sourceStreamType, BStreamType targetStreamType, + Set unresolvedTypes) { + return isAssignable(sourceStreamType.constraint, targetStreamType.constraint, unresolvedTypes) + && isAssignable(sourceStreamType.completionType, targetStreamType.completionType, unresolvedTypes); + } + + private boolean recordFieldsAssignableToType(BRecordType recordType, BType targetType, + Set unresolvedTypes) { + for (BField field : recordType.fields.values()) { + if (!isAssignable(field.type, targetType, unresolvedTypes)) { + return false; + } + } + + if (!recordType.sealed) { + return isAssignable(recordType.restFieldType, targetType, unresolvedTypes); + } + + return true; + } + + private boolean isAssignableTableType(BTableType sourceTableType, BTableType targetTableType, + Set unresolvedTypes) { + if (!isAssignable(sourceTableType.constraint, targetTableType.constraint, unresolvedTypes)) { + return false; + } + + if (targetTableType.keyTypeConstraint == null && targetTableType.fieldNameList.isEmpty()) { return true; } - switch (type.tag) { - case TypeTags.ANY: - case TypeTags.ANYDATA: - case TypeTags.JSON: - case TypeTags.XML: - case TypeTags.XML_COMMENT: - case TypeTags.XML_ELEMENT: - case TypeTags.XML_PI: - case TypeTags.BYTE_ARRAY: + if (targetTableType.keyTypeConstraint != null) { + if (sourceTableType.keyTypeConstraint != null && + (isAssignable(sourceTableType.keyTypeConstraint, targetTableType.keyTypeConstraint, + unresolvedTypes))) { return true; - case TypeTags.ARRAY: - BArrayType arrayType = (BArrayType) type; - BType elementType = arrayType.eType; - if (elementType == symTable.semanticError && arrayType.mutableType != null) { - elementType = arrayType.mutableType.eType; - } - return isInherentlyImmutableType(elementType) || - isSelectivelyImmutableType(elementType, unresolvedTypes, forceCheck, packageID); - case TypeTags.TUPLE: - BTupleType tupleType = (BTupleType) type; - List tupleMemberTypes = tupleType.getTupleTypes(); - if (tupleMemberTypes.isEmpty() && tupleType.mutableType != null) { - tupleMemberTypes = tupleType.mutableType.getTupleTypes(); - } - for (BType memberType : tupleMemberTypes) { - if (!isInherentlyImmutableType(memberType) && - !isSelectivelyImmutableType(memberType, unresolvedTypes, forceCheck, packageID)) { - return false; - } - } + } - BType tupRestType = tupleType.restType; - if (tupRestType == null) { - return true; - } + if (sourceTableType.fieldNameList.isEmpty()) { + return false; + } - return isInherentlyImmutableType(tupRestType) || - isSelectivelyImmutableType(tupRestType, unresolvedTypes, forceCheck, packageID); + List fieldTypes = new ArrayList<>(); + sourceTableType.fieldNameList.stream() + .map(f -> getTableConstraintField(sourceTableType.constraint, f)) + .filter(Objects::nonNull).map(f -> new BTupleMember(f.type, + Symbols.createVarSymbolForTupleMember(f.type))).forEach(fieldTypes::add); + if (fieldTypes.size() == 1) { + return isAssignable(fieldTypes.get(0).type, targetTableType.keyTypeConstraint, unresolvedTypes); + } + + BTupleType tupleType = new BTupleType(fieldTypes); + return isAssignable(tupleType, targetTableType.keyTypeConstraint, unresolvedTypes); + } + + return targetTableType.fieldNameList.equals(sourceTableType.fieldNameList); + } + + + BField getTableConstraintField(BType constraintType, String fieldName) { + constraintType = getImpliedType(constraintType); + switch (constraintType.tag) { case TypeTags.RECORD: - BRecordType recordType = (BRecordType) type; - LinkedHashMap recordFields = recordType.fields; - if (recordFields.isEmpty() && recordType.mutableType != null) { - recordFields = recordType.mutableType.fields; - } - for (BField field : recordFields.values()) { - BType fieldType = field.type; - if (!Symbols.isFlagOn(field.symbol.flags, Flags.OPTIONAL) && - !isInherentlyImmutableType(fieldType) && - !isSelectivelyImmutableType(fieldType, unresolvedTypes, forceCheck, packageID)) { - return false; - } + Map fieldList = ((BRecordType) constraintType).getFields(); + return fieldList.get(fieldName); + case TypeTags.UNION: + BUnionType unionType = (BUnionType) constraintType; + Set memTypes = unionType.getMemberTypes(); + List fields = memTypes.stream().map(type -> getTableConstraintField(type, fieldName)) + .filter(Objects::nonNull).toList(); + + if (fields.size() != memTypes.size()) { + return null; } - return true; - case TypeTags.MAP: - BMapType mapType = (BMapType) type; - BType constraintType = mapType.constraint; - if (constraintType == symTable.semanticError && mapType.mutableType != null) { - constraintType = mapType.mutableType.constraint; + + if (fields.stream().allMatch(field -> isAssignable(field.type, fields.get(0).type) && + isAssignable(fields.get(0).type, field.type))) { + return fields.get(0); } - return isInherentlyImmutableType(constraintType) || - isSelectivelyImmutableType(constraintType, unresolvedTypes, forceCheck, packageID); - case TypeTags.OBJECT: - BObjectType objectType = (BObjectType) type; - LinkedHashMap objectFields = objectType.fields; - if (objectFields.isEmpty() && objectType.mutableType != null) { - objectFields = objectType.mutableType.fields; + } + + return null; + } + + private boolean isAssignableMapType(BMapType sourceMapType, BRecordType targetRecType) { + if (targetRecType.sealed) { + return false; + } + + for (BField field : targetRecType.fields.values()) { + if (!Symbols.isFlagOn(field.symbol.flags, Flags.OPTIONAL)) { + return false; + } + + if (hasIncompatibleReadOnlyFlags(field.symbol.flags, sourceMapType.flags)) { + return false; + } + + if (!isAssignable(sourceMapType.constraint, field.type)) { + return false; + } + } + + return isAssignable(sourceMapType.constraint, targetRecType.restFieldType); + } + + private boolean hasIncompatibleReadOnlyFlags(long targetFlags, long sourceFlags) { + return Symbols.isFlagOn(targetFlags, Flags.READONLY) && !Symbols.isFlagOn(sourceFlags, Flags.READONLY); + } + + private boolean isErrorTypeAssignable(BErrorType source, BErrorType target, Set unresolvedTypes) { + if (target == symTable.errorType) { + return true; + } + TypePair pair = new TypePair(source, target); + if (unresolvedTypes.contains(pair)) { + return true; + } + unresolvedTypes.add(pair); + return isAssignable(source.detailType, target.detailType, unresolvedTypes) + && target.typeIdSet.isAssignableFrom(source.typeIdSet); + } + + private boolean isXMLTypeAssignable(BType sourceT, BType targetT, Set unresolvedTypes) { + BType sourceType = getImpliedType(sourceT); + BType targetType = getImpliedType(targetT); + int sourceTag = sourceType.tag; + int targetTag = targetType.tag; + + if (targetTag == TypeTags.XML) { + BXMLType target = (BXMLType) targetType; + if (target.constraint != null) { + if (TypeTags.isXMLNonSequenceType(sourceTag)) { + return isAssignable(sourceType, target.constraint, unresolvedTypes); } - for (BField field : objectFields.values()) { - BType fieldType = field.type; - if (!isInherentlyImmutableType(fieldType) && - !isSelectivelyImmutableType(fieldType, unresolvedTypes, forceCheck, packageID)) { - return false; + BXMLType source = (BXMLType) sourceType; + if (getImpliedType(source.constraint).tag == TypeTags.NEVER) { + if (sourceTag == targetTag) { + return true; } + return isAssignable(source, target.constraint, unresolvedTypes); } - return true; - case TypeTags.TABLE: - BTableType tableType = (BTableType) type; - BType tableConstraintType = tableType.constraint; - if (tableConstraintType == symTable.semanticError && tableType.mutableType != null) { - tableConstraintType = tableType.mutableType.constraint; - } - return isInherentlyImmutableType(tableConstraintType) || - isSelectivelyImmutableType(tableConstraintType, unresolvedTypes, forceCheck, packageID); - case TypeTags.UNION: - boolean readonlyIntersectionExists = false; - BUnionType unionType = (BUnionType) type; - LinkedHashSet memberTypes = unionType.getMemberTypes(); - for (BType memberType : memberTypes) { - if (isInherentlyImmutableType(memberType) || - isSelectivelyImmutableType(memberType, unresolvedTypes, forceCheck, packageID)) { - readonlyIntersectionExists = true; + return isAssignable(source.constraint, target, unresolvedTypes); + } + return true; + } + if (sourceTag == TypeTags.XML) { + BXMLType source = (BXMLType) sourceType; + if (targetTag == TypeTags.XML_TEXT) { + if (source.constraint != null) { + int constraintTag = getImpliedType(source.constraint).tag; + if (constraintTag == TypeTags.NEVER || constraintTag == TypeTags.XML_TEXT) { + return true; + } else { + return isAssignable(source.constraint, targetType, unresolvedTypes); } } - return readonlyIntersectionExists; + return false; + } } - return false; + return sourceTag == targetTag; } - public static boolean containsTypeParams(BInvokableType type) { - boolean hasParameterizedTypes = type.paramTypes.stream() - .anyMatch(t -> { - t = getImpliedType(t); - if (t.tag == TypeTags.FUNCTION_POINTER) { - return containsTypeParams((BInvokableType) t); - } - return TypeParamAnalyzer.isTypeParam(t); - }); + private boolean isTupleTypeAssignable(BType source, BType target, Set unresolvedTypes) { + TypePair pair = new TypePair(source, target); + if (unresolvedTypes.contains(pair)) { + return true; + } - if (hasParameterizedTypes) { + source = getImpliedType(source); + if (source.tag == TypeTags.TUPLE && ((BTupleType) source).isCyclic) { + // add cyclic source to target pair to avoid recursive calls + unresolvedTypes.add(pair); + } + + target = getImpliedType(target); + if (target.tag == TypeTags.JSON && source.tag == TypeTags.TUPLE) { + BTupleType rhsTupleType = (BTupleType) source; + for (BType tupleType : rhsTupleType.getTupleTypes()) { + if (!isAssignable(tupleType, target, unresolvedTypes)) { + return false; + } + } + if (rhsTupleType.restType != null) { + return isAssignable(rhsTupleType.restType, target, unresolvedTypes); + } return true; } - BType retType = getImpliedType(type.retType); - if (retType.tag == TypeTags.FUNCTION_POINTER) { - return containsTypeParams((BInvokableType) retType); + if (source.tag != TypeTags.TUPLE || target.tag != TypeTags.TUPLE) { + return false; } - return TypeParamAnalyzer.isTypeParam(type.retType); - } + BTupleType lhsTupleType = (BTupleType) target; + BTupleType rhsTupleType = (BTupleType) source; - public void setForeachTypedBindingPatternType(BLangForeach foreachNode) { - BType collectionType = getImpliedType(foreachNode.collection.getBType()); - BType varType; - switch (collectionType.tag) { - case TypeTags.STRING: - varType = symTable.charStringType; + if (lhsTupleType.restType == null && rhsTupleType.restType != null) { + return false; + } + + if (lhsTupleType.restType == null && + lhsTupleType.getMembers().size() != rhsTupleType.getMembers().size()) { + return false; + } + + if (lhsTupleType.restType != null && rhsTupleType.restType != null) { + if (!isAssignable(rhsTupleType.restType, lhsTupleType.restType, unresolvedTypes)) { + return false; + } + } + List lhsTupleMemberTypes = lhsTupleType.getTupleTypes(); + List rhsTupleMemberTypes = rhsTupleType.getTupleTypes(); + + if (lhsTupleMemberTypes.size() > rhsTupleMemberTypes.size()) { + return false; + } + + for (int i = 0; i < rhsTupleMemberTypes.size(); i++) { + BType lhsType = (lhsTupleMemberTypes.size() > i) + ? lhsTupleMemberTypes.get(i) : lhsTupleType.restType; + if (!isAssignable(rhsTupleMemberTypes.get(i), lhsType, unresolvedTypes)) { + return false; + } + } + return true; + } + + private boolean checkAllTupleMembersBelongNoType(List tupleTypes) { + boolean isNoType = false; + for (BType type : tupleTypes) { + type = getImpliedType(type); + switch (type.tag) { + case TypeTags.NONE: + isNoType = true; + break; + case TypeTags.TUPLE: + isNoType = checkAllTupleMembersBelongNoType(((BTupleType) type).getTupleTypes()); + if (!isNoType) { + return false; + } + break; + default: + return false; + } + } + return isNoType; + } + + private boolean isTupleTypeAssignableToArrayType(BTupleType source, BArrayType target, + Set unresolvedTypes) { + if (target.state != BArrayState.OPEN + && (source.restType != null || source.getMembers().size() != target.size)) { + return false; + } + + List sourceTypes = new ArrayList<>(source.getTupleTypes()); + if (source.restType != null) { + BType type = source.restType; + sourceTypes.add(type); + } + return sourceTypes.stream() + .allMatch(tupleElemType -> isAssignable(tupleElemType, target.eType, unresolvedTypes)); + } + + private boolean isArrayTypeAssignableToTupleType(BArrayType source, BTupleType target, + Set unresolvedTypes) { + BType restType = target.restType; + List tupleTypes = target.getTupleTypes(); + if (source.state == BArrayState.OPEN) { + if (restType == null || !tupleTypes.isEmpty()) { + // [int, int] = int[] || [int, int...] = int[] + return false; + } + + return isAssignable(source.eType, restType, unresolvedTypes); + } + + int targetTupleMemberSize = tupleTypes.size(); + int sourceArraySize = source.size; + + if (targetTupleMemberSize > sourceArraySize) { + // [int, int, int...] = int[1] + return false; + } + + if (restType == null && targetTupleMemberSize < sourceArraySize) { + // [int, int] = int[3] + return false; + } + + BType sourceElementType = source.eType; + for (BType memType : tupleTypes) { + if (!isAssignable(sourceElementType, memType, unresolvedTypes)) { + return false; + } + } + + if (restType == null) { + return true; + } + + return sourceArraySize == targetTupleMemberSize || isAssignable(sourceElementType, restType, unresolvedTypes); + } + + private boolean isArrayTypesAssignable(BArrayType source, BType target, Set unresolvedTypes) { + BType sourceElementType = source.getElementType(); + target = getImpliedType(target); + if (target.tag == TypeTags.ARRAY) { + BArrayType targetArrayType = (BArrayType) target; + BType targetElementType = targetArrayType.getElementType(); + if (targetArrayType.state == BArrayState.OPEN) { + return isAssignable(sourceElementType, targetElementType, unresolvedTypes); + } + + if (targetArrayType.size != source.size) { + return false; + } + + return isAssignable(sourceElementType, targetElementType, unresolvedTypes); + } else if (target.tag == TypeTags.JSON) { + return isAssignable(sourceElementType, target, unresolvedTypes); + } else if (target.tag == TypeTags.ANYDATA) { + return isAssignable(sourceElementType, target, unresolvedTypes); + } + return false; + } + + private boolean isFunctionTypeAssignable(BInvokableType source, BInvokableType target, + Set unresolvedTypes) { + if (hasIncompatibleIsolatedFlags(source, target) || hasIncompatibleTransactionalFlags(source, target)) { + return false; + } + + if (Symbols.isFlagOn(target.flags, Flags.ANY_FUNCTION)) { + return true; + } + if (Symbols.isFlagOn(source.flags, Flags.ANY_FUNCTION) && !Symbols.isFlagOn(target.flags, Flags.ANY_FUNCTION)) { + return false; + } + + // For invokable types with typeParam parameters, we have to check whether the source param types are + // covariant with the target param types. + if (containsTypeParams(target)) { + // TODO: 7/4/19 See if the below code can be generalized to avoid code duplication + if (source.paramTypes.size() != target.paramTypes.size()) { + return false; + } + + for (int i = 0; i < source.paramTypes.size(); i++) { + BType sourceParam = source.paramTypes.get(i); + BType targetParam = target.paramTypes.get(i); + boolean isTypeParam = TypeParamAnalyzer.isTypeParam(targetParam); + + if (isTypeParam) { + if (!isAssignable(sourceParam, targetParam)) { + return false; + } + } else { + if (!isAssignable(targetParam, sourceParam)) { + return false; + } + } + } + + if (source.retType == null && target.retType == null) { + return true; + } else if (source.retType == null || target.retType == null) { + return false; + } + + // Source return type should be covariant with target return type + return isAssignable(source.retType, target.retType, unresolvedTypes); + } + + // Source param types should be contravariant with target param types. Hence s and t switched when checking + // assignability. + return checkFunctionTypeEquality(source, target, unresolvedTypes, (s, t, ut) -> isAssignable(t, s, ut)); + } + + public boolean isInherentlyImmutableType(BType type) { + type = getImpliedType(type); + if (isValueType(type)) { + return true; + } + + return switch (type.tag) { + case TypeTags.XML_TEXT, + TypeTags.FINITE, // Assuming a finite type will only have members from simple basic types. + TypeTags.READONLY, + TypeTags.NIL, + TypeTags.NEVER, + TypeTags.ERROR, + TypeTags.INVOKABLE, + TypeTags.TYPEDESC, + TypeTags.HANDLE, + TypeTags.REGEXP -> true; + case TypeTags.XML -> getImpliedType(((BXMLType) type).constraint).tag == TypeTags.NEVER; + default -> false; + }; + } + + /** + * Retrieve the referred type if a given type is a type reference type or + * retrieve the effective type if the given type is an intersection type. + * + * @param type type to retrieve the implied type + * @return the implied type if provided with a type reference type or an intersection type, + * else returns the original type + */ + public static BType getImpliedType(BType type) { + type = getReferredType(type); + if (type != null && type.tag == TypeTags.INTERSECTION) { + return getImpliedType(((BIntersectionType) type).effectiveType); + } + + return type; + } + + public static BType getReferredType(BType type) { + if (type != null && type.tag == TypeTags.TYPEREFDESC) { + return getReferredType(((BTypeReferenceType) type).referredType); + } + + return type; + } + + public BLangExpression addConversionExprIfRequired(BLangExpression expr, BType lhsType) { + if (lhsType.tag == TypeTags.NONE) { + return expr; + } + + BType rhsType = expr.getBType(); + + if (lhsType.tag == TypeTags.TYPEREFDESC && rhsType.tag != TypeTags.TYPEREFDESC) { + return addConversionExprIfRequired(expr, Types.getReferredType(lhsType)); + } + + if (isSameType(rhsType, lhsType)) { + return expr; + } + + setImplicitCastExpr(expr, rhsType, lhsType); + if (expr.impConversionExpr != null) { + BLangExpression impConversionExpr = expr.impConversionExpr; + expr.impConversionExpr = null; + return impConversionExpr; + } + + if (lhsType.tag == TypeTags.JSON && rhsType.tag == TypeTags.NIL) { + return expr; + } + + if (lhsType.tag == TypeTags.NIL && rhsType.isNullable()) { + return expr; + } + + if (lhsType.tag == TypeTags.ARRAY && rhsType.tag == TypeTags.TUPLE) { + return expr; + } + + // Create a type cast expression + BLangTypeConversionExpr conversionExpr = (BLangTypeConversionExpr) + TreeBuilder.createTypeConversionNode(); + conversionExpr.expr = expr; + conversionExpr.targetType = lhsType; + conversionExpr.setBType(lhsType); + conversionExpr.pos = expr.pos; + conversionExpr.checkTypes = false; + conversionExpr.internal = true; + return conversionExpr; + } + + boolean isSelectivelyImmutableType(BType type, PackageID packageID) { + return isSelectivelyImmutableType(type, new HashSet<>(), false, packageID); + } + + boolean isSelectivelyImmutableType(BType type, boolean forceCheck, PackageID packageID) { + return isSelectivelyImmutableType(type, new HashSet<>(), forceCheck, packageID); + } + + public boolean isSelectivelyImmutableType(BType type, Set unresolvedTypes, PackageID packageID) { + return isSelectivelyImmutableType(type, unresolvedTypes, false, packageID); + } + + private boolean isSelectivelyImmutableType(BType type, Set unresolvedTypes, boolean forceCheck, + PackageID packageID) { + return isSelectivelyImmutableType(type, false, unresolvedTypes, forceCheck, packageID); + } + + private boolean isSelectivelyImmutableType(BType input, boolean disallowReadOnlyObjects, Set unresolvedTypes, + boolean forceCheck, PackageID packageID) { + BType type = getImpliedType(input); + + if (isInherentlyImmutableType(type) || !(type instanceof SelectivelyImmutableReferenceType)) { + // Always immutable. + return false; + } + + if (!unresolvedTypes.add(type)) { + return true; + } + + if (!forceCheck && + getImmutableType(symTable, packageID, (SelectivelyImmutableReferenceType) type).isPresent()) { + return true; + } + + switch (type.tag) { + case TypeTags.ANY: + case TypeTags.ANYDATA: + case TypeTags.JSON: + case TypeTags.XML: + case TypeTags.XML_COMMENT: + case TypeTags.XML_ELEMENT: + case TypeTags.XML_PI: + case TypeTags.BYTE_ARRAY: + return true; + case TypeTags.ARRAY: + BArrayType arrayType = (BArrayType) type; + BType elementType = arrayType.eType; + if (elementType == symTable.semanticError && arrayType.mutableType != null) { + elementType = arrayType.mutableType.eType; + } + return isInherentlyImmutableType(elementType) || + isSelectivelyImmutableType(elementType, unresolvedTypes, forceCheck, packageID); + case TypeTags.TUPLE: + BTupleType tupleType = (BTupleType) type; + List tupleMemberTypes = tupleType.getTupleTypes(); + if (tupleMemberTypes.isEmpty() && tupleType.mutableType != null) { + tupleMemberTypes = tupleType.mutableType.getTupleTypes(); + } + for (BType memberType : tupleMemberTypes) { + if (!isInherentlyImmutableType(memberType) && + !isSelectivelyImmutableType(memberType, unresolvedTypes, forceCheck, packageID)) { + return false; + } + } + + BType tupRestType = tupleType.restType; + if (tupRestType == null) { + return true; + } + + return isInherentlyImmutableType(tupRestType) || + isSelectivelyImmutableType(tupRestType, unresolvedTypes, forceCheck, packageID); + case TypeTags.RECORD: + BRecordType recordType = (BRecordType) type; + LinkedHashMap recordFields = recordType.fields; + if (recordFields.isEmpty() && recordType.mutableType != null) { + recordFields = recordType.mutableType.fields; + } + for (BField field : recordFields.values()) { + BType fieldType = field.type; + if (!Symbols.isFlagOn(field.symbol.flags, Flags.OPTIONAL) && + !isInherentlyImmutableType(fieldType) && + !isSelectivelyImmutableType(fieldType, unresolvedTypes, forceCheck, packageID)) { + return false; + } + } + return true; + case TypeTags.MAP: + BMapType mapType = (BMapType) type; + BType constraintType = mapType.constraint; + if (constraintType == symTable.semanticError && mapType.mutableType != null) { + constraintType = mapType.mutableType.constraint; + } + return isInherentlyImmutableType(constraintType) || + isSelectivelyImmutableType(constraintType, unresolvedTypes, forceCheck, packageID); + case TypeTags.OBJECT: + BObjectType objectType = (BObjectType) type; + LinkedHashMap objectFields = objectType.fields; + if (objectFields.isEmpty() && objectType.mutableType != null) { + objectFields = objectType.mutableType.fields; + } + for (BField field : objectFields.values()) { + BType fieldType = field.type; + if (!isInherentlyImmutableType(fieldType) && + !isSelectivelyImmutableType(fieldType, unresolvedTypes, forceCheck, packageID)) { + return false; + } + } + return true; + case TypeTags.TABLE: + BTableType tableType = (BTableType) type; + BType tableConstraintType = tableType.constraint; + if (tableConstraintType == symTable.semanticError && tableType.mutableType != null) { + tableConstraintType = tableType.mutableType.constraint; + } + return isInherentlyImmutableType(tableConstraintType) || + isSelectivelyImmutableType(tableConstraintType, unresolvedTypes, forceCheck, packageID); + case TypeTags.UNION: + boolean readonlyIntersectionExists = false; + BUnionType unionType = (BUnionType) type; + LinkedHashSet memberTypes = unionType.getMemberTypes(); + for (BType memberType : memberTypes) { + if (isInherentlyImmutableType(memberType) || + isSelectivelyImmutableType(memberType, unresolvedTypes, forceCheck, packageID)) { + readonlyIntersectionExists = true; + } + } + return readonlyIntersectionExists; + } + return false; + } + + private boolean containsTypeParams(BInvokableType type) { + boolean hasParameterizedTypes = type.paramTypes.stream() + .anyMatch(t -> { + t = getImpliedType(t); + if (t.tag == TypeTags.FUNCTION_POINTER) { + return containsTypeParams((BInvokableType) t); + } + return TypeParamAnalyzer.isTypeParam(t); + }); + + if (hasParameterizedTypes) { + return true; + } + + BType retType = getImpliedType(type.retType); + if (retType.tag == TypeTags.FUNCTION_POINTER) { + return containsTypeParams((BInvokableType) retType); + } + + return TypeParamAnalyzer.isTypeParam(type.retType); + } + + private boolean checkFunctionTypeEquality(BInvokableType source, BInvokableType target, + Set unresolvedTypes, TypeEqualityPredicate equality) { + if (hasIncompatibleIsolatedFlags(source, target) || hasIncompatibleTransactionalFlags(source, target)) { + return false; + } + + if (Symbols.isFlagOn(target.flags, Flags.ANY_FUNCTION) && Symbols.isFlagOn(source.flags, Flags.ANY_FUNCTION)) { + return true; + } + + if (Symbols.isFlagOn(target.flags, Flags.ANY_FUNCTION) || Symbols.isFlagOn(source.flags, Flags.ANY_FUNCTION)) { + return false; + } + + if (source.paramTypes.size() != target.paramTypes.size()) { + return false; + } + + for (int i = 0; i < source.paramTypes.size(); i++) { + if (!equality.test(source.paramTypes.get(i), target.paramTypes.get(i), unresolvedTypes)) { + return false; + } + } + + if ((source.restType != null && target.restType == null) || + target.restType != null && source.restType == null) { + return false; + } else if (source.restType != null && !equality.test(source.restType, target.restType, unresolvedTypes)) { + return false; + } + + if (source.retType == null && target.retType == null) { + return true; + } else if (source.retType == null || target.retType == null) { + return false; + } + + // Source return type should be covariant with target return type + return isAssignable(source.retType, target.retType, unresolvedTypes); + } + + private boolean hasIncompatibleIsolatedFlags(BInvokableType source, BInvokableType target) { + return Symbols.isFlagOn(target.flags, Flags.ISOLATED) && !Symbols.isFlagOn(source.flags, Flags.ISOLATED); + } + + private boolean hasIncompatibleTransactionalFlags(BInvokableType source, BInvokableType target) { + return Symbols.isFlagOn(source.flags, Flags.TRANSACTIONAL) && + !Symbols.isFlagOn(target.flags, Flags.TRANSACTIONAL); + } + + public boolean isSameArrayType(BType source, BType target, Set unresolvedTypes) { + target = getImpliedType(target); + source = getImpliedType(source); + if (target.tag != TypeTags.ARRAY || source.tag != TypeTags.ARRAY) { + return false; + } + + BArrayType lhsArrayType = (BArrayType) target; + BArrayType rhsArrayType = (BArrayType) source; + boolean hasSameTypeElements = isSameType(lhsArrayType.eType, rhsArrayType.eType, unresolvedTypes); + if (lhsArrayType.state == BArrayState.OPEN) { + return (rhsArrayType.state == BArrayState.OPEN) && hasSameTypeElements; + } + + return checkSealedArraySizeEquality(rhsArrayType, lhsArrayType) && hasSameTypeElements; + } + + public boolean checkSealedArraySizeEquality(BArrayType rhsArrayType, BArrayType lhsArrayType) { + return lhsArrayType.size == rhsArrayType.size; + } + + public boolean checkStructEquivalency(BType rhsType, BType lhsType) { + return checkStructEquivalency(rhsType, lhsType, new HashSet<>()); + } + + private boolean checkStructEquivalency(BType rhsType, BType lhsType, Set unresolvedTypes) { + // If we encounter two types that we are still resolving, then skip it. + // This is done to avoid recursive checking of the same type. + TypePair pair = new TypePair(rhsType, lhsType); + if (unresolvedTypes.contains(pair)) { + return true; + } + unresolvedTypes.add(pair); + + rhsType = getImpliedType(rhsType); + lhsType = getImpliedType(lhsType); + if (rhsType.tag == TypeTags.OBJECT && lhsType.tag == TypeTags.OBJECT) { + return checkObjectEquivalency((BObjectType) rhsType, (BObjectType) lhsType, unresolvedTypes); + } + + if (rhsType.tag == TypeTags.RECORD && lhsType.tag == TypeTags.RECORD) { + return checkRecordEquivalency((BRecordType) rhsType, (BRecordType) lhsType, unresolvedTypes); + } + + return false; + } + + public boolean checkObjectEquivalency(BObjectType rhsType, BObjectType lhsType, Set unresolvedTypes) { + if (Symbols.isFlagOn(lhsType.flags, Flags.ISOLATED) && !Symbols.isFlagOn(rhsType.flags, Flags.ISOLATED)) { + return false; + } + + BObjectTypeSymbol lhsStructSymbol = (BObjectTypeSymbol) lhsType.tsymbol; + BObjectTypeSymbol rhsStructSymbol = (BObjectTypeSymbol) rhsType.tsymbol; + List lhsFuncs = lhsStructSymbol.attachedFuncs; + List rhsFuncs = ((BObjectTypeSymbol) rhsType.tsymbol).attachedFuncs; + int lhsAttachedFuncCount = getObjectFuncCount(lhsStructSymbol); + int rhsAttachedFuncCount = getObjectFuncCount(rhsStructSymbol); + + // If LHS is a service obj, then RHS must be a service object in order to assignable + boolean isLhsAService = Symbols.isService(lhsStructSymbol); + if (isLhsAService && !Symbols.isService(rhsStructSymbol)) { + return false; + } + + // RHS type should have at least all the fields as well attached functions of LHS type. + if (lhsType.fields.size() > rhsType.fields.size() || lhsAttachedFuncCount > rhsAttachedFuncCount) { + return false; + } + + // The LHS type cannot have any private members. + for (BField bField : lhsType.fields.values()) { + if (Symbols.isPrivate(bField.symbol)) { + return false; + } + } + + for (BAttachedFunction func : lhsFuncs) { + if (Symbols.isPrivate(func.symbol)) { + return false; + } + } + + for (BField lhsField : lhsType.fields.values()) { + BField rhsField = rhsType.fields.get(lhsField.name.value); + if (rhsField == null || + !isInSameVisibilityRegion(lhsField.symbol, rhsField.symbol) || + !isAssignable(rhsField.type, lhsField.type, unresolvedTypes)) { + return false; + } + } + + for (BAttachedFunction lhsFunc : lhsFuncs) { + if (lhsFunc == lhsStructSymbol.initializerFunc) { + continue; + } + + Optional rhsFunction = getMatchingInvokableType(rhsFuncs, lhsFunc, unresolvedTypes); + if (rhsFunction.isEmpty()) { + return false; + } + + BAttachedFunction rhsFunc = rhsFunction.get(); + if (!isInSameVisibilityRegion(lhsFunc.symbol, rhsFunc.symbol)) { + return false; + } + + if (Symbols.isRemote(lhsFunc.symbol) != Symbols.isRemote(rhsFunc.symbol)) { + return false; + } + } + + return lhsType.typeIdSet.isAssignableFrom(rhsType.typeIdSet) || this.ignoreObjectTypeIds; + } + + private int getObjectFuncCount(BObjectTypeSymbol sym) { + int count = sym.attachedFuncs.size(); + // If an explicit initializer is available, it could mean, + // 1) User explicitly defined an initializer + // 2) The object type is coming from an already compiled source, hence the initializer is already set. + // If it's coming from a compiled binary, the attached functions list of the symbol would already contain + // the initializer in it. + if (sym.initializerFunc != null && sym.attachedFuncs.contains(sym.initializerFunc)) { + return count - 1; + } + return count; + } + + public boolean checkRecordEquivalency(BRecordType rhsType, BRecordType lhsType, Set unresolvedTypes) { + // If the LHS record is closed and the RHS record is open and the rest field type of RHS is not a 'never' + // type, the records aren't equivalent + if (lhsType.sealed && !rhsType.sealed && getImpliedType(rhsType.restFieldType).tag != TypeTags.NEVER) { + return false; + } + + // If both are open records, the rest field type of the RHS record should be assignable to the rest field + // type of the LHS type. + if (!rhsType.sealed && !isAssignable(rhsType.restFieldType, lhsType.restFieldType, unresolvedTypes)) { + return false; + } + + return checkFieldEquivalency(lhsType, rhsType, unresolvedTypes); + } + + public void setForeachTypedBindingPatternType(BLangForeach foreachNode) { + BType collectionType = getImpliedType(foreachNode.collection.getBType()); + BType varType; + switch (collectionType.tag) { + case TypeTags.STRING: + varType = symTable.charStringType; + break; + case TypeTags.ARRAY: + BArrayType arrayType = (BArrayType) collectionType; + varType = arrayType.eType; + break; + case TypeTags.TUPLE: + varType = getTupleMemberType((BTupleType) collectionType); + break; + case TypeTags.MAP: + BMapType bMapType = (BMapType) collectionType; + varType = bMapType.constraint; + break; + case TypeTags.RECORD: + BRecordType recordType = (BRecordType) collectionType; + varType = inferRecordFieldType(recordType); + break; + case TypeTags.XML: + BType typedBindingPatternType = getTypedBindingPatternTypeForXmlCollection(collectionType); + if (typedBindingPatternType == null) { + foreachNode.varType = symTable.semanticError; + foreachNode.resultType = symTable.semanticError; + foreachNode.nillableResultType = symTable.semanticError; + return; + } + varType = typedBindingPatternType; + break; + case TypeTags.XML_TEXT: + varType = symTable.xmlTextType; + break; + case TypeTags.TABLE: + BTableType tableType = (BTableType) collectionType; + varType = tableType.constraint; + break; + case TypeTags.STREAM: + BStreamType streamType = (BStreamType) collectionType; + if (streamType.constraint.tag == TypeTags.NONE) { + varType = symTable.anydataType; + break; + } + varType = streamType.constraint; + List completionType = getAllTypes(streamType.completionType, true); + if (completionType.stream().anyMatch(type -> getImpliedType(type).tag != TypeTags.NIL)) { + BType actualType = BUnionType.create(null, varType, streamType.completionType); + dlog.error(foreachNode.collection.pos, DiagnosticErrorCode.INCOMPATIBLE_TYPES, + varType, actualType); + } + break; + case TypeTags.OBJECT: + // check for iterable objects + BUnionType nextMethodReturnType = getVarTypeFromIterableObject((BObjectType) collectionType); + if (nextMethodReturnType != null) { + foreachNode.resultType = getRecordType(nextMethodReturnType); + BType valueType = (foreachNode.resultType != null) + ? ((BRecordType) foreachNode.resultType).fields.get("value").type : null; + BType errorType = getErrorType(nextMethodReturnType); + if (errorType != null) { + BType actualType = BUnionType.create(null, valueType, errorType); + dlog.error(foreachNode.collection.pos, + DiagnosticErrorCode.INVALID_ITERABLE_COMPLETION_TYPE_IN_FOREACH_NEXT_FUNCTION, + actualType, errorType); + } + foreachNode.nillableResultType = nextMethodReturnType; + foreachNode.varType = valueType; + return; + } + // fallthrough + case TypeTags.SEMANTIC_ERROR: + foreachNode.varType = symTable.semanticError; + foreachNode.resultType = symTable.semanticError; + foreachNode.nillableResultType = symTable.semanticError; + return; + default: + foreachNode.varType = symTable.semanticError; + foreachNode.resultType = symTable.semanticError; + foreachNode.nillableResultType = symTable.semanticError; + dlog.error(foreachNode.collection.pos, DiagnosticErrorCode.ITERABLE_NOT_SUPPORTED_COLLECTION, + collectionType); + return; + } + + BInvokableSymbol iteratorSymbol = (BInvokableSymbol) symResolver.lookupLangLibMethod(collectionType, + Names.fromString(BLangCompilerConstants.ITERABLE_COLLECTION_ITERATOR_FUNC), env); + BObjectType objectType = (BObjectType) getImpliedType(iteratorSymbol.retType); + BUnionType nextMethodReturnType = + (BUnionType) getResultTypeOfNextInvocation(objectType); + foreachNode.varType = varType; + foreachNode.resultType = getRecordType(nextMethodReturnType); + foreachNode.nillableResultType = nextMethodReturnType; + } + + public void setInputClauseTypedBindingPatternType(BLangInputClause bLangInputClause) { + if (bLangInputClause.collection == null) { + //not-possible + return; + } + + BType collectionType = bLangInputClause.collection.getBType(); + bLangInputClause.varType = visitCollectionType(bLangInputClause, collectionType); + if (bLangInputClause.varType.tag == TypeTags.SEMANTIC_ERROR || + getImpliedType(collectionType).tag == OBJECT) { + return; + } + + BInvokableSymbol iteratorSymbol = (BInvokableSymbol) symResolver.lookupLangLibMethod(collectionType, + Names.fromString(BLangCompilerConstants.ITERABLE_COLLECTION_ITERATOR_FUNC), env); + BUnionType nextMethodReturnType = + (BUnionType) getResultTypeOfNextInvocation((BObjectType) getImpliedType(iteratorSymbol.retType)); + bLangInputClause.resultType = getRecordType(nextMethodReturnType); + bLangInputClause.nillableResultType = nextMethodReturnType; + } + + private BType getTypedBindingPatternTypeForXmlCollection(BType collectionType) { + BType constraint = getImpliedType(((BXMLType) collectionType).constraint); + while (constraint.tag == TypeTags.XML) { + collectionType = constraint; + constraint = getImpliedType(((BXMLType) collectionType).constraint); + } + + switch (constraint.tag) { + case TypeTags.XML_ELEMENT: + case TypeTags.XML_COMMENT: + case TypeTags.XML_TEXT: + case TypeTags.XML_PI: + case TypeTags.NEVER: + return constraint; + case TypeTags.UNION: + Set collectionTypes = getEffectiveMemberTypes((BUnionType) constraint); + Set builtinXMLConstraintTypes = getEffectiveMemberTypes + ((BUnionType) ((BXMLType) symTable.xmlType).constraint); + return collectionTypes.size() == 4 && builtinXMLConstraintTypes.equals(collectionTypes) ? + collectionType : BUnionType.create(null, (LinkedHashSet) collectionTypes); + default: + return null; + } + } + + private BType visitCollectionType(BLangInputClause bLangInputClause, BType collectionType) { + collectionType = getImpliedType(collectionType); + switch (collectionType.tag) { + case TypeTags.STRING: + return symTable.stringType; + case TypeTags.ARRAY: + BArrayType arrayType = (BArrayType) collectionType; + return arrayType.eType; + case TypeTags.TUPLE: + return getTupleMemberType((BTupleType) collectionType); + case TypeTags.MAP: + BMapType bMapType = (BMapType) collectionType; + return bMapType.constraint; + case TypeTags.RECORD: + BRecordType recordType = (BRecordType) collectionType; + return inferRecordFieldType(recordType); + case TypeTags.XML: + BType bindingPatternType = getTypedBindingPatternTypeForXmlCollection(collectionType); + return bindingPatternType == null ? symTable.semanticError : bindingPatternType; + case TypeTags.XML_TEXT: + return symTable.xmlTextType; + case TypeTags.TABLE: + BTableType tableType = (BTableType) collectionType; + return tableType.constraint; + case TypeTags.STREAM: + BStreamType streamType = (BStreamType) collectionType; + if (streamType.constraint.tag == TypeTags.NONE) { + return symTable.anydataType; + } + return streamType.constraint; + case TypeTags.OBJECT: + // check for iterable objects + if (!isAssignable(collectionType, symTable.iterableType)) { + dlog.error(bLangInputClause.collection.pos, DiagnosticErrorCode.INVALID_ITERABLE_OBJECT_TYPE, + bLangInputClause.collection.getBType(), symTable.iterableType); + bLangInputClause.varType = symTable.semanticError; + bLangInputClause.resultType = symTable.semanticError; + bLangInputClause.nillableResultType = symTable.semanticError; + break; + } + + BUnionType nextMethodReturnType = getVarTypeFromIterableObject((BObjectType) collectionType); + if (nextMethodReturnType != null) { + bLangInputClause.resultType = getRecordType(nextMethodReturnType); + bLangInputClause.nillableResultType = nextMethodReturnType; + bLangInputClause.varType = ((BRecordType) bLangInputClause.resultType).fields.get("value").type; + return bLangInputClause.varType; + } + // fallthrough + case TypeTags.SEMANTIC_ERROR: + bLangInputClause.varType = symTable.semanticError; + bLangInputClause.resultType = symTable.semanticError; + bLangInputClause.nillableResultType = symTable.semanticError; + break; + default: + bLangInputClause.varType = symTable.semanticError; + bLangInputClause.resultType = symTable.semanticError; + bLangInputClause.nillableResultType = symTable.semanticError; + dlog.error(bLangInputClause.collection.pos, DiagnosticErrorCode.ITERABLE_NOT_SUPPORTED_COLLECTION, + collectionType); + } + return symTable.semanticError; + } + + private BType getTupleMemberType(BTupleType tupleType) { + LinkedHashSet tupleTypes = new LinkedHashSet<>(tupleType.getTupleTypes()); + if (tupleType.restType != null) { + tupleTypes.add(tupleType.restType); + } + int tupleTypesSize = tupleTypes.size(); + if (tupleTypesSize == 0) { + return symTable.neverType; + } + return tupleTypesSize == 1 ? + tupleTypes.iterator().next() : BUnionType.create(null, tupleTypes); + } + + public BUnionType getVarTypeFromIterableObject(BObjectType collectionType) { + BObjectTypeSymbol objectTypeSymbol = (BObjectTypeSymbol) collectionType.tsymbol; + for (BAttachedFunction func : objectTypeSymbol.attachedFuncs) { + if (func.funcName.value.equals(BLangCompilerConstants.ITERABLE_COLLECTION_ITERATOR_FUNC)) { + return getVarTypeFromIteratorFunc(func); + } + } + + return null; + } + + private BUnionType getVarTypeFromIteratorFunc(BAttachedFunction candidateIteratorFunc) { + if (!candidateIteratorFunc.type.paramTypes.isEmpty()) { + return null; + } + + BType returnType = candidateIteratorFunc.type.retType; + // abstract object {public function next() returns record {|int value;|}?;} + return getVarTypeFromIteratorFuncReturnType(returnType); + } + + public BUnionType getVarTypeFromIteratorFuncReturnType(BType type) { + BObjectTypeSymbol objectTypeSymbol; + BType returnType = getImpliedType(type); + if (returnType.tag != TypeTags.OBJECT) { + return null; + } + + objectTypeSymbol = (BObjectTypeSymbol) returnType.tsymbol; + for (BAttachedFunction func : objectTypeSymbol.attachedFuncs) { + if (func.funcName.value.equals(BLangCompilerConstants.NEXT_FUNC)) { + return getVarTypeFromNextFunc(func); + } + } + + return null; + } + + private BUnionType getVarTypeFromNextFunc(BAttachedFunction nextFunc) { + BType returnType; + if (!nextFunc.type.paramTypes.isEmpty()) { + return null; + } + + returnType = nextFunc.type.retType; + // Check if the next function return type has the union type, + // record {|int value;|}|error|(); + if (checkNextFuncReturnType(returnType)) { + return (BUnionType) returnType; + } + + return null; + } + + private boolean checkNextFuncReturnType(BType returnType) { + if (getImpliedType(returnType).tag != TypeTags.UNION) { + return false; + } + + List types = getAllTypes(returnType, true); + boolean containsCompletionType = types.removeIf(type -> type.tag == TypeTags.NIL); + containsCompletionType = types.removeIf(type -> type.tag == TypeTags.ERROR) || containsCompletionType; + if (!containsCompletionType) { + return false; + } + + if (types.size() != 1) { + //TODO: print error + return false; + } + + if (types.get(0).tag != TypeTags.RECORD) { + return false; + } + + BRecordType recordType = (BRecordType) types.get(0); + // Check if the union type has the record type, + // record {|int value;|}; + return checkRecordTypeInNextFuncReturnType(recordType); + } + + private boolean checkRecordTypeInNextFuncReturnType(BRecordType recordType) { + if (!recordType.sealed) { + return false; + } + + if (recordType.fields.size() != 1) { + return false; + } + + return recordType.fields.containsKey(BLangCompilerConstants.VALUE_FIELD); + } + + private BRecordType getRecordType(BUnionType type) { + for (BType member : type.getMemberTypes()) { + BType referredRecordType = getImpliedType(member); + if (referredRecordType.tag == TypeTags.RECORD) { + return (BRecordType) referredRecordType; + } + } + return null; + } + + public BErrorType getErrorType(BUnionType type) { + for (BType member : type.getMemberTypes()) { + member = getImpliedType(member); + + if (member.tag == TypeTags.ERROR) { + return (BErrorType) member; + } else if (member.tag == TypeTags.UNION) { + BErrorType e = getErrorType((BUnionType) member); + if (e != null) { + return e; + } + } + } + return null; + } + + public BType getResultTypeOfNextInvocation(BObjectType iteratorType) { + BAttachedFunction nextFunc = getAttachedFuncFromObject(iteratorType, BLangCompilerConstants.NEXT_FUNC); + return Objects.requireNonNull(nextFunc).type.retType; + } + + public BAttachedFunction getAttachedFuncFromObject(BObjectType objectType, String funcName) { + BObjectTypeSymbol iteratorSymbol = (BObjectTypeSymbol) objectType.tsymbol; + for (BAttachedFunction bAttachedFunction : iteratorSymbol.attachedFuncs) { + if (funcName.equals(bAttachedFunction.funcName.value)) { + return bAttachedFunction; + } + } + return null; + } + + public BType inferRecordFieldType(BRecordType recordType) { + Map fields = recordType.fields; + BUnionType unionType = BUnionType.create(null); + + if (!recordType.sealed) { + unionType.add(recordType.restFieldType); + } else if (fields.isEmpty()) { + unionType.add(symTable.neverType); + } + + for (BField field : fields.values()) { + if (isAssignable(field.type, unionType)) { + continue; + } + + if (isAssignable(unionType, field.type)) { + unionType = BUnionType.create(null); + } + + unionType.add(field.type); + } + + if (unionType.getMemberTypes().size() > 1) { + unionType.tsymbol = Symbols.createTypeSymbol(SymTag.UNION_TYPE, Flags.asMask(EnumSet.of(Flag.PUBLIC)), + Names.EMPTY, recordType.tsymbol.pkgID, null, + recordType.tsymbol.owner, symTable.builtinPos, VIRTUAL); + return unionType; + } + + return unionType.getMemberTypes().iterator().next(); + } + + + public BType getTypeWithEffectiveIntersectionTypes(BType bType) { + // TODO Can remove this method since this unwraps the referred type and intersection type. #40958 + BType type = getReferredType(bType); + BType effectiveType = null; + if (type.tag == TypeTags.INTERSECTION) { + effectiveType = ((BIntersectionType) type).effectiveType; + type = effectiveType; + } + + if (type.tag != TypeTags.UNION) { + return Objects.requireNonNullElse(effectiveType, bType); + } + + LinkedHashSet members = new LinkedHashSet<>(); + boolean hasDifferentMember = false; + + for (BType memberType : ((BUnionType) type).getMemberTypes()) { + effectiveType = getTypeWithEffectiveIntersectionTypes(memberType); + effectiveType = getImpliedType(effectiveType); + if (effectiveType != memberType) { + hasDifferentMember = true; + } + members.add(effectiveType); + } + + if (hasDifferentMember) { + return BUnionType.create(null, members); + } + return bType; + } + + /** + * Enum to represent type test result. + * + * @since 1.2.0 + */ + enum TypeTestResult { + NOT_FOUND, + TRUE, + FALSE + } + + TypeTestResult isBuiltInTypeWidenPossible(BType actualType, BType targetType) { + int targetTag = getImpliedType(targetType).tag; + int actualTag = getImpliedType(actualType).tag; + + if (actualTag < TypeTags.JSON && targetTag < TypeTags.JSON) { + // Fail Fast for value types. + switch (actualTag) { + case TypeTags.INT: + case TypeTags.BYTE: + case TypeTags.FLOAT: + case TypeTags.DECIMAL: + if (targetTag == TypeTags.BOOLEAN || targetTag == TypeTags.STRING) { + return TypeTestResult.FALSE; + } + break; + case TypeTags.BOOLEAN: + if (targetTag == TypeTags.INT || targetTag == TypeTags.BYTE || targetTag == TypeTags.FLOAT + || targetTag == TypeTags.DECIMAL || targetTag == TypeTags.STRING) { + return TypeTestResult.FALSE; + } + break; + case TypeTags.STRING: + if (targetTag == TypeTags.INT || targetTag == TypeTags.BYTE || targetTag == TypeTags.FLOAT + || targetTag == TypeTags.DECIMAL || targetTag == TypeTags.BOOLEAN) { + return TypeTestResult.FALSE; + } + break; + } + } + switch (actualTag) { + case TypeTags.INT: + case TypeTags.BYTE: + case TypeTags.FLOAT: + case TypeTags.DECIMAL: + case TypeTags.BOOLEAN: + case TypeTags.STRING: + case TypeTags.SIGNED32_INT: + case TypeTags.SIGNED16_INT: + case TypeTags.SIGNED8_INT: + case TypeTags.UNSIGNED32_INT: + case TypeTags.UNSIGNED16_INT: + case TypeTags.UNSIGNED8_INT: + case TypeTags.CHAR_STRING: + if (targetTag == TypeTags.JSON || targetTag == TypeTags.ANYDATA || targetTag == TypeTags.ANY || + targetTag == TypeTags.READONLY) { + return TypeTestResult.TRUE; + } break; - case TypeTags.ARRAY: - BArrayType arrayType = (BArrayType) collectionType; - varType = arrayType.eType; + case TypeTags.ANYDATA: + case TypeTags.TYPEDESC: + if (targetTag == TypeTags.ANY) { + return TypeTestResult.TRUE; + } break; - case TypeTags.TUPLE: - varType = getTupleMemberType((BTupleType) collectionType); + default: + } + + if (TypeTags.isIntegerTypeTag(targetTag) && actualTag == targetTag) { + return TypeTestResult.FALSE; // No widening. + } + + // Validate for Integers subtypes. + if ((TypeTags.isIntegerTypeTag(actualTag) || actualTag == TypeTags.BYTE) + && (TypeTags.isIntegerTypeTag(targetTag) || targetTag == TypeTags.BYTE)) { + return checkBuiltInIntSubtypeWidenPossible(actualType, targetType); + } + + if (actualTag == TypeTags.CHAR_STRING && TypeTags.STRING == targetTag) { + return TypeTestResult.TRUE; + } + return TypeTestResult.NOT_FOUND; + } + + private TypeTestResult checkBuiltInIntSubtypeWidenPossible(BType actualType, BType targetType) { + int actualTag = getImpliedType(actualType).tag; + targetType = getImpliedType(targetType); + switch (targetType.tag) { + case TypeTags.INT: + if (actualTag == TypeTags.BYTE || TypeTags.isIntegerTypeTag(actualTag)) { + return TypeTestResult.TRUE; + } break; - case TypeTags.MAP: - BMapType bMapType = (BMapType) collectionType; - varType = bMapType.constraint; + case TypeTags.SIGNED32_INT: + if (actualTag == TypeTags.SIGNED16_INT || actualTag == TypeTags.SIGNED8_INT || + actualTag == TypeTags.UNSIGNED16_INT || actualTag == TypeTags.UNSIGNED8_INT || + actualTag == TypeTags.BYTE) { + return TypeTestResult.TRUE; + } break; - case TypeTags.RECORD: - BRecordType recordType = (BRecordType) collectionType; - varType = inferRecordFieldType(recordType); + case TypeTags.SIGNED16_INT: + if (actualTag == TypeTags.SIGNED8_INT || actualTag == TypeTags.UNSIGNED8_INT || + actualTag == TypeTags.BYTE) { + return TypeTestResult.TRUE; + } break; - case TypeTags.XML: - BType typedBindingPatternType = getTypedBindingPatternTypeForXmlCollection(collectionType); - if (typedBindingPatternType == null) { - foreachNode.varType = symTable.semanticError; - foreachNode.resultType = symTable.semanticError; - foreachNode.nillableResultType = symTable.semanticError; - return; + case TypeTags.UNSIGNED32_INT: + if (actualTag == TypeTags.UNSIGNED16_INT || actualTag == TypeTags.UNSIGNED8_INT || + actualTag == TypeTags.BYTE) { + return TypeTestResult.TRUE; } - varType = typedBindingPatternType; break; - case TypeTags.XML_TEXT: - varType = symTable.xmlTextType; + case TypeTags.UNSIGNED16_INT: + if (actualTag == TypeTags.UNSIGNED8_INT || actualTag == TypeTags.BYTE) { + return TypeTestResult.TRUE; + } break; - case TypeTags.TABLE: - BTableType tableType = (BTableType) collectionType; - varType = tableType.constraint; + case TypeTags.BYTE: + if (actualTag == TypeTags.UNSIGNED8_INT) { + return TypeTestResult.TRUE; + } break; - case TypeTags.STREAM: - BStreamType streamType = (BStreamType) collectionType; - if (streamType.constraint.tag == TypeTags.NONE) { - varType = symTable.anydataType; - break; + case TypeTags.UNSIGNED8_INT: + if (actualTag == TypeTags.BYTE) { + return TypeTestResult.TRUE; } - varType = streamType.constraint; - List completionType = getAllTypes(streamType.completionType, true); - if (completionType.stream().anyMatch(type -> getImpliedType(type).tag != TypeTags.NIL)) { - BType actualType = BUnionType.create(typeEnv(), null, varType, streamType.completionType); - dlog.error(foreachNode.collection.pos, DiagnosticErrorCode.INCOMPATIBLE_TYPES, - varType, actualType); + } + return TypeTestResult.NOT_FOUND; + } + + public boolean isImplicitlyCastable(BType actual, BType target) { + /* The word Builtin refers for Compiler known types. */ + + BType targetType = getImpliedType(target); + BType actualType = getImpliedType(actual); + BType newTargetType = targetType; + int targetTypeTag = targetType.tag; + if ((targetTypeTag == TypeTags.UNION || targetTypeTag == TypeTags.FINITE) && isValueType(actualType)) { + newTargetType = symTable.anyType; // TODO : Check for correctness. + } + + TypeTestResult result = isBuiltInTypeWidenPossible(actualType, newTargetType); + if (result != TypeTestResult.NOT_FOUND) { + return result == TypeTestResult.TRUE; + } + + if (isValueType(targetType) && + (actualType.tag == TypeTags.FINITE || + (actualType.tag == TypeTags.UNION && ((BUnionType) actualType).getMemberTypes().stream() + .anyMatch(type -> getImpliedType(type).tag == TypeTags.FINITE && + isAssignable(type, targetType))))) { + // for nil, no cast is required + return TypeTags.isIntegerTypeTag(targetTypeTag) || targetType.tag == TypeTags.BYTE || + targetTypeTag == TypeTags.FLOAT || + targetTypeTag == TypeTags.DECIMAL || + TypeTags.isStringTypeTag(targetTypeTag) || + targetTypeTag == TypeTags.BOOLEAN; + + } else if (isValueType(targetType) && actualType.tag == TypeTags.UNION && + ((BUnionType) actualType).getMemberTypes().stream().allMatch(type -> isAssignable(type, targetType))) { + return true; + + } else if (targetTypeTag == TypeTags.ERROR + && (actualType.tag == TypeTags.UNION + && isAllErrorMembers((BUnionType) actualType))) { + return true; + } + return false; + } + + public boolean isTypeCastable(BLangExpression expr, BType source, BType target, SymbolEnv env) { + BType sourceType = getImpliedType(source); + BType targetType = getImpliedType(target); + if (sourceType.tag == TypeTags.SEMANTIC_ERROR || targetType.tag == TypeTags.SEMANTIC_ERROR || + sourceType == targetType) { + return true; + } + + // Disallow casting away error, this forces user to handle the error via type-test, check, or checkpanic + IntersectionContext intersectionContext = IntersectionContext.compilerInternalIntersectionTestContext(); + BType errorIntersection = getTypeIntersection(intersectionContext, sourceType, symTable.errorType, env); + if (errorIntersection != symTable.semanticError && + getTypeIntersection(intersectionContext, symTable.errorType, targetType, env) + == symTable.semanticError) { + return false; + } + + if (isAssignable(sourceType, targetType) || isAssignable(targetType, sourceType)) { + return true; + } + if (isNumericConversionPossible(expr, sourceType, targetType)) { + return true; + } + if (sourceType.tag == TypeTags.ANY && targetType.tag == TypeTags.READONLY) { + return true; + } + + boolean validTypeCast = false; + + // Use instanceof to check for anydata and json. + if (sourceType instanceof BUnionType) { + if (getTypeForUnionTypeMembersAssignableToType((BUnionType) sourceType, targetType, env, + intersectionContext, new LinkedHashSet<>()) + != symTable.semanticError) { + // string|typedesc v1 = "hello world"; + // json|table v2 = > v1; + validTypeCast = true; + } + } + + // Use instanceof to check for anydata and json. + if (targetType instanceof BUnionType) { + if (getTypeForUnionTypeMembersAssignableToType((BUnionType) targetType, sourceType, env, + intersectionContext, new LinkedHashSet<>()) + != symTable.semanticError) { + // string|int v1 = "hello world"; + // string|boolean v2 = v1; + validTypeCast = true; + } + } + + if (sourceType.tag == TypeTags.FINITE) { + if (getTypeForFiniteTypeValuesAssignableToType((BFiniteType) sourceType, targetType) + != symTable.semanticError) { + validTypeCast = true; + } + } + + if (targetType.tag == TypeTags.FINITE) { + if (getTypeForFiniteTypeValuesAssignableToType((BFiniteType) targetType, sourceType) + != symTable.semanticError) { + validTypeCast = true; + } + } + + if (validTypeCast) { + if (isValueType(sourceType)) { + setImplicitCastExpr(expr, sourceType, symTable.anyType); + } + return true; + } + + return false; + } + + boolean isNumericConversionPossible(BLangExpression expr, BType sourceType, + BType targetType) { + + final boolean isSourceNumericType = isBasicNumericType(sourceType); + final boolean isTargetNumericType = isBasicNumericType(targetType); + if (isSourceNumericType && isTargetNumericType) { + // We only reach here for different numeric types. + // 2019R3 Spec defines numeric conversion between each type. + return true; + } + if (targetType.tag == TypeTags.UNION) { + HashSet typeTags = new HashSet<>(); + for (BType bType : ((BUnionType) targetType).getMemberTypes()) { + if (isBasicNumericType(bType)) { + typeTags.add(getImpliedType(bType).tag); + if (typeTags.size() > 1) { + // Multiple Basic numeric types found in the union. + return false; + } + } + } + } + + if (!isTargetNumericType && targetType.tag != TypeTags.UNION) { + return false; + } + + // Target type has at least one numeric type member. + + if (isSourceNumericType) { + // i.e., a conversion from a numeric type to another numeric type in a union. + // int|string u1 = 1.0; + // TODO : Fix me. This doesn't belong here. + setImplicitCastExpr(expr, sourceType, symTable.anyType); + return true; + } + + // TODO : Do we need this? This doesn't belong here. + switch (sourceType.tag) { + case TypeTags.ANY: + case TypeTags.ANYDATA: + case TypeTags.JSON: + // This + return true; + case TypeTags.UNION: + for (BType memType : ((BUnionType) sourceType).getMemberTypes()) { + BType referredType = getImpliedType(memType); + if (isBasicNumericType(referredType) || + (referredType.tag == TypeTags.FINITE && + finiteTypeContainsNumericTypeValues((BFiniteType) referredType))) { + return true; + } + } + break; + case TypeTags.FINITE: + if (finiteTypeContainsNumericTypeValues((BFiniteType) sourceType)) { + return true; } break; - case TypeTags.OBJECT: - // check for iterable objects - BUnionType nextMethodReturnType = getVarTypeFromIterableObject((BObjectType) collectionType); - if (nextMethodReturnType != null) { - foreachNode.resultType = getRecordType(nextMethodReturnType); - BType valueType = (foreachNode.resultType != null) - ? ((BRecordType) foreachNode.resultType).fields.get("value").type : null; - BType errorType = getErrorType(nextMethodReturnType); - if (errorType != null) { - BType actualType = BUnionType.create(typeEnv(), null, valueType, errorType); - dlog.error(foreachNode.collection.pos, - DiagnosticErrorCode.INVALID_ITERABLE_COMPLETION_TYPE_IN_FOREACH_NEXT_FUNCTION, - actualType, errorType); + } + return false; + } + + public boolean isAllErrorMembers(BUnionType actualType) { + return actualType.getMemberTypes().stream().allMatch(t -> isAssignable(t, symTable.errorType)); + } + + public void setImplicitCastExpr(BLangExpression expr, BType actualType, BType targetType) { + BType expType = getImpliedType(targetType); + if (!isImplicitlyCastable(actualType, expType)) { + return; + } + BLangTypeConversionExpr implicitConversionExpr = + (BLangTypeConversionExpr) TreeBuilder.createTypeConversionNode(); + implicitConversionExpr.pos = expr.pos; + implicitConversionExpr.expr = expr.impConversionExpr == null ? expr : expr.impConversionExpr; + implicitConversionExpr.setBType(expType); + implicitConversionExpr.targetType = expType; + implicitConversionExpr.internal = true; + expr.impConversionExpr = implicitConversionExpr; + } + + public boolean checkListenerCompatibilityAtServiceDecl(BType type) { + if (getImpliedType(type).tag == TypeTags.UNION) { + // There should be at least one listener compatible type and all the member types, except error type + // should be listener compatible. + int listenerCompatibleTypeCount = 0; + for (BType memberType : getAllTypes(type, true)) { + if (memberType.tag != TypeTags.ERROR) { + if (!checkListenerCompatibility(memberType)) { + return false; } - foreachNode.nillableResultType = nextMethodReturnType; - foreachNode.varType = valueType; - return; + listenerCompatibleTypeCount++; } - // fallthrough - case TypeTags.SEMANTIC_ERROR: - foreachNode.varType = symTable.semanticError; - foreachNode.resultType = symTable.semanticError; - foreachNode.nillableResultType = symTable.semanticError; - return; - default: - foreachNode.varType = symTable.semanticError; - foreachNode.resultType = symTable.semanticError; - foreachNode.nillableResultType = symTable.semanticError; - dlog.error(foreachNode.collection.pos, DiagnosticErrorCode.ITERABLE_NOT_SUPPORTED_COLLECTION, - collectionType); - return; + } + return listenerCompatibleTypeCount > 0; + } + return checkListenerCompatibility(type); + } + + public boolean checkListenerCompatibility(BType bType) { + BType type = getImpliedType(bType); + if (type.tag == TypeTags.UNION) { + BUnionType unionType = (BUnionType) type; + for (BType memberType : unionType.getMemberTypes()) { + if (!checkListenerCompatibility(memberType)) { + return false; + } + } + return true; + } + + if (type.tag != TypeTags.OBJECT) { + return false; + } + + BObjectType rhsType = (BObjectType) type; + List rhsFuncs = ((BStructureTypeSymbol) rhsType.tsymbol).attachedFuncs; + + ListenerValidationModel listenerValidationModel = new ListenerValidationModel(this, symTable); + return listenerValidationModel.checkMethods(rhsFuncs); + + } + + public boolean isValidErrorDetailType(BType detailType) { + return switch (getImpliedType(detailType).tag) { + case TypeTags.MAP, TypeTags.RECORD -> isAssignable(detailType, symTable.detailType); + default -> false; + }; + } + + // private methods + + private boolean isSealedRecord(BType recordType) { + return recordType.getKind() == TypeKind.RECORD && ((BRecordType) recordType).sealed; + } + + private boolean isNullable(BType fieldType) { + return fieldType.isNullable(); + } + + private class BSameTypeVisitor implements BTypeVisitor { + + Set unresolvedTypes; + + TypeEqualityPredicate equality; + + BSameTypeVisitor(Set unresolvedTypes, TypeEqualityPredicate equality) { + this.unresolvedTypes = unresolvedTypes; + this.equality = equality; + } + + @Override + public Boolean visit(BType target, BType source) { + BType t = getImpliedType(target); + BType s = getImpliedType(source); + if (t == s) { + return true; + } + + return switch (t.tag) { + case TypeTags.INT, + TypeTags.BYTE, + TypeTags.FLOAT, + TypeTags.DECIMAL, + TypeTags.STRING, + TypeTags.BOOLEAN -> t.tag == s.tag && + ((TypeParamAnalyzer.isTypeParam(t) || TypeParamAnalyzer.isTypeParam(s)) || + (t.tag == TypeTags.TYPEREFDESC || s.tag == TypeTags.TYPEREFDESC)); + case TypeTags.ANY, + TypeTags.ANYDATA -> t.tag == s.tag && hasSameReadonlyFlag(s, t) && + (TypeParamAnalyzer.isTypeParam(t) || TypeParamAnalyzer.isTypeParam(s)); + default -> false; + }; + } + + @Override + public Boolean visit(BBuiltInRefType t, BType s) { + return t == s; + } + + @Override + public Boolean visit(BAnyType t, BType s) { + return t == s; + } + + @Override + public Boolean visit(BAnydataType t, BType s) { + return t == s || t.tag == s.tag; + } + + @Override + public Boolean visit(BMapType t, BType s) { + return s.tag == TypeTags.MAP && hasSameReadonlyFlag(s, t) && + equality.test(((BMapType) s).constraint, t.constraint, this.unresolvedTypes); + } + + @Override + public Boolean visit(BFutureType t, BType s) { + return s.tag == TypeTags.FUTURE && + equality.test(((BFutureType) s).constraint, t.constraint, this.unresolvedTypes); + } + + @Override + public Boolean visit(BXMLType t, BType s) { + return visit((BBuiltInRefType) t, s); + } + + @Override + public Boolean visit(BJSONType t, BType s) { + return s.tag == TypeTags.JSON && hasSameReadonlyFlag(s, t); + } + + @Override + public Boolean visit(BArrayType t, BType s) { + return s.tag == TypeTags.ARRAY && hasSameReadonlyFlag(s, t) && isSameArrayType(s, t, this.unresolvedTypes); + } + + @Override + public Boolean visit(BObjectType t, BType s) { + return t == s || (s.tag == TypeTags.OBJECT && t.tsymbol.pkgID.equals(s.tsymbol.pkgID) && + t.tsymbol.name.equals(s.tsymbol.name)); + } + + @Override + public Boolean visit(BRecordType t, BType s) { + if (t == s) { + return true; + } + + if (s.tag != TypeTags.RECORD || !hasSameReadonlyFlag(s, t)) { + return false; + } + + BRecordType source = (BRecordType) s; + LinkedHashMap sFields = source.fields; + LinkedHashMap tFields = t.fields; + + if (sFields.size() != tFields.size()) { + return false; + } + + for (BField sourceField : sFields.values()) { + if (tFields.containsKey(sourceField.name.value)) { + BField targetField = tFields.get(sourceField.name.value); + if ((!Symbols.isFlagOn(targetField.symbol.flags, Flags.READONLY) || + Symbols.isFlagOn(sourceField.symbol.flags, Flags.READONLY)) && + hasSameOptionalFlag(sourceField.symbol, targetField.symbol) && + equality.test(sourceField.type, targetField.type, new HashSet<>(this.unresolvedTypes))) { + continue; + } + } + return false; + } + return equality.test(source.restFieldType, t.restFieldType, new HashSet<>(this.unresolvedTypes)); + } + + private boolean hasSameOptionalFlag(BVarSymbol s, BVarSymbol t) { + return ((s.flags & Flags.OPTIONAL) ^ (t.flags & Flags.OPTIONAL)) != Flags.OPTIONAL; + } + + boolean hasSameReadonlyFlag(BType source, BType target) { + return Symbols.isFlagOn(target.flags, Flags.READONLY) == Symbols.isFlagOn(source.flags, Flags.READONLY); + } + + @Override + public Boolean visit(BTupleType t, BType s) { + List tTupleTypes = t.getTupleTypes(); + if (((!tTupleTypes.isEmpty() && checkAllTupleMembersBelongNoType(tTupleTypes)) || + (t.restType != null && t.restType.tag == TypeTags.NONE)) && + !(s.tag == TypeTags.ARRAY && ((BArrayType) s).state == BArrayState.OPEN)) { + return true; + } + + if (s.tag != TypeTags.TUPLE || !hasSameReadonlyFlag(s, t)) { + return false; + } + + BTupleType source = (BTupleType) s; + List sTupleTypes = source.getTupleTypes(); + if (sTupleTypes.size() != tTupleTypes.size()) { + return false; + } + + BType sourceRestType = source.restType; + BType targetRestType = t.restType; + if ((sourceRestType == null || targetRestType == null) && sourceRestType != targetRestType) { + return false; + } + + for (int i = 0; i < sTupleTypes.size(); i++) { + if (tTupleTypes.get(i) == symTable.noType) { + continue; + } + if (!equality.test(sTupleTypes.get(i), tTupleTypes.get(i), + new HashSet<>(this.unresolvedTypes))) { + return false; + } + } + + if (sourceRestType == null || targetRestType == symTable.noType) { + return true; + } + + return equality.test(sourceRestType, targetRestType, new HashSet<>(this.unresolvedTypes)); + } + + @Override + public Boolean visit(BStreamType t, BType s) { + if (s.tag != TypeTags.STREAM) { + return false; + } + + BStreamType source = (BStreamType) s; + return equality.test(source.constraint, t.constraint, unresolvedTypes) + && equality.test(source.completionType, t.completionType, unresolvedTypes); + } + + @Override + public Boolean visit(BTableType t, BType s) { + return t == s; + } + + @Override + public Boolean visit(BInvokableType t, BType s) { + return s.tag == TypeTags.INVOKABLE && + checkFunctionTypeEquality((BInvokableType) s, t, this.unresolvedTypes, equality); + } + + @Override + public Boolean visit(BUnionType tUnionType, BType s) { + if (s.tag != TypeTags.UNION || !hasSameReadonlyFlag(s, tUnionType)) { + return false; + } + + BUnionType sUnionType = (BUnionType) s; + + if (sUnionType.getMemberTypes().size() + != tUnionType.getMemberTypes().size()) { + return false; + } + + Set sourceTypes = new LinkedHashSet<>(sUnionType.getMemberTypes().size()); + Set targetTypes = new LinkedHashSet<>(tUnionType.getMemberTypes().size()); + + if (sUnionType.isCyclic) { + sourceTypes.add(sUnionType); + } + if (tUnionType.isCyclic) { + targetTypes.add(tUnionType); + } + + sourceTypes.addAll(sUnionType.getMemberTypes()); + targetTypes.addAll(tUnionType.getMemberTypes()); + + boolean notSameType = sourceTypes + .stream() + .map(sT -> targetTypes + .stream() + .anyMatch(it -> equality.test(sT, it, new HashSet<>(this.unresolvedTypes)))) + .anyMatch(foundSameType -> !foundSameType); + return !notSameType; + } + + @Override + public Boolean visit(BIntersectionType tIntersectionType, BType s) { + if (s.tag != TypeTags.INTERSECTION) { + return false; + } + return visit(tIntersectionType.effectiveType, ((BIntersectionType) s).effectiveType); + } + + @Override + public Boolean visit(BErrorType t, BType s) { + if (s.tag != TypeTags.ERROR) { + return false; + } + BErrorType source = (BErrorType) s; + + if (!source.typeIdSet.equals(t.typeIdSet)) { + return false; + } + + if (source.detailType == t.detailType) { + return true; + } + + return equality.test(source.detailType, t.detailType, this.unresolvedTypes); + } + + @Override + public Boolean visit(BTypedescType t, BType s) { + if (s.tag != TypeTags.TYPEDESC) { + return false; + } + BTypedescType sType = ((BTypedescType) s); + return equality.test(sType.constraint, t.constraint, this.unresolvedTypes); + } + + @Override + public Boolean visit(BFiniteType t, BType s) { + return s == t; + } + + @Override + public Boolean visit(BParameterizedType t, BType s) { + if (s.tag != TypeTags.PARAMETERIZED_TYPE) { + return false; + } + + BParameterizedType sType = (BParameterizedType) s; + return sType.paramSymbol.equals(t.paramSymbol) && + equality.test(sType.paramValueType, t.paramValueType, new HashSet<>()); + } + + public Boolean visit(BTypeReferenceType t, BType s) { + BType constraint = s; + if (s.tag == TypeTags.TYPEREFDESC) { + constraint = getImpliedType(((BTypeReferenceType) s).referredType); + } + BType target = getImpliedType(t.referredType); + return equality.test(target, constraint, new HashSet<>()); + } + } + + @Deprecated + public boolean isSameBIRShape(BType source, BType target) { + return isSameBIRShape(source, target, new HashSet<>()); + } + + private boolean isSameBIRShape(BType source, BType target, Set unresolvedTypes) { + // If we encounter two types that we are still resolving, then skip it. + // This is done to avoid recursive checking of the same type. + TypePair pair = new TypePair(source, target); + if (!unresolvedTypes.add(pair)) { + return true; + } + + BIRSameShapeVisitor birSameShapeVisitor = new BIRSameShapeVisitor(unresolvedTypes, this::isSameBIRShape); + + if (target.accept(birSameShapeVisitor, source)) { + return true; + } + + unresolvedTypes.remove(pair); + return false; + } + + @Deprecated + private class BIRSameShapeVisitor extends BSameTypeVisitor { + + BIRSameShapeVisitor(Set unresolvedTypes, TypeEqualityPredicate equality) { + super(unresolvedTypes, equality); + } + + @Override + public Boolean visit(BType target, BType source) { + if (source.tag == TypeTags.TYPEREFDESC || target.tag == TypeTags.TYPEREFDESC) { + if (source.tag != target.tag) { + return false; + } + + BTypeReferenceType sourceRefType = (BTypeReferenceType) source; + BTypeReferenceType targetRefType = (BTypeReferenceType) target; + + BTypeSymbol sourceTSymbol = sourceRefType.tsymbol; + BTypeSymbol targetTSymbol = targetRefType.tsymbol; + String sourcePkgId = CompilerUtils.getPackageIDStringWithMajorVersion(sourceTSymbol.pkgID); + String targetPkgId = CompilerUtils.getPackageIDStringWithMajorVersion(targetTSymbol.pkgID); + return sourcePkgId.equals(targetPkgId) && sourceTSymbol.name.equals(targetTSymbol.name); + } + + BType t = getImpliedType(target); + BType s = getImpliedType(source); + if (t == s) { + return true; + } + return switch (t.tag) { + case TypeTags.INT, + TypeTags.BYTE, + TypeTags.FLOAT, + TypeTags.DECIMAL, + TypeTags.STRING, + TypeTags.BOOLEAN -> t.tag == s.tag && + ((TypeParamAnalyzer.isTypeParam(t) || TypeParamAnalyzer.isTypeParam(s)) || + (t.tag == TypeTags.TYPEREFDESC || s.tag == TypeTags.TYPEREFDESC)); + case TypeTags.ANY, + TypeTags.ANYDATA -> t.tag == s.tag && hasSameReadonlyFlag(s, t) && + (TypeParamAnalyzer.isTypeParam(t) || TypeParamAnalyzer.isTypeParam(s)); + default -> false; + }; + + } + + @Override + public Boolean visit(BFiniteType t, BType s) { + s = getImpliedType(s); + if (s.tag != TypeTags.FINITE) { + return false; + } + + Set sourceValueSpace = ((BFiniteType) s).getValueSpace(); + Set targetValueSpace = t.getValueSpace(); + + if (sourceValueSpace.size() != targetValueSpace.size()) { + return false; + } + + return hasSameMembers(sourceValueSpace, targetValueSpace); } - BInvokableSymbol iteratorSymbol = (BInvokableSymbol) symResolver.lookupLangLibMethod(collectionType, - Names.fromString(BLangCompilerConstants.ITERABLE_COLLECTION_ITERATOR_FUNC), env); - BObjectType objectType = (BObjectType) getImpliedType(iteratorSymbol.retType); - BUnionType nextMethodReturnType = - (BUnionType) getResultTypeOfNextInvocation(objectType); - foreachNode.varType = varType; - foreachNode.resultType = getRecordType(nextMethodReturnType); - foreachNode.nillableResultType = nextMethodReturnType; - } + @Override + public Boolean visit(BTypeReferenceType t, BType s) { + s = getImpliedType(s); + if (s.tag != TypeTags.TYPEREFDESC) { + return false; + } - public void setInputClauseTypedBindingPatternType(BLangInputClause bLangInputClause) { - if (bLangInputClause.collection == null) { - //not-possible - return; + BTypeReferenceType sTypeRefType = (BTypeReferenceType) s; + + BTypeSymbol sourceTSymbol = sTypeRefType.tsymbol; + BTypeSymbol targetTSymbol = t.tsymbol; + String sourcePkgId = CompilerUtils.getPackageIDStringWithMajorVersion(sourceTSymbol.pkgID); + String targetPkgId = CompilerUtils.getPackageIDStringWithMajorVersion(targetTSymbol.pkgID); + return sourcePkgId.equals(targetPkgId) && sourceTSymbol.name.equals(targetTSymbol.name); } + } - BType collectionType = bLangInputClause.collection.getBType(); - bLangInputClause.varType = visitCollectionType(bLangInputClause, collectionType); - if (bLangInputClause.varType.tag == TypeTags.SEMANTIC_ERROR || - getImpliedType(collectionType).tag == OBJECT) { - return; + private boolean hasSameMembers(Set sourceValueSpace, Set targetValueSpace) { + Set setOne = new HashSet<>(sourceValueSpace); + Set setTwo = new HashSet<>(targetValueSpace); + + Iterator setOneIterator = setOne.iterator(); + Iterator setTwoIterator = setTwo.iterator(); + + while (setOneIterator.hasNext()) { + BLangLiteral setOneMem = (BLangLiteral) setOneIterator.next(); + + if (!setTwoIterator.hasNext()) { + return false; + } + + boolean hasEqualValue = false; + while (setTwoIterator.hasNext()) { + BLangLiteral setTwoMem = (BLangLiteral) setTwoIterator.next(); + if (setOneMem.value.equals(setTwoMem.value) && setOneMem.getBType() == setTwoMem.getBType()) { + hasEqualValue = true; + setOneIterator.remove(); + setTwoIterator.remove(); + break; + } + } + + if (!hasEqualValue) { + return false; + } } - - BInvokableSymbol iteratorSymbol = (BInvokableSymbol) symResolver.lookupLangLibMethod(collectionType, - Names.fromString(BLangCompilerConstants.ITERABLE_COLLECTION_ITERATOR_FUNC), env); - BUnionType nextMethodReturnType = - (BUnionType) getResultTypeOfNextInvocation((BObjectType) getImpliedType(iteratorSymbol.retType)); - bLangInputClause.resultType = getRecordType(nextMethodReturnType); - bLangInputClause.nillableResultType = nextMethodReturnType; + + return !setTwoIterator.hasNext(); } - private BType getTypedBindingPatternTypeForXmlCollection(BType collectionType) { - BType constraint = getImpliedType(((BXMLType) collectionType).constraint); - while (constraint.tag == TypeTags.XML) { - collectionType = constraint; - constraint = getImpliedType(((BXMLType) collectionType).constraint); + private class BOrderedTypeVisitor implements BTypeVisitor { + + Set unresolvedTypes; + + BOrderedTypeVisitor(Set unresolvedTypes) { + this.unresolvedTypes = unresolvedTypes; } - switch (constraint.tag) { - case TypeTags.XML_ELEMENT: - case TypeTags.XML_COMMENT: - case TypeTags.XML_TEXT: - case TypeTags.XML_PI: - case TypeTags.NEVER: - return constraint; - case TypeTags.UNION: - Set collectionTypes = getEffectiveMemberTypes((BUnionType) constraint); - Set builtinXMLConstraintTypes = getEffectiveMemberTypes - ((BUnionType) ((BXMLType) symTable.xmlType).constraint); - return collectionTypes.size() == 4 && builtinXMLConstraintTypes.equals(collectionTypes) ? - collectionType : - BUnionType.create(typeEnv(), null, (LinkedHashSet) collectionTypes); - default: - return null; + @Override + public Boolean visit(BType target, BType source) { + BType sourceType = getImpliedType(source); + BType targetType = getImpliedType(target); + int sourceTag = sourceType.tag; + int targetTag = targetType.tag; + if (isSimpleBasicType(sourceTag) && isSimpleBasicType(targetTag)) { + // If type T is ordered, then type T? Is also ordered. + return (source == target) || sourceTag == TypeTags.NIL || targetTag == TypeTags.NIL || + isIntOrStringType(sourceTag, targetTag); + } + if (sourceTag == TypeTags.FINITE) { + return checkValueSpaceHasSameType(((BFiniteType) source), target); + } + return isSameOrderedType(target, source, this.unresolvedTypes); } - } - private BType visitCollectionType(BLangInputClause bLangInputClause, BType collectionType) { - collectionType = getImpliedType(collectionType); - switch (collectionType.tag) { - case TypeTags.STRING: - return symTable.stringType; - case TypeTags.ARRAY: - BArrayType arrayType = (BArrayType) collectionType; - return arrayType.eType; - case TypeTags.TUPLE: - return getTupleMemberType((BTupleType) collectionType); - case TypeTags.MAP: - BMapType bMapType = (BMapType) collectionType; - return bMapType.constraint; - case TypeTags.RECORD: - BRecordType recordType = (BRecordType) collectionType; - return inferRecordFieldType(recordType); - case TypeTags.XML: - BType bindingPatternType = getTypedBindingPatternTypeForXmlCollection(collectionType); - return bindingPatternType == null ? symTable.semanticError : bindingPatternType; - case TypeTags.XML_TEXT: - return symTable.xmlTextType; - case TypeTags.TABLE: - BTableType tableType = (BTableType) collectionType; - return tableType.constraint; - case TypeTags.STREAM: - BStreamType streamType = (BStreamType) collectionType; - if (streamType.constraint.tag == TypeTags.NONE) { - return symTable.anydataType; + @Override + public Boolean visit(BArrayType target, BType source) { + source = getImpliedType(source); + if (source.tag != TypeTags.ARRAY) { + if (source.tag == TypeTags.TUPLE || source.tag == TypeTags.UNION) { + return isSameOrderedType(target, source); } - return streamType.constraint; - case TypeTags.OBJECT: - // check for iterable objects - if (!isAssignable(collectionType, symTable.iterableType)) { - dlog.error(bLangInputClause.collection.pos, DiagnosticErrorCode.INVALID_ITERABLE_OBJECT_TYPE, - bLangInputClause.collection.getBType(), symTable.iterableType); - bLangInputClause.varType = symTable.semanticError; - bLangInputClause.resultType = symTable.semanticError; - bLangInputClause.nillableResultType = symTable.semanticError; - break; + return false; + } + return isSameOrderedType(target.eType, ((BArrayType) source).eType, unresolvedTypes); + } + + @Override + public Boolean visit(BTupleType target, BType source) { + source = getImpliedType(source); + if (source.tag == TypeTags.UNION) { + return isSameOrderedType(target, source); + } + if (source.tag != TypeTags.TUPLE && source.tag != TypeTags.ARRAY) { + return false; + } + List targetTupleTypes = target.getTupleTypes(); + BType targetRestType = target.restType; + + if (source.tag == TypeTags.ARRAY) { + // Check whether the element type of the source array has same ordered type with each member type in + // target tuple type. + BType eType = ((BArrayType) source).eType; + for (BType memberType : targetTupleTypes) { + if (!isSameOrderedType(eType, memberType, this.unresolvedTypes)) { + return false; + } } - - BUnionType nextMethodReturnType = getVarTypeFromIterableObject((BObjectType) collectionType); - if (nextMethodReturnType != null) { - bLangInputClause.resultType = getRecordType(nextMethodReturnType); - bLangInputClause.nillableResultType = nextMethodReturnType; - bLangInputClause.varType = ((BRecordType) bLangInputClause.resultType).fields.get("value").type; - return bLangInputClause.varType; + if (targetRestType == null) { + return true; } - // fallthrough - case TypeTags.SEMANTIC_ERROR: - bLangInputClause.varType = symTable.semanticError; - bLangInputClause.resultType = symTable.semanticError; - bLangInputClause.nillableResultType = symTable.semanticError; - break; - default: - bLangInputClause.varType = symTable.semanticError; - bLangInputClause.resultType = symTable.semanticError; - bLangInputClause.nillableResultType = symTable.semanticError; - dlog.error(bLangInputClause.collection.pos, DiagnosticErrorCode.ITERABLE_NOT_SUPPORTED_COLLECTION, - collectionType); + return isSameOrderedType(targetRestType, eType, this.unresolvedTypes); + } + + BTupleType sourceT = (BTupleType) source; + List sourceTupleTypes = sourceT.getTupleTypes(); + + BType sourceRestType = sourceT.restType; + + int sourceTupleCount = sourceTupleTypes.size(); + int targetTupleCount = targetTupleTypes.size(); + + int len = Math.min(sourceTupleCount, targetTupleCount); + for (int i = 0; i < len; i++) { + // Check whether the corresponding member types are same ordered type. + if (!isSameOrderedType(sourceTupleTypes.get(i), targetTupleTypes.get(i), + this.unresolvedTypes)) { + return false; + } + } + + if (sourceTupleCount == targetTupleCount) { + if (sourceRestType == null || targetRestType == null) { + return true; + } + return isSameOrderedType(sourceRestType, targetRestType, this.unresolvedTypes); + } else if (sourceTupleCount > targetTupleCount) { + // Source tuple has higher number of member types. + // Check whether the excess member types can be narrowed to an ordered rest type in source tuple. + // Ex. source tuple -> [string, (), float, int, byte] + // target tuple -> [string, (), float] + // here, source tuple can be represented as [string, (), float, int...] + // since [string, (), float] & [string, (), float, int...] are individually order types and + // [string, (), float, int...] can be taken as the ordered type which the static type of both + // operands belong. + if (!hasCommonOrderedTypeForTuples(sourceTupleTypes, targetTupleCount + 1)) { + return false; + } + return checkSameOrderedTypeInTuples(sourceT, sourceTupleCount, targetTupleCount, sourceRestType, + targetRestType); + } else { + // Target tuple has higher number of member types. + if (!hasCommonOrderedTypeForTuples(targetTupleTypes, sourceTupleCount + 1)) { + return false; + } + return checkSameOrderedTypeInTuples(target, targetTupleCount, sourceTupleCount, targetRestType, + sourceRestType); + } } - return symTable.semanticError; - } - private BType getTupleMemberType(BTupleType tupleType) { - LinkedHashSet tupleTypes = new LinkedHashSet<>(tupleType.getTupleTypes()); - if (tupleType.restType != null) { - tupleTypes.add(tupleType.restType); + private boolean hasCommonOrderedTypeForTuples(List typeList, int startIndex) { + BType baseType = typeList.get(startIndex - 1); + for (int i = startIndex; i < typeList.size(); i++) { + if (isNil(baseType)) { + baseType = typeList.get(i); + continue; + } + if (!isSameOrderedType(baseType, typeList.get(i), this.unresolvedTypes)) { + return false; + } + } + return true; } - int tupleTypesSize = tupleTypes.size(); - if (tupleTypesSize == 0) { - return symTable.neverType; + + private boolean checkSameOrderedTypeInTuples(BTupleType source, int sourceTupleCount, + int targetTupleCount, + BType sourceRestType, BType targetRestType) { + if (targetRestType == null) { + return true; + } + for (int i = targetTupleCount; i < sourceTupleCount; i++) { + if (!isSameOrderedType(source.getTupleTypes().get(i), targetRestType, this.unresolvedTypes)) { + return false; + } + } + if (sourceRestType == null) { + return true; + } + return isSameOrderedType(sourceRestType, targetRestType, this.unresolvedTypes); } - return tupleTypesSize == 1 ? - tupleTypes.iterator().next() : BUnionType.create(typeEnv(), null, tupleTypes); - } - public BUnionType getVarTypeFromIterableObject(BObjectType collectionType) { - BObjectTypeSymbol objectTypeSymbol = (BObjectTypeSymbol) collectionType.tsymbol; - for (BAttachedFunction func : objectTypeSymbol.attachedFuncs) { - if (func.funcName.value.equals(BLangCompilerConstants.ITERABLE_COLLECTION_ITERATOR_FUNC)) { - return getVarTypeFromIteratorFunc(func); + @Override + public Boolean visit(BUnionType target, BType source) { + source = getImpliedType(source); + if (source.tag != TypeTags.UNION || !hasSameReadonlyFlag(source, target)) { + return checkUnionHasSameType(target, source); + } + + BUnionType sUnionType = (BUnionType) source; + LinkedHashSet sourceTypes = sUnionType.getMemberTypes(); + LinkedHashSet targetTypes = target.getMemberTypes(); + + if (checkUnionHasAllFiniteOrNilMembers(sourceTypes) && + checkUnionHasAllFiniteOrNilMembers(targetTypes)) { + BType type = target.getMemberTypes().iterator().next(); + return checkValueSpaceHasSameType(((BFiniteType) getImpliedType(type)), + sUnionType.getMemberTypes().iterator().next()); } + + return checkSameOrderedTypesInUnionMembers(sourceTypes, targetTypes); } - return null; - } + private boolean checkSameOrderedTypesInUnionMembers(LinkedHashSet sourceTypes, + LinkedHashSet targetTypes) { - private BUnionType getVarTypeFromIteratorFunc(BAttachedFunction candidateIteratorFunc) { - if (!candidateIteratorFunc.type.paramTypes.isEmpty()) { - return null; + for (BType sourceT : sourceTypes) { + boolean foundSameOrderedType = false; + if (isNil(sourceT)) { + continue; + } + for (BType targetT : targetTypes) { + if (isNil(targetT)) { + foundSameOrderedType = true; + continue; + } + if (isSameOrderedType(targetT, sourceT, this.unresolvedTypes)) { + foundSameOrderedType = true; + } else { + return false; + } + } + if (!foundSameOrderedType) { + return false; + } + } + return true; } - BType returnType = candidateIteratorFunc.type.retType; - // abstract object {public function next() returns record {|int value;|}?;} - return getVarTypeFromIteratorFuncReturnType(returnType); - } + @Override + public Boolean visit(BFiniteType t, BType s) { + return checkValueSpaceHasSameType(t, s); + } - public BUnionType getVarTypeFromIteratorFuncReturnType(BType type) { - BObjectTypeSymbol objectTypeSymbol; - BType returnType = getImpliedType(type); - if (returnType.tag != TypeTags.OBJECT) { - return null; + private boolean hasSameReadonlyFlag(BType source, BType target) { + return Symbols.isFlagOn(target.flags, Flags.READONLY) == Symbols.isFlagOn(source.flags, Flags.READONLY); } - objectTypeSymbol = (BObjectTypeSymbol) returnType.tsymbol; - for (BAttachedFunction func : objectTypeSymbol.attachedFuncs) { - if (func.funcName.value.equals(BLangCompilerConstants.NEXT_FUNC)) { - return getVarTypeFromNextFunc(func); - } + @Override + public Boolean visit(BBuiltInRefType t, BType s) { + return false; } - return null; - } + @Override + public Boolean visit(BAnyType t, BType s) { + return false; + } - private BUnionType getVarTypeFromNextFunc(BAttachedFunction nextFunc) { - BType returnType; - if (!nextFunc.type.paramTypes.isEmpty()) { - return null; + @Override + public Boolean visit(BAnydataType t, BType s) { + return false; } - returnType = nextFunc.type.retType; - // Check if the next function return type has the union type, - // record {|int value;|}|error|(); - if (checkNextFuncReturnType(returnType)) { - return (BUnionType) returnType; + @Override + public Boolean visit(BMapType t, BType s) { + return false; } - return null; - } + @Override + public Boolean visit(BFutureType t, BType s) { + return false; + } - private boolean checkNextFuncReturnType(BType returnType) { - if (getImpliedType(returnType).tag != TypeTags.UNION) { + @Override + public Boolean visit(BXMLType t, BType s) { return false; } - List types = getAllTypes(returnType, true); - boolean containsCompletionType = types.removeIf(type -> type.tag == TypeTags.NIL); - containsCompletionType = types.removeIf(type -> type.tag == TypeTags.ERROR) || containsCompletionType; - if (!containsCompletionType) { + @Override + public Boolean visit(BJSONType t, BType s) { + return false; + } + + + @Override + public Boolean visit(BObjectType t, BType s) { + return false; + } + + @Override + public Boolean visit(BRecordType t, BType s) { return false; } - if (types.size() != 1) { - //TODO: print error + @Override + public Boolean visit(BStreamType t, BType s) { return false; } - if (types.get(0).tag != TypeTags.RECORD) { + @Override + public Boolean visit(BTableType t, BType s) { return false; } - BRecordType recordType = (BRecordType) types.get(0); - // Check if the union type has the record type, - // record {|int value;|}; - return checkRecordTypeInNextFuncReturnType(recordType); - } - - private boolean checkRecordTypeInNextFuncReturnType(BRecordType recordType) { - if (!recordType.sealed) { + @Override + public Boolean visit(BInvokableType t, BType s) { return false; } - if (recordType.fields.size() != 1) { - return false; + @Override + public Boolean visit(BIntersectionType tIntersectionType, BType s) { + return this.visit(getImpliedType(tIntersectionType), s); } - return recordType.fields.containsKey(BLangCompilerConstants.VALUE_FIELD); - } + @Override + public Boolean visit(BErrorType t, BType s) { + return false; + } - private BRecordType getRecordType(BUnionType type) { - for (BType member : type.getMemberTypes()) { - BType referredRecordType = getImpliedType(member); - if (referredRecordType.tag == TypeTags.RECORD) { - return (BRecordType) referredRecordType; - } + @Override + public Boolean visit(BTypedescType t, BType s) { + return false; } - return null; - } - public BErrorType getErrorType(BUnionType type) { - for (BType member : type.getMemberTypes()) { - member = getImpliedType(member); + public Boolean visit(BTypeReferenceType t, BType s) { + return this.visit(getImpliedType(t), t); + } - if (member.tag == TypeTags.ERROR) { - return (BErrorType) member; - } else if (member.tag == TypeTags.UNION) { - BErrorType e = getErrorType((BUnionType) member); - if (e != null) { - return e; - } - } + @Override + public Boolean visit(BParameterizedType t, BType s) { + return false; } - return null; } - public BType getResultTypeOfNextInvocation(BObjectType iteratorType) { - BAttachedFunction nextFunc = getAttachedFuncFromObject(iteratorType, BLangCompilerConstants.NEXT_FUNC); - return Objects.requireNonNull(nextFunc).type.retType; + private boolean isNil(BType type) { + // Currently, type reference for `null` literal is taken as Finite type and type reference for `()` literal + // taken as Nil type. + BType referredType = getImpliedType(type); + TypeKind referredTypeKind = referredType.getKind(); + if (referredTypeKind == TypeKind.NIL) { + return true; + } else if (referredTypeKind == TypeKind.FINITE) { + Set valueSpace = ((BFiniteType) referredType).getValueSpace(); + return valueSpace.size() == 1 && valueSpace.iterator().next().getBType().getKind() == TypeKind.NIL; + } + return false; } - public BAttachedFunction getAttachedFuncFromObject(BObjectType objectType, String funcName) { - BObjectTypeSymbol iteratorSymbol = (BObjectTypeSymbol) objectType.tsymbol; - for (BAttachedFunction bAttachedFunction : iteratorSymbol.attachedFuncs) { - if (funcName.equals(bAttachedFunction.funcName.value)) { - return bAttachedFunction; + private boolean checkUnionHasSameType(BUnionType unionType, BType baseType) { + LinkedHashSet memberTypes = unionType.getMemberTypes(); + for (BType type : memberTypes) { + type = getImpliedType(type); + if (type.tag == TypeTags.FINITE) { + for (BLangExpression expr : ((BFiniteType) type).getValueSpace()) { + if (!isSameOrderedType(expr.getBType(), baseType)) { + return false; + } + } +// } else if (type.tag == TypeTags.UNION) { +// if (!checkUnionHasSameType((BUnionType) type, baseType)) { +// return false; +// } + } else if (type.tag == TypeTags.TUPLE || type.tag == TypeTags.ARRAY) { + if (!isSameOrderedType(type, baseType)) { + return false; + } + } else if (isSimpleBasicType(type.tag)) { + if (!isSameOrderedType(type, baseType) && !isNil(type)) { + return false; + } } } - return null; + return true; } - public BType inferRecordFieldType(BRecordType recordType) { - Map fields = recordType.fields; - BUnionType unionType = BUnionType.create(typeEnv(), null); - - if (!recordType.sealed) { - unionType.add(recordType.restFieldType); - } else if (fields.isEmpty()) { - unionType.add(symTable.neverType); + private boolean checkValueSpaceHasSameType(BFiniteType finiteType, BType type) { + BType baseType = getImpliedType(type); + if (baseType.tag == TypeTags.FINITE) { + BType baseExprType = finiteType.getValueSpace().iterator().next().getBType(); + return checkValueSpaceHasSameType(((BFiniteType) baseType), baseExprType); } - - for (BField field : fields.values()) { - if (isAssignable(field.type, unionType)) { - continue; - } - - if (isAssignable(unionType, field.type)) { - unionType = BUnionType.create(typeEnv(), null); + boolean isValueSpaceSameType = false; + for (BLangExpression expr : finiteType.getValueSpace()) { + isValueSpaceSameType = isSameOrderedType(expr.getBType(), baseType); + if (!isValueSpaceSameType) { + break; } - - unionType.add(field.type); } + return isValueSpaceSameType; + } - if (unionType.getMemberTypes().size() > 1) { - unionType.tsymbol = Symbols.createTypeSymbol(SymTag.UNION_TYPE, Flags.asMask(EnumSet.of(Flag.PUBLIC)), - Names.EMPTY, recordType.tsymbol.pkgID, null, - recordType.tsymbol.owner, symTable.builtinPos, VIRTUAL); - return unionType; + private boolean checkUnionHasAllFiniteOrNilMembers(LinkedHashSet memberTypes) { + for (BType bType : memberTypes) { + BType type = getImpliedType(bType); + if (type.tag != TypeTags.FINITE && !isNil(type)) { + return false; + } } - - return unionType.getMemberTypes().iterator().next(); + return true; } + private boolean checkFieldEquivalency(BRecordType lhsType, BRecordType rhsType, Set unresolvedTypes) { + Map rhsFields = new LinkedHashMap<>(rhsType.fields); - public BType getTypeWithEffectiveIntersectionTypes(BType bType) { - // TODO Can remove this method since this unwraps the referred type and intersection type. #40958 - BType type = getReferredType(bType); - BType effectiveType = null; - if (type.tag == TypeTags.INTERSECTION) { - effectiveType = ((BIntersectionType) type).effectiveType; - type = effectiveType; - } + // Check if the RHS record has corresponding fields to those of the LHS record. + for (BField lhsField : lhsType.fields.values()) { + BField rhsField = rhsFields.get(lhsField.name.value); - if (type.tag != TypeTags.UNION) { - return Objects.requireNonNullElse(effectiveType, bType); - } + // If LHS field is required, there should be a corresponding RHS field + // If LHS field is never typed, RHS rest field type should include never type + if (rhsField == null) { + if (!Symbols.isOptional(lhsField.symbol) || isInvalidNeverField(lhsField, rhsType)) { + return false; + } - LinkedHashSet members = new LinkedHashSet<>(); - boolean hasDifferentMember = false; + if (!rhsType.sealed && !isAssignable(rhsType.restFieldType, lhsField.type, unresolvedTypes)) { + return false; + } - for (BType memberType : ((BUnionType) type).getMemberTypes()) { - effectiveType = getTypeWithEffectiveIntersectionTypes(memberType); - effectiveType = getImpliedType(effectiveType); - if (effectiveType != memberType) { - hasDifferentMember = true; + continue; + } + if (hasIncompatibleReadOnlyFlags(lhsField.symbol.flags, rhsField.symbol.flags)) { + return false; } - members.add(effectiveType); - } - - if (hasDifferentMember) { - return BUnionType.create(typeEnv(), null, members); - } - return bType; - } - - /** - * Enum to represent type test result. - * - * @since 1.2.0 - */ - enum TypeTestResult { - NOT_FOUND, - TRUE, - FALSE - } - TypeTestResult isBuiltInTypeWidenPossible(BType actualType, BType targetType) { // TODO: can we remove? - int targetTag = getImpliedType(targetType).tag; - int actualTag = getImpliedType(actualType).tag; + // If LHS field is required, so should the RHS field + if (!Symbols.isOptional(lhsField.symbol) && Symbols.isOptional(rhsField.symbol)) { + return false; + } - if (actualTag < TypeTags.JSON && targetTag < TypeTags.JSON) { - // Fail Fast for value types. - switch (actualTag) { - case TypeTags.INT: - case TypeTags.BYTE: - case TypeTags.FLOAT: - case TypeTags.DECIMAL: - if (targetTag == TypeTags.BOOLEAN || targetTag == TypeTags.STRING) { - return TypeTestResult.FALSE; - } - break; - case TypeTags.BOOLEAN: - if (targetTag == TypeTags.INT || targetTag == TypeTags.BYTE || targetTag == TypeTags.FLOAT - || targetTag == TypeTags.DECIMAL || targetTag == TypeTags.STRING) { - return TypeTestResult.FALSE; - } - break; - case TypeTags.STRING: - if (targetTag == TypeTags.INT || targetTag == TypeTags.BYTE || targetTag == TypeTags.FLOAT - || targetTag == TypeTags.DECIMAL || targetTag == TypeTags.BOOLEAN) { - return TypeTestResult.FALSE; - } - break; + // The corresponding RHS field should be assignable to the LHS field. + if (!isAssignable(rhsField.type, lhsField.type, unresolvedTypes)) { + return false; } - } - switch (actualTag) { - case TypeTags.INT: - case TypeTags.BYTE: - case TypeTags.FLOAT: - case TypeTags.DECIMAL: - case TypeTags.BOOLEAN: - case TypeTags.STRING: - case TypeTags.SIGNED32_INT: - case TypeTags.SIGNED16_INT: - case TypeTags.SIGNED8_INT: - case TypeTags.UNSIGNED32_INT: - case TypeTags.UNSIGNED16_INT: - case TypeTags.UNSIGNED8_INT: - case TypeTags.CHAR_STRING: - if (targetTag == TypeTags.JSON || targetTag == TypeTags.ANYDATA || targetTag == TypeTags.ANY || - targetTag == TypeTags.READONLY) { - return TypeTestResult.TRUE; - } - break; - case TypeTags.ANYDATA: - case TypeTags.TYPEDESC: - if (targetTag == TypeTags.ANY) { - return TypeTestResult.TRUE; - } - break; - default: - } - if (TypeTags.isIntegerTypeTag(targetTag) && actualTag == targetTag) { - return TypeTestResult.FALSE; // No widening. + rhsFields.remove(lhsField.name.value); } - // Validate for Integers subtypes. - if ((TypeTags.isIntegerTypeTag(actualTag) || actualTag == TypeTags.BYTE) - && (TypeTags.isIntegerTypeTag(targetTag) || targetTag == TypeTags.BYTE)) { - return checkBuiltInIntSubtypeWidenPossible(actualType, targetType); + if (lhsType.sealed) { + for (BField field : rhsFields.values()) { + if (!isNeverTypeOrStructureTypeWithARequiredNeverMember(field.type)) { + return false; + } + } + return true; } - if (actualTag == TypeTags.CHAR_STRING && TypeTags.STRING == targetTag) { - return TypeTestResult.TRUE; + // If there are any remaining RHS fields, the types of those should be assignable to the rest field type of + // the LHS record. + BType lhsRestFieldType = lhsType.restFieldType; + for (BField field : rhsFields.values()) { + if (!isAssignable(field.type, lhsRestFieldType, unresolvedTypes)) { + return false; + } } - return TypeTestResult.NOT_FOUND; + return true; } - private TypeTestResult checkBuiltInIntSubtypeWidenPossible(BType actualType, BType targetType) { - int actualTag = getImpliedType(actualType).tag; - targetType = getImpliedType(targetType); - switch (targetType.tag) { - case TypeTags.INT: - if (actualTag == TypeTags.BYTE || TypeTags.isIntegerTypeTag(actualTag)) { - return TypeTestResult.TRUE; - } - break; - case TypeTags.SIGNED32_INT: - if (actualTag == TypeTags.SIGNED16_INT || actualTag == TypeTags.SIGNED8_INT || - actualTag == TypeTags.UNSIGNED16_INT || actualTag == TypeTags.UNSIGNED8_INT || - actualTag == TypeTags.BYTE) { - return TypeTestResult.TRUE; - } - break; - case TypeTags.SIGNED16_INT: - if (actualTag == TypeTags.SIGNED8_INT || actualTag == TypeTags.UNSIGNED8_INT || - actualTag == TypeTags.BYTE) { - return TypeTestResult.TRUE; - } - break; - case TypeTags.UNSIGNED32_INT: - if (actualTag == TypeTags.UNSIGNED16_INT || actualTag == TypeTags.UNSIGNED8_INT || - actualTag == TypeTags.BYTE) { - return TypeTestResult.TRUE; - } - break; - case TypeTags.UNSIGNED16_INT: - if (actualTag == TypeTags.UNSIGNED8_INT || actualTag == TypeTags.BYTE) { - return TypeTestResult.TRUE; - } - break; - case TypeTags.BYTE: - if (actualTag == TypeTags.UNSIGNED8_INT) { - return TypeTestResult.TRUE; - } - break; - case TypeTags.UNSIGNED8_INT: - if (actualTag == TypeTags.BYTE) { - return TypeTestResult.TRUE; - } + private boolean isInvalidNeverField(BField lhsField, BRecordType rhsType) { + if (getImpliedType(lhsField.type).tag != NEVER || rhsType.sealed) { + return false; } - return TypeTestResult.NOT_FOUND; + + BType restFieldType = rhsType.restFieldType; + return switch (restFieldType.tag) { + case TypeTags.UNION -> { + for (BType member : ((BUnionType) restFieldType).getOriginalMemberTypes()) { + if (getImpliedType(member).tag == NEVER) { + yield false; + } + } + yield true; + } + case NEVER -> false; + default -> true; + }; } - public boolean isImplicitlyCastable(BType actual, BType target) { - /* The word Builtin refers for Compiler known types. */ + private Optional getMatchingInvokableType(List rhsFuncList, + BAttachedFunction lhsFunc, + Set unresolvedTypes) { + Optional matchingFunction = rhsFuncList.stream() + .filter(rhsFunc -> lhsFunc.funcName.equals(rhsFunc.funcName)) + .filter(rhsFunc -> isFunctionTypeAssignable(rhsFunc.type, lhsFunc.type, unresolvedTypes)) + .findFirst(); - BType targetType = getImpliedType(target); - BType actualType = getImpliedType(actual); - BType newTargetType = targetType; - int targetTypeTag = targetType.tag; - if ((targetTypeTag == TypeTags.UNION || targetTypeTag == TypeTags.FINITE) && isValueType(actualType)) { - newTargetType = symTable.anyType; // TODO : Check for correctness. + if (matchingFunction.isEmpty()) { + return matchingFunction; } + // For resource function match, we need to check whether lhs function resource path type belongs to + // rhs function resource path type + BAttachedFunction matchingFunc = matchingFunction.get(); + // Todo: We could include this logic in `isFunctionTypeAssignable` if we have `resourcePathType` information in + // `BInvokableType` issue #37502 + boolean lhsFuncIsResource = Symbols.isResource(lhsFunc.symbol); + boolean matchingFuncIsResource = Symbols.isResource(matchingFunc.symbol); - TypeTestResult result = isBuiltInTypeWidenPossible(actualType, newTargetType); - if (result != TypeTestResult.NOT_FOUND) { - return result == TypeTestResult.TRUE; + if (!lhsFuncIsResource && !matchingFuncIsResource) { + return matchingFunction; } - if (isValueType(targetType) && - (actualType.tag == TypeTags.FINITE || - (actualType.tag == TypeTags.UNION && ((BUnionType) actualType).getMemberTypes().stream() - .anyMatch(type -> getImpliedType(type).tag == TypeTags.FINITE && - isAssignable(type, targetType))))) { - // for nil, no cast is required - return TypeTags.isIntegerTypeTag(targetTypeTag) || targetType.tag == TypeTags.BYTE || - targetTypeTag == TypeTags.FLOAT || - targetTypeTag == TypeTags.DECIMAL || - TypeTags.isStringTypeTag(targetTypeTag) || - targetTypeTag == TypeTags.BOOLEAN; + if (!lhsFuncIsResource || !matchingFuncIsResource) { + return Optional.empty(); + } - } else if (isValueType(targetType) && actualType.tag == TypeTags.UNION && - ((BUnionType) actualType).getMemberTypes().stream().allMatch(type -> isAssignable(type, targetType))) { - return true; + List lhsFuncPathTypes = ((BResourceFunction) lhsFunc).pathSegmentSymbols; + List rhsFuncPathTypes = ((BResourceFunction) matchingFunc).pathSegmentSymbols; - } else if (targetTypeTag == TypeTags.ERROR - && (actualType.tag == TypeTags.UNION - && isAllErrorMembers((BUnionType) actualType))) { - return true; + int lhsFuncResourcePathTypesSize = lhsFuncPathTypes.size(); + if (lhsFuncResourcePathTypesSize != rhsFuncPathTypes.size()) { + return Optional.empty(); } - return false; - } - public boolean isTypeCastable(BType source, BType target) { - BType sourceType = getImpliedType(source); - BType targetType = getImpliedType(target); - if (sourceType.tag == TypeTags.SEMANTIC_ERROR || targetType.tag == TypeTags.SEMANTIC_ERROR || - sourceType == targetType) { - return true; + for (int i = 0; i < lhsFuncResourcePathTypesSize; i++) { + if (!isAssignable(lhsFuncPathTypes.get(i).type, rhsFuncPathTypes.get(i).type)) { + return Optional.empty(); + } } - SemType sourceSemType = sourceType.semType(); - SemType targetSemType = targetType.semType(); + return matchingFunction; + } - // Disallow casting away error, this forces user to handle the error via type-test, check, or checkpanic - if (containsErrorType(sourceSemType) && !containsErrorType(targetSemType)) { - return false; + private boolean isInSameVisibilityRegion(BSymbol lhsSym, BSymbol rhsSym) { + if (Symbols.isPrivate(lhsSym)) { + return Symbols.isPrivate(rhsSym) && lhsSym.pkgID.equals(rhsSym.pkgID) + && lhsSym.owner.name.equals(rhsSym.owner.name); + } else if (Symbols.isPublic(lhsSym)) { + return Symbols.isPublic(rhsSym); } + return !Symbols.isPrivate(rhsSym) && !Symbols.isPublic(rhsSym) && lhsSym.pkgID.equals(rhsSym.pkgID); + } - if (isNumericConversionPossible(sourceType, targetType)) { + private boolean isAssignableToUnionType(BType source, BType target, Set unresolvedTypes) { + TypePair pair = new TypePair(source, target); + if (unresolvedTypes.contains(pair)) { return true; } - return intersectionExists(sourceSemType, targetSemType); - } - - public boolean containsErrorType(SemType t) { - return SemTypes.containsBasicType(t, PredefinedType.ERROR); - } - - boolean isNumericConversionPossible(BType sourceType, BType targetType) { - Optional targetNumericType = Core.singleNumericType(targetType.semType()); - if (targetNumericType.isEmpty()) { - return false; + source = getImpliedType(source); + target = getImpliedType(target); + if (isJsonAnydataOrUserDefinedUnion(source) && ((BUnionType) source).isCyclic) { + // add cyclic source to target pair to avoid recursive calls + unresolvedTypes.add(pair); } - return !Core.isEmpty(semTypeCtx, SemTypes.intersect(sourceType.semType(), PredefinedType.NUMBER)); - } + Set sourceTypes = new LinkedHashSet<>(); + Set targetTypes = new LinkedHashSet<>(); - public boolean isAllErrorMembers(BUnionType actualType) { - return isSubtype(actualType, PredefinedType.ERROR); - } + if (isJsonAnydataOrUserDefinedUnion(source)) { + sourceTypes.addAll(getEffectiveMemberTypes((BUnionType) source)); + } else { + sourceTypes.add(source); + } - public void setImplicitCastExpr(BLangExpression expr, BType actualType, BType targetType) { - BType expType = getImpliedType(targetType); - if (!isImplicitlyCastable(actualType, expType)) { - return; + boolean targetIsAUnion = false; + if (target.tag == TypeTags.UNION) { + targetIsAUnion = true; + targetTypes.addAll(getEffectiveMemberTypes((BUnionType) target)); + } else { + targetTypes.add(target); } - BLangTypeConversionExpr implicitConversionExpr = - (BLangTypeConversionExpr) TreeBuilder.createTypeConversionNode(); - implicitConversionExpr.pos = expr.pos; - implicitConversionExpr.expr = expr.impConversionExpr == null ? expr : expr.impConversionExpr; - implicitConversionExpr.setBType(expType); - implicitConversionExpr.targetType = expType; - implicitConversionExpr.internal = true; - expr.impConversionExpr = implicitConversionExpr; - } - public boolean checkListenerCompatibilityAtServiceDecl(BType type) { - if (getImpliedType(type).tag == TypeTags.UNION) { - // There should be at least one listener compatible type and all the member types, except error type - // should be listener compatible. - int listenerCompatibleTypeCount = 0; - for (BType memberType : getAllTypes(type, true)) { - if (memberType.tag != TypeTags.ERROR) { - if (!checkListenerCompatibility(memberType)) { - return false; + // check if all the value types are assignable between two unions + Iterator sourceIterator = sourceTypes.iterator(); + while (sourceIterator.hasNext()) { + BType sMember = sourceIterator.next(); + if (sMember.tag == TypeTags.NEVER) { + sourceIterator.remove(); + continue; + } + if (sMember.tag == TypeTags.FINITE && isAssignable(sMember, target, unresolvedTypes)) { + sourceIterator.remove(); + continue; + } + if (sMember.tag == TypeTags.XML && + isAssignableToUnionType(expandedXMLBuiltinSubtypes, target, unresolvedTypes)) { + sourceIterator.remove(); + continue; + } + + if (!isValueType(sMember)) { + if (!targetIsAUnion) { + continue; + } + BUnionType targetUnion = (BUnionType) target; + // prevent cyclic unions being compared as individual items + if (sMember instanceof BUnionType sUnion) { + if (sUnion.isCyclic && targetUnion.isCyclic) { + unresolvedTypes.add(new TypePair(sUnion, targetUnion)); + if (isAssignable(sUnion, targetUnion, unresolvedTypes)) { + sourceIterator.remove(); + continue; + } } - listenerCompatibleTypeCount++; + if (sMember.tag == TypeTags.JSON && isAssignable(sUnion, targetUnion, unresolvedTypes)) { + sourceIterator.remove(); + continue; + } + } + // readonly can match to a union similar to any|error + if (sMember.tag == TypeTags.READONLY && isAssignable(symTable.anyAndReadonlyOrError, targetUnion)) { + sourceIterator.remove(); + continue; } + continue; } - return listenerCompatibleTypeCount > 0; - } - return checkListenerCompatibility(type); - } - public boolean checkListenerCompatibility(BType bType) { - BType type = getImpliedType(bType); - if (type.tag == TypeTags.UNION) { - BUnionType unionType = (BUnionType) type; - for (BType memberType : unionType.getMemberTypes()) { - if (!checkListenerCompatibility(memberType)) { - return false; + boolean sourceTypeIsNotAssignableToAnyTargetType = true; + Iterator targetIterator = targetTypes.iterator(); + while (targetIterator.hasNext()) { + BType t = targetIterator.next(); + if (isAssignable(sMember, t, unresolvedTypes)) { + sourceIterator.remove(); + sourceTypeIsNotAssignableToAnyTargetType = false; + break; } } - return true; + if (sourceTypeIsNotAssignableToAnyTargetType) { + unresolvedTypes.remove(pair); + return false; + } } - if (type.tag != TypeTags.OBJECT) { - return false; + // check the structural values for similarity + sourceIterator = sourceTypes.iterator(); + while (sourceIterator.hasNext()) { + BType sourceMember = sourceIterator.next(); + boolean sourceTypeIsNotAssignableToAnyTargetType = true; + Iterator targetIterator = targetTypes.iterator(); + + boolean selfReferencedSource = (sourceMember != source) && + isSelfReferencedStructuredType(source, sourceMember); + + while (targetIterator.hasNext()) { + BType targetMember = targetIterator.next(); + + boolean selfReferencedTarget = isSelfReferencedStructuredType(target, targetMember); + if (selfReferencedTarget && selfReferencedSource && (sourceMember.tag == targetMember.tag)) { + sourceTypeIsNotAssignableToAnyTargetType = false; + break; + } + + if (isAssignable(sourceMember, targetMember, unresolvedTypes)) { + sourceTypeIsNotAssignableToAnyTargetType = false; + break; + } + } + if (sourceTypeIsNotAssignableToAnyTargetType) { + unresolvedTypes.remove(pair); + return false; + } } - BObjectType rhsType = (BObjectType) type; - List rhsFuncs = ((BStructureTypeSymbol) rhsType.tsymbol).attachedFuncs; + unresolvedTypes.add(pair); + return true; + } - ListenerValidationModel listenerValidationModel = new ListenerValidationModel(this, symTable); - return listenerValidationModel.checkMethods(rhsFuncs); + private boolean isJsonAnydataOrUserDefinedUnion(BType type) { + int tag = type.tag; + return tag == TypeTags.UNION || tag == TypeTags.JSON || tag == TypeTags.ANYDATA; + } + public boolean isSelfReferencedStructuredType(BType source, BType s) { + if (source == s) { + return true; + } + + s = getImpliedType(s); + if (s.tag == TypeTags.ARRAY) { + return isSelfReferencedStructuredType(source, ((BArrayType) s).eType); + } + if (s.tag == TypeTags.MAP) { + return isSelfReferencedStructuredType(source, ((BMapType) s).constraint); + } + if (s.tag == TypeTags.TABLE) { + return isSelfReferencedStructuredType(source, ((BTableType) s).constraint); + } + return false; } - public boolean isValidErrorDetailType(BType detailType) { - return switch (getImpliedType(detailType).tag) { - case TypeTags.MAP, TypeTags.RECORD -> isAssignable(detailType, symTable.detailType); - default -> false; - }; + public BType updateSelfReferencedWithNewType(BType source, BType s, BType target) { + if (s.tag == TypeTags.ARRAY) { + BArrayType arrayType = (BArrayType) s; + if (arrayType.eType == source) { + return new BArrayType(target, arrayType.tsymbol, arrayType.size, + arrayType.state, arrayType.flags); + } + } + if (s.tag == TypeTags.MAP) { + BMapType mapType = (BMapType) s; + if (mapType.constraint == source) { + return new BMapType(mapType.tag, target, mapType.tsymbol, mapType.flags); + } + } + if (s.tag == TypeTags.TABLE) { + BTableType tableType = (BTableType) s; + if (tableType.constraint == source) { + return new BTableType(tableType.tag, target, tableType.tsymbol, + tableType.flags); + } else if (tableType.constraint instanceof BMapType) { + return updateSelfReferencedWithNewType(source, tableType.constraint, target); + } + } + return s; } - // private methods + public static void fixSelfReferencingSameUnion(BType originalMemberType, BUnionType origUnionType, + BType immutableMemberType, BUnionType newImmutableUnion, + LinkedHashSet readOnlyMemTypes) { + boolean sameMember = originalMemberType == immutableMemberType; + if (originalMemberType.tag == TypeTags.ARRAY) { + BArrayType arrayType = (BArrayType) originalMemberType; + if (origUnionType == arrayType.eType) { + if (sameMember) { + BArrayType newArrayType = new BArrayType(newImmutableUnion, arrayType.tsymbol, arrayType.size, + arrayType.state, arrayType.flags); + readOnlyMemTypes.add(newArrayType); + } else { + ((BArrayType) immutableMemberType).eType = newImmutableUnion; + readOnlyMemTypes.add(immutableMemberType); + } + } + } else if (originalMemberType.tag == TypeTags.MAP) { + BMapType mapType = (BMapType) originalMemberType; + if (origUnionType == mapType.constraint) { + if (sameMember) { + BMapType newMapType = new BMapType(mapType.tag, newImmutableUnion, mapType.tsymbol, mapType.flags); + readOnlyMemTypes.add(newMapType); + } else { + ((BMapType) immutableMemberType).constraint = newImmutableUnion; + readOnlyMemTypes.add(immutableMemberType); + } + } + } else if (originalMemberType.tag == TypeTags.TABLE) { + BTableType tableType = (BTableType) originalMemberType; + if (origUnionType == tableType.constraint) { + if (sameMember) { + BTableType newTableType = new BTableType(tableType.tag, newImmutableUnion, tableType.tsymbol, + tableType.flags); + readOnlyMemTypes.add(newTableType); + } else { + ((BTableType) immutableMemberType).constraint = newImmutableUnion; + readOnlyMemTypes.add(immutableMemberType); + } + return; + } + + BType immutableConstraint = ((BTableType) immutableMemberType).constraint; + if (tableType.constraint.tag == TypeTags.MAP) { + sameMember = tableType.constraint == immutableConstraint; + BMapType mapType = (BMapType) tableType.constraint; + if (origUnionType == mapType.constraint) { + if (sameMember) { + BMapType newMapType = new BMapType(mapType.tag, newImmutableUnion, mapType.tsymbol, + mapType.flags); + ((BTableType) immutableMemberType).constraint = newMapType; + } else { + ((BTableType) immutableMemberType).constraint = newImmutableUnion; + } + readOnlyMemTypes.add(immutableMemberType); + } + } + } else { + readOnlyMemTypes.add(immutableMemberType); + } + } private Set getEffectiveMemberTypes(BUnionType unionType) { Set memTypes = new LinkedHashSet<>(); @@ -1803,6 +3880,44 @@ private Set getEffectiveMemberTypes(BUnionType unionType) { return memTypes; } + private boolean isFiniteTypeAssignable(BFiniteType finiteType, BType targetType, Set unresolvedTypes) { + BType expType = getImpliedType(targetType); + if (expType.tag == TypeTags.FINITE) { + for (BLangExpression expression : finiteType.getValueSpace()) { + ((BLangLiteral) expression).isFiniteContext = true; + if (!isAssignableToFiniteType(expType, (BLangLiteral) expression)) { + return false; + } + } + return true; + } + + if (expType.tag == TypeTags.UNION) { + List unionMemberTypes = getAllTypes(targetType, true); + for (BLangExpression valueExpr : finiteType.getValueSpace()) { + ((BLangLiteral) valueExpr).isFiniteContext = true; + if (unionMemberTypes.stream() + .noneMatch(targetMemType -> + getImpliedType(targetMemType).tag == TypeTags.FINITE ? + isAssignableToFiniteType(targetMemType, (BLangLiteral) valueExpr) : + isAssignable(valueExpr.getBType(), targetMemType, unresolvedTypes) || + isLiteralCompatibleWithBuiltinTypeWithSubTypes( + (BLangLiteral) valueExpr, targetMemType))) { + return false; + } + } + return true; + } + + for (BLangExpression expression : finiteType.getValueSpace()) { + if (!isLiteralCompatibleWithBuiltinTypeWithSubTypes((BLangLiteral) expression, targetType) && + !isAssignable(expression.getBType(), expType, unresolvedTypes)) { + return false; + } + } + return true; + } + boolean isAssignableToFiniteType(BType type, BLangLiteral literalExpr) { type = getImpliedType(type); if (type.tag != TypeTags.FINITE) { @@ -1810,7 +3925,20 @@ boolean isAssignableToFiniteType(BType type, BLangLiteral literalExpr) { } BFiniteType expType = (BFiniteType) type; - return checkLiteralAssignabilityBasedOnType(literalExpr, expType, literalExpr.getBType().tag); + return expType.getValueSpace().stream().anyMatch(memberLiteral -> { + if (((BLangLiteral) memberLiteral).value == null) { + return literalExpr.value == null; + } + + // If the literal which needs to be tested is from finite type and the type of the any member literal + // is not the same type, the literal cannot be assignable to finite type. + if (literalExpr.isFiniteContext && memberLiteral.getBType().tag != literalExpr.getBType().tag) { + return false; + } + // Check whether the literal that needs to be tested is assignable to any of the member literal in the + // value space. + return checkLiteralAssignabilityBasedOnType((BLangLiteral) memberLiteral, literalExpr); + }); } /** @@ -1819,14 +3947,18 @@ boolean isAssignableToFiniteType(BType type, BLangLiteral literalExpr) { * literal or a constant. In case of a constant, it is assignable to the base literal if and only if both * literals have same type and equivalent values. * - * @param literal Literal to be tested whether it is assignable to the base literal or not. - * @param finiteType - * @param targetTypeTag + * @param baseLiteral Literal based on which we check the assignability. + * @param candidateLiteral Literal to be tested whether it is assignable to the base literal or not. * @return true if assignable; false otherwise. */ - boolean checkLiteralAssignabilityBasedOnType(BLangLiteral literal, BFiniteType finiteType, int targetTypeTag) { - Object value = literal.value; - int literalTypeTag = literal.getBType().tag; + boolean checkLiteralAssignabilityBasedOnType(BLangLiteral baseLiteral, BLangLiteral candidateLiteral) { + // Different literal kinds. + if (baseLiteral.getKind() != candidateLiteral.getKind()) { + return false; + } + Object baseValue = baseLiteral.value; + Object candidateValue = candidateLiteral.value; + int candidateTypeTag = candidateLiteral.getBType().tag; // Numeric literal assignability is based on assignable type and numeric equivalency of values. // If the base numeric literal is, @@ -1835,64 +3967,104 @@ boolean checkLiteralAssignabilityBasedOnType(BLangLiteral literal, BFiniteType f // (3) float: we can assign int simple literal(Not an int constant) or a float literal/constant with same value. // (4) decimal: we can assign int simple literal or float simple literal (Not int/float constants) or decimal // with the same value. - SemType t = finiteType.semType(); - switch (targetTypeTag) { + switch (baseLiteral.getBType().tag) { + case TypeTags.BYTE: + if (candidateTypeTag == TypeTags.BYTE || (candidateTypeTag == TypeTags.INT && + !candidateLiteral.isConstant && isByteLiteralValue((Long) candidateValue))) { + return ((Number) baseValue).longValue() == ((Number) candidateValue).longValue(); + } + break; case TypeTags.INT: - if (literalTypeTag == TypeTags.INT) { - if (value instanceof String) { - return false; - } - return Core.containsConstInt(t, ((Number) value).longValue()); + if (candidateTypeTag == TypeTags.INT) { + return ((Number) baseValue).longValue() == ((Number) candidateValue).longValue(); + } + break; + case TypeTags.SIGNED32_INT: + if (candidateTypeTag == TypeTags.INT && isSigned32LiteralValue((Long) candidateValue)) { + return ((Number) baseValue).longValue() == ((Number) candidateValue).longValue(); + } + break; + case TypeTags.SIGNED16_INT: + if (candidateTypeTag == TypeTags.INT && isSigned16LiteralValue((Long) candidateValue)) { + return ((Number) baseValue).longValue() == ((Number) candidateValue).longValue(); + } + break; + case TypeTags.SIGNED8_INT: + if (candidateTypeTag == TypeTags.INT && isSigned8LiteralValue((Long) candidateValue)) { + return ((Number) baseValue).longValue() == ((Number) candidateValue).longValue(); + } + break; + case TypeTags.UNSIGNED32_INT: + if (candidateTypeTag == TypeTags.INT && isUnsigned32LiteralValue((Long) candidateValue)) { + return ((Number) baseValue).longValue() == ((Number) candidateValue).longValue(); + } + break; + case TypeTags.UNSIGNED16_INT: + if (candidateTypeTag == TypeTags.INT && isUnsigned16LiteralValue((Long) candidateValue)) { + return ((Number) baseValue).longValue() == ((Number) candidateValue).longValue(); + } + break; + case TypeTags.UNSIGNED8_INT: + if (candidateTypeTag == TypeTags.INT && isUnsigned8LiteralValue((Long) candidateValue)) { + return ((Number) baseValue).longValue() == ((Number) candidateValue).longValue(); } break; case TypeTags.FLOAT: - double doubleValue; - if (literalTypeTag == TypeTags.INT && !literal.isConstant) { - if (literal.value instanceof Double) { + String baseValueStr = String.valueOf(baseValue); + String originalValue = baseLiteral.originalValue != null ? baseLiteral.originalValue : baseValueStr; + if (NumericLiteralSupport.isDecimalDiscriminated(originalValue)) { + return false; + } + double baseDoubleVal; + try { + baseDoubleVal = Double.parseDouble(baseValueStr); + } catch (NumberFormatException e) { + // We reach here if a floating point literal has syntax diagnostics. + return false; + } + double candidateDoubleVal; + if (candidateTypeTag == TypeTags.INT && !candidateLiteral.isConstant) { + if (candidateLiteral.value instanceof Double) { // Out of range value for int but in range for float - doubleValue = Double.parseDouble(String.valueOf(value)); + candidateDoubleVal = Double.parseDouble(String.valueOf(candidateValue)); + return baseDoubleVal == candidateDoubleVal; } else { - doubleValue = ((Long) value).doubleValue(); - } - return Core.containsConstFloat(t, doubleValue); - } else if (literalTypeTag == TypeTags.FLOAT) { - try { - doubleValue = Double.parseDouble(String.valueOf(value)); - return Core.containsConstFloat(t, doubleValue); - } catch (NumberFormatException e) { - return false; + candidateDoubleVal = ((Long) candidateValue).doubleValue(); + return baseDoubleVal == candidateDoubleVal; } + } else if (candidateTypeTag == TypeTags.FLOAT) { + candidateDoubleVal = Double.parseDouble(String.valueOf(candidateValue)); + return baseDoubleVal == candidateDoubleVal; } break; case TypeTags.DECIMAL: - BigDecimal decimalValue; - if (literalTypeTag == TypeTags.INT && !literal.isConstant) { - if (literal.value instanceof String) { + BigDecimal baseDecimalVal = NumericLiteralSupport.parseBigDecimal(baseValue); + BigDecimal candidateDecimalVal; + if (candidateTypeTag == TypeTags.INT && !candidateLiteral.isConstant) { + if (candidateLiteral.value instanceof String) { // out of range value for float but in range for decimal - decimalValue = NumericLiteralSupport.parseBigDecimal(value); - } else if (literal.value instanceof Double) { + candidateDecimalVal = NumericLiteralSupport.parseBigDecimal(candidateValue); + return baseDecimalVal.compareTo(candidateDecimalVal) == 0; + } else if (candidateLiteral.value instanceof Double) { // out of range value for int in range for decimal and float - decimalValue = new BigDecimal((Double) value, MathContext.DECIMAL128); + candidateDecimalVal = new BigDecimal((Double) candidateValue, MathContext.DECIMAL128); + return baseDecimalVal.compareTo(candidateDecimalVal) == 0; } else { - decimalValue = new BigDecimal((long) value, MathContext.DECIMAL128); + candidateDecimalVal = new BigDecimal((long) candidateValue, MathContext.DECIMAL128); + return baseDecimalVal.compareTo(candidateDecimalVal) == 0; } - return Core.containsConstDecimal(t, decimalValue); - } else if (literalTypeTag == TypeTags.FLOAT && !literal.isConstant || - literalTypeTag == TypeTags.DECIMAL) { - if (NumericLiteralSupport.isFloatDiscriminated(String.valueOf(value))) { - return false; - } - try { - decimalValue = NumericLiteralSupport.parseBigDecimal(value); - return Core.containsConstDecimal(t, decimalValue); - } catch (NumberFormatException e) { + } else if (candidateTypeTag == TypeTags.FLOAT && !candidateLiteral.isConstant || + candidateTypeTag == TypeTags.DECIMAL) { + if (NumericLiteralSupport.isFloatDiscriminated(String.valueOf(candidateValue))) { return false; } + candidateDecimalVal = NumericLiteralSupport.parseBigDecimal(candidateValue); + return baseDecimalVal.compareTo(candidateDecimalVal) == 0; } break; default: // Non-numeric literal kind. - return Core.containsConst(t, value); + return baseValue.equals(candidateValue); } return false; } @@ -2002,23 +4174,38 @@ boolean isCharLiteralValue(String literal) { * Method to retrieve a type representing all the values in the value space of a finite type that are assignable to * the target type. * - * @param finiteType finite type - * @param targetType target type + * @param finiteType the finite type + * @param targetType the target type * @return a new finite type if at least one value in the value space of the specified finiteType is * assignable to targetType (the same if all are assignable), else semanticError */ - private Optional getFiniteTypeForAssignableValues(BType finiteType, BType targetType) { - BFiniteType bFiniteType = (BFiniteType) finiteType; - List newValueSpace = new ArrayList<>(bFiniteType.valueSpace.length); - - for (SemNamedType semNamedType : bFiniteType.valueSpace) { - if (SemTypes.isSubtype(semTypeCtx, semNamedType.semType(), targetType.semType())) { - newValueSpace.add(semNamedType); + BType getTypeForFiniteTypeValuesAssignableToType(BFiniteType finiteType, BType targetType) { + // finiteType - type Foo "foo"; + // targetType - type FooBar "foo"|"bar"; + if (isAssignable(finiteType, targetType)) { + return finiteType; + } + + // Identify all the values from the value space of the finite type that are assignable to the target type. + // e.g., finiteType - type Foo "foo"|1 ; + Set matchingValues = new HashSet<>(); + for (BLangExpression expr : finiteType.getValueSpace()) { + // case I: targetType - string ("foo" is assignable to string) + BLangLiteral literal = (BLangLiteral) expr; + if (isAssignable(expr.getBType(), targetType) || + // case II: targetType - type Bar "foo"|"baz" ; ("foo" is assignable to Bar) + isAssignableToFiniteType(targetType, literal) || + // type FooVal "foo"; + // case III: targetType - boolean|FooVal ("foo" is assignable to FooVal) + isAssignableToFiniteTypeMemberInUnion(literal, targetType) || + // case IV: targetType - int:Signed16 (1 is assignable to int:Signed16) + isAssignableToBuiltinSubtypeInTargetType(literal, targetType)) { + matchingValues.add(expr); } } - if (newValueSpace.isEmpty()) { - return Optional.empty(); + if (matchingValues.isEmpty()) { + return symTable.semanticError; } // Create a new finite type representing the assignable values. @@ -2027,9 +4214,62 @@ private Optional getFiniteTypeForAssignableValues(BType finiteType, BType finiteType.tsymbol.pkgID, null, finiteType.tsymbol.owner, finiteType.tsymbol.pos, VIRTUAL); - BFiniteType ft = new BFiniteType(finiteTypeSymbol, newValueSpace.toArray(SemNamedType[]::new)); - finiteTypeSymbol.type = ft; - return Optional.of(ft); + BFiniteType intersectingFiniteType = new BFiniteType(finiteTypeSymbol, matchingValues); + finiteTypeSymbol.type = intersectingFiniteType; + return intersectingFiniteType; + } + + private boolean isAssignableToFiniteTypeMemberInUnion(BLangLiteral expr, BType targetType) { + targetType = getImpliedType(targetType); + if (targetType.tag != TypeTags.UNION) { + return false; + } + + for (BType memType : ((BUnionType) targetType).getMemberTypes()) { + if (isAssignableToFiniteType(memType, expr)) { + return true; + } + } + return false; + } + + private boolean isAssignableToBuiltinSubtypeInTargetType(BLangLiteral literal, BType targetType) { + targetType = getImpliedType(targetType); + if (targetType.tag == TypeTags.UNION) { + for (BType memberType : ((BUnionType) targetType).getMemberTypes()) { + if (isLiteralCompatibleWithBuiltinTypeWithSubTypes(literal, memberType)) { + return true; + } + } + } + + return isLiteralCompatibleWithBuiltinTypeWithSubTypes(literal, targetType); + } + + public boolean isLiteralCompatibleWithBuiltinTypeWithSubTypes(BLangLiteral literal, BType targetType) { + BType literalType = literal.getBType(); + targetType = getImpliedType(targetType); + if (literalType.tag == targetType.tag) { + return true; + } + + return switch (targetType.tag) { + case TypeTags.BYTE -> literalType.tag == TypeTags.INT && isByteLiteralValue((Long) literal.value); + case TypeTags.SIGNED32_INT -> + literalType.tag == TypeTags.INT && isSigned32LiteralValue((Long) literal.value); + case TypeTags.SIGNED16_INT -> + literalType.tag == TypeTags.INT && isSigned16LiteralValue((Long) literal.value); + case TypeTags.SIGNED8_INT -> literalType.tag == TypeTags.INT && isSigned8LiteralValue((Long) literal.value); + case TypeTags.UNSIGNED32_INT -> + literalType.tag == TypeTags.INT && isUnsigned32LiteralValue((Long) literal.value); + case TypeTags.UNSIGNED16_INT -> + literalType.tag == TypeTags.INT && isUnsigned16LiteralValue((Long) literal.value); + case TypeTags.UNSIGNED8_INT -> + literalType.tag == TypeTags.INT && isUnsigned8LiteralValue((Long) literal.value); + case TypeTags.CHAR_STRING -> + literalType.tag == TypeTags.STRING && isCharLiteralValue((String) literal.value); + default -> false; + }; } /** @@ -2066,71 +4306,201 @@ BType getTypeForUnionTypeMembersAssignableToType(BUnionType unionType, BType tar if (intersection.size() == 1) { return intersection.get(0); } else { - return BUnionType.create(typeEnv(), null, new LinkedHashSet<>(intersection)); + return BUnionType.create(null, new LinkedHashSet<>(intersection)); } } boolean validEqualityIntersectionExists(BType lhsType, BType rhsType) { - SemType intersect = Core.intersect(lhsType.semType(), rhsType.semType()); - if (Core.isEmpty(semTypeCtx, intersect)) { + if (!isAnydata(lhsType) && !isAnydata(rhsType)) { return false; } - return isAnydata(intersect); - } + if (isAssignable(lhsType, rhsType) || isAssignable(rhsType, lhsType)) { + return true; + } - /** - * Checks where a type is subtype of either string or xml. - * - * @param type type to be checked - * @return a boolean - */ - boolean validStringOrXmlTypeExists(BType type) { - return isStringSubtype(type) || isXmlSubType(type); + Set lhsTypes = expandAndGetMemberTypesRecursive(lhsType); + Set rhsTypes = expandAndGetMemberTypesRecursive(rhsType); + return equalityIntersectionExists(lhsTypes, rhsTypes); } - /** - * Checks whether a type is a subtype of xml. - * - * @param type type to be checked - * @return a boolean - */ - boolean isXmlSubType(BType type) { - return SemTypeHelper.isSubtypeSimple(type, PredefinedType.XML); + private boolean equalityIntersectionExists(Set lhsTypes, Set rhsTypes) { + if ((lhsTypes.contains(symTable.anydataType) && + rhsTypes.stream().anyMatch(type -> getImpliedType(type).tag != TypeTags.ERROR)) || + (rhsTypes.contains(symTable.anydataType) && + lhsTypes.stream().anyMatch(type -> getImpliedType(type).tag != TypeTags.ERROR))) { + return true; + } + + boolean matchFound = false; + for (BType lhsType : lhsTypes) { + for (BType rhsType : rhsTypes) { + if (isAssignable(lhsType, rhsType) || isAssignable(rhsType, lhsType)) { + matchFound = true; + break; + } + } + if (matchFound) { + break; + } + } + + if (!matchFound) { + matchFound = equalityIntersectionExistsForComplexTypes(lhsTypes, rhsTypes); + } + + return matchFound; } - /** - * Checks whether a type is a subtype of string. - * - * @param type type to be checked - * @return a boolean - */ - boolean isStringSubtype(BType type) { - return SemTypeHelper.isSubtypeSimple(type, PredefinedType.STRING); + boolean validNumericStringOrXmlTypeExists(BType type, TypeExistenceValidationFunction validationFunction) { + switch (type.tag) { + case TypeTags.UNION: + BUnionType unionType = (BUnionType) type; + Set memberTypes = unionType.getMemberTypes(); + BType firstTypeInUnion = getBasicTypeOfBuiltinSubtype(getImpliedType(memberTypes.iterator().next())); + if (!validationFunction.validate(firstTypeInUnion)) { + return false; + } + if (firstTypeInUnion.tag == TypeTags.FINITE) { + Set valSpace = ((BFiniteType) firstTypeInUnion).getValueSpace(); + BType baseExprType = valSpace.iterator().next().getBType(); + for (BType memType : memberTypes) { + memType = getImpliedType(memType); + if (memType.tag == TypeTags.FINITE) { + if (!checkValueSpaceHasSameType((BFiniteType) memType, baseExprType)) { + return false; + } + continue; + } + + if (!isSubTypeOfBaseType(memType, baseExprType.tag)) { + return false; + } + } + } else { + for (BType memType : memberTypes) { + memType = getImpliedType(memType); + if (memType.tag == TypeTags.FINITE) { + if (!checkValueSpaceHasSameType((BFiniteType) memType, firstTypeInUnion)) { + return false; + } + continue; + } + if (!isSubTypeOfBaseType(memType, firstTypeInUnion.tag)) { + return false; + } + } + } + return true; + case TypeTags.FINITE: + Set valSpace = ((BFiniteType) type).getValueSpace(); + BType baseExprType = valSpace.iterator().next().getBType(); + for (BLangExpression expr : valSpace) { + if (!checkValueSpaceHasSameType((BFiniteType) type, baseExprType)) { + return false; + } + if (!validationFunction.validate(expr.getBType())) { + return false; + } + } + return true; + case TypeTags.TYPEREFDESC: + return validationFunction.validate(getImpliedType(type)); + case TypeTags.INTERSECTION: + return validationFunction.validate(((BIntersectionType) type).effectiveType); + default: + return false; + } } - /** - * Checks whether a type is a subtype of one of int?, float? or decimal?. - * - * @param type type to be checked - * @return a boolean - */ boolean validNumericTypeExists(BType type) { - SemType tButNil = Core.diff(type.semType(), PredefinedType.NIL); // nil lift - BasicTypeBitSet basicTypeBitSet = Core.widenToBasicTypes(tButNil); - return basicTypeBitSet.equals(PredefinedType.INT) || - basicTypeBitSet.equals(PredefinedType.FLOAT) || - basicTypeBitSet.equals(PredefinedType.DECIMAL); + if (type.isNullable() && getImpliedType(type).tag != TypeTags.NIL) { + type = getSafeType(type, true, false); + } + if (isBasicNumericType(type)) { + return true; + } + return validNumericStringOrXmlTypeExists(type, this::validNumericTypeExists); + } + + boolean validStringOrXmlTypeExists(BType type) { + BType refType = getImpliedType(type); + if (TypeTags.isStringTypeTag(refType.tag) || TypeTags.isXMLTypeTag(refType.tag)) { + return true; + } + return validNumericStringOrXmlTypeExists(type, this::validStringOrXmlTypeExists); } boolean validIntegerTypeExists(BType bType) { - SemType s = bType.semType(); - s = Core.diff(s, PredefinedType.NIL); // nil lift - return SemTypes.isSubtypeSimpleNotNever(s, PredefinedType.INT); + BType type = getImpliedType(bType); + if (type.isNullable() && type.tag != TypeTags.NIL) { + type = getSafeType(type, true, false); + } + if (TypeTags.isIntegerTypeTag(type.tag)) { + return true; + } + switch (type.tag) { + case TypeTags.BYTE: + return true; + case TypeTags.UNION: + LinkedHashSet memberTypes = ((BUnionType) type).getMemberTypes(); + for (BType memberType : memberTypes) { + memberType = getImpliedType(memberType); + if (!validIntegerTypeExists(memberType)) { + return false; + } + } + return true; + case TypeTags.FINITE: + Set valueSpace = ((BFiniteType) type).getValueSpace(); + for (BLangExpression expr : valueSpace) { + if (!validIntegerTypeExists(expr.getBType())) { + return false; + } + } + return true; + default: + return false; + } + } + + public BType getBasicTypeOfBuiltinSubtype(BType type) { + if (TypeTags.isIntegerTypeTag(type.tag) || type.tag == TypeTags.BYTE) { + return symTable.intType; + } + if (TypeTags.isStringTypeTag(type.tag)) { + return symTable.stringType; + } + if (TypeTags.isXMLTypeTag(type.tag)) { + return symTable.xmlType; + } + return type; } - public boolean isStringSubType(BType type) { - return SemTypeHelper.isSubtypeSimpleNotNever(type, PredefinedType.STRING); + public boolean checkTypeContainString(BType type) { + type = getImpliedType(type); + if (TypeTags.isStringTypeTag(type.tag)) { + return true; + } + switch (type.tag) { + case TypeTags.UNION: + for (BType memType : ((BUnionType) type).getMemberTypes()) { + if (!checkTypeContainString(memType)) { + return false; + } + } + return true; + case TypeTags.FINITE: + Set valSpace = ((BFiniteType) type).getValueSpace(); + for (BLangExpression expr : valSpace) { + if (!checkTypeContainString(expr.getBType())) { + return false; + } + } + return true; + default: + return false; + } } /** @@ -2158,8 +4528,8 @@ private Set expandAndGetMemberTypesRecursiveHelper(BType bType, memberTypes.add(symTable.byteType); break; case TypeTags.FINITE: - Set broadTypes = SemTypeHelper.broadTypes((BFiniteType) referredType, symTable); - memberTypes.addAll(broadTypes); + BFiniteType expType = (BFiniteType) referredType; + expType.getValueSpace().forEach(value -> memberTypes.add(value.getBType())); break; case TypeTags.UNION: BUnionType unionType = (BUnionType) referredType; @@ -2176,13 +4546,12 @@ private Set expandAndGetMemberTypesRecursiveHelper(BType bType, // add an unsealed array to allow comparison between closed and open arrays // TODO: 10/16/18 improve this, since it will allow comparison between sealed arrays of different sizes if (((BArrayType) referredType).getSize() != -1) { - memberTypes.add(new BArrayType(typeEnv(), arrayElementType)); + memberTypes.add(new BArrayType(arrayElementType)); } if (getImpliedType(arrayElementType).tag == TypeTags.UNION) { Set elementUnionTypes = expandAndGetMemberTypesRecursiveHelper(arrayElementType, visited); - elementUnionTypes.forEach( - elementUnionType -> memberTypes.add(new BArrayType(typeEnv(), elementUnionType))); + elementUnionTypes.forEach(elementUnionType -> memberTypes.add(new BArrayType(elementUnionType))); } memberTypes.add(bType); break; @@ -2191,9 +4560,8 @@ private Set expandAndGetMemberTypesRecursiveHelper(BType bType, if (getImpliedType(mapConstraintType).tag == TypeTags.UNION) { Set constraintUnionTypes = expandAndGetMemberTypesRecursiveHelper(mapConstraintType, visited); - constraintUnionTypes.forEach(constraintUnionType -> memberTypes.add( - new BMapType(symTable.typeEnv(), TypeTags.MAP, constraintUnionType, - symTable.mapType.tsymbol))); + constraintUnionTypes.forEach(constraintUnionType -> + memberTypes.add(new BMapType(TypeTags.MAP, constraintUnionType, symTable.mapType.tsymbol))); } memberTypes.add(bType); break; @@ -2203,6 +4571,235 @@ private Set expandAndGetMemberTypesRecursiveHelper(BType bType, return memberTypes; } + private boolean tupleIntersectionExists(BTupleType lhsType, BTupleType rhsType) { + if (lhsType.getTupleTypes().size() != rhsType.getTupleTypes().size()) { + return false; + } + + List lhsMemberTypes = lhsType.getTupleTypes(); + List rhsMemberTypes = rhsType.getTupleTypes(); + + for (int i = 0; i < lhsType.getTupleTypes().size(); i++) { + if (!equalityIntersectionExists(expandAndGetMemberTypesRecursive(lhsMemberTypes.get(i)), + expandAndGetMemberTypesRecursive(rhsMemberTypes.get(i)))) { + return false; + } + } + return true; + } + + private boolean equalityIntersectionExistsForComplexTypes(Set lhsTypes, Set rhsTypes) { + for (BType lhsMemberType : lhsTypes) { + if (isEqualityIntersectionExistsForMemberType(lhsMemberType, rhsTypes)) { + return true; + } + } + return false; + } + + private boolean isEqualityIntersectionExistsForMemberType(BType lhsMemberType, Set rhsTypes) { + switch (lhsMemberType.tag) { + case TypeTags.INT: + case TypeTags.STRING: + case TypeTags.FLOAT: + case TypeTags.DECIMAL: + case TypeTags.BOOLEAN: + case TypeTags.NIL: + if (rhsTypes.stream().map(Types::getImpliedType) + .anyMatch(rhsMemberType -> rhsMemberType.tag == TypeTags.JSON)) { + return true; + } + break; + case TypeTags.JSON: + if (jsonEqualityIntersectionExists(rhsTypes)) { + return true; + } + break; + // When expanding members for tuples, arrays and maps, set isValueDeepEquality to true, to allow + // comparison between JSON lists/maps and primitive lists/maps since they are all reference types + case TypeTags.TUPLE: + if (rhsTypes.stream().map(Types::getImpliedType).anyMatch( + rhsMemberType -> rhsMemberType.tag == TypeTags.TUPLE && + tupleIntersectionExists((BTupleType) lhsMemberType, (BTupleType) rhsMemberType))) { + return true; + } + + if (rhsTypes.stream().map(Types::getImpliedType).anyMatch( + rhsMemberType -> rhsMemberType.tag == TypeTags.ARRAY && + arrayTupleEqualityIntersectionExists((BArrayType) rhsMemberType, + (BTupleType) lhsMemberType))) { + return true; + } + break; + case TypeTags.ARRAY: + if (rhsTypes.stream().map(Types::getImpliedType).anyMatch( + rhsMemberType -> rhsMemberType.tag == TypeTags.ARRAY && + equalityIntersectionExists( + expandAndGetMemberTypesRecursive(((BArrayType) lhsMemberType).eType), + expandAndGetMemberTypesRecursive(((BArrayType) rhsMemberType).eType)))) { + return true; + } + + if (rhsTypes.stream().map(Types::getImpliedType).anyMatch( + rhsMemberType -> rhsMemberType.tag == TypeTags.TUPLE && + arrayTupleEqualityIntersectionExists((BArrayType) lhsMemberType, + (BTupleType) rhsMemberType))) { + return true; + } + break; + case TypeTags.MAP: + if (rhsTypes.stream().map(Types::getImpliedType).anyMatch( + rhsMemberType -> rhsMemberType.tag == TypeTags.MAP && + equalityIntersectionExists( + expandAndGetMemberTypesRecursive(((BMapType) lhsMemberType).constraint), + expandAndGetMemberTypesRecursive(((BMapType) rhsMemberType).constraint)))) { + return true; + } + + if (!isAssignable(((BMapType) lhsMemberType).constraint, symTable.errorType) && + rhsTypes.stream().map(Types::getImpliedType).anyMatch(rhsMemberType + -> rhsMemberType.tag == TypeTags.JSON)) { + // at this point it is guaranteed that the map is anydata + return true; + } + + if (rhsTypes.stream().map(Types::getImpliedType).anyMatch( + rhsMemberType -> rhsMemberType.tag == TypeTags.RECORD && + mapRecordEqualityIntersectionExists((BMapType) lhsMemberType, + (BRecordType) rhsMemberType))) { + return true; + } + break; + case TypeTags.OBJECT: + case TypeTags.RECORD: + if (rhsTypes.stream().map(Types::getImpliedType).anyMatch( + rhsMemberType -> checkStructEquivalency(rhsMemberType, lhsMemberType) || + checkStructEquivalency(lhsMemberType, rhsMemberType))) { + return true; + } + + if (rhsTypes.stream().map(Types::getImpliedType).anyMatch( + rhsMemberType -> rhsMemberType.tag == TypeTags.RECORD && + recordEqualityIntersectionExists((BRecordType) lhsMemberType, + (BRecordType) rhsMemberType))) { + return true; + } + + if (rhsTypes.stream().map(Types::getImpliedType).anyMatch(rhsMemberType + -> rhsMemberType.tag == TypeTags.JSON) && + jsonEqualityIntersectionExists(expandAndGetMemberTypesRecursive(lhsMemberType))) { + return true; + } + + if (rhsTypes.stream().map(Types::getImpliedType).anyMatch( + rhsMemberType -> rhsMemberType.tag == TypeTags.MAP && + mapRecordEqualityIntersectionExists((BMapType) rhsMemberType, + (BRecordType) lhsMemberType))) { + return true; + } + break; + case TypeTags.TYPEREFDESC: + case TypeTags.INTERSECTION: + return isEqualityIntersectionExistsForMemberType(getImpliedType(lhsMemberType), rhsTypes); + } + return false; + } + + private boolean arrayTupleEqualityIntersectionExists(BArrayType arrayType, BTupleType tupleType) { + Set elementTypes = expandAndGetMemberTypesRecursive(arrayType.eType); + + return tupleType.getTupleTypes().stream().allMatch(tupleMemType -> + equalityIntersectionExists(elementTypes, expandAndGetMemberTypesRecursive(tupleMemType))); + } + + private boolean recordEqualityIntersectionExists(BRecordType lhsType, BRecordType rhsType) { + Map lhsFields = lhsType.fields; + Map rhsFields = rhsType.fields; + + List matchedFieldNames = new ArrayList<>(); + for (BField lhsField : lhsFields.values()) { + if (rhsFields.containsKey(lhsField.name.value)) { + if (!equalityIntersectionExists(expandAndGetMemberTypesRecursive(lhsField.type), + expandAndGetMemberTypesRecursive( + rhsFields.get(lhsField.name.value).type))) { + return false; + } + matchedFieldNames.add(lhsField.getName()); + } else { + if (Symbols.isFlagOn(lhsField.symbol.flags, Flags.OPTIONAL)) { + break; + } + + if (rhsType.sealed) { + return false; + } + + if (!equalityIntersectionExists(expandAndGetMemberTypesRecursive(lhsField.type), + expandAndGetMemberTypesRecursive(rhsType.restFieldType))) { + return false; + } + } + } + + for (BField rhsField : rhsFields.values()) { + if (matchedFieldNames.contains(rhsField.getName())) { + continue; + } + + if (!Symbols.isFlagOn(rhsField.symbol.flags, Flags.OPTIONAL)) { + if (lhsType.sealed) { + return false; + } + + if (!equalityIntersectionExists(expandAndGetMemberTypesRecursive(rhsField.type), + expandAndGetMemberTypesRecursive(lhsType.restFieldType))) { + return false; + } + } + } + + return true; + } + + private boolean mapRecordEqualityIntersectionExists(BMapType mapType, BRecordType recordType) { + Set mapConstrTypes = expandAndGetMemberTypesRecursive(mapType.getConstraint()); + + for (BField field : recordType.fields.values()) { + if (!Symbols.isFlagOn(field.symbol.flags, Flags.OPTIONAL) && + !equalityIntersectionExists(mapConstrTypes, expandAndGetMemberTypesRecursive(field.type))) { + return false; + } + } + + return true; + } + + private boolean jsonEqualityIntersectionExists(Set typeSet) { + for (BType type : typeSet) { + type = getImpliedType(type); + switch (type.tag) { + case TypeTags.MAP: + if (!isAssignable(((BMapType) type).constraint, symTable.errorType)) { + return true; + } + break; + case TypeTags.RECORD: + BRecordType recordType = (BRecordType) type; + if (recordType.fields.values().stream() + .allMatch(field -> Symbols.isFlagOn(field.symbol.flags, Flags.OPTIONAL) || + !isAssignable(field.type, symTable.errorType))) { + return true; + } + break; + default: + if (isAssignable(type, symTable.jsonType)) { + return true; + } + } + } + return false; + } + public BType getRemainingMatchExprType(BType originalType, BType typeToRemove, SymbolEnv env) { originalType = getImpliedType(originalType); return switch (originalType.tag) { @@ -2235,11 +4832,11 @@ private BType getRemainingType(BTupleType originalType, BTupleType typeToRemove, List tupleTypes = new ArrayList<>(); for (int i = 0; i < originalTupleTypes.size(); i++) { BType type = getRemainingMatchExprType(originalTupleTypes.get(i), typesToRemove.get(i), env); - BVarSymbol varSymbol = new BVarSymbol(type.getFlags(), null, null, type, null, null, null); + BVarSymbol varSymbol = new BVarSymbol(type.flags, null, null, type, null, null, null); tupleTypes.add(new BTupleMember(type, varSymbol)); } if (typeToRemove.restType == null) { - return new BTupleType(typeEnv(), tupleTypes); + return new BTupleType(tupleTypes); } if (originalTupleTypes.size() == typesToRemove.size()) { return originalType; @@ -2249,7 +4846,7 @@ private BType getRemainingType(BTupleType originalType, BTupleType typeToRemove, BVarSymbol varSymbol = Symbols.createVarSymbolForTupleMember(type); tupleTypes.add(new BTupleMember(type, varSymbol)); } - return new BTupleType(typeEnv(), tupleTypes); + return new BTupleType(tupleTypes); } private BType getRemainingType(BTupleType originalType, BArrayType typeToRemove, SymbolEnv env) { @@ -2260,7 +4857,7 @@ private BType getRemainingType(BTupleType originalType, BArrayType typeToRemove, BVarSymbol varSymbol = Symbols.createVarSymbolForTupleMember(type); tupleTypes.add(new BTupleMember(type, varSymbol)); } - BTupleType remainingType = new BTupleType(typeEnv(), tupleTypes); + BTupleType remainingType = new BTupleType(tupleTypes); if (originalType.restType != null) { remainingType.restType = getRemainingMatchExprType(originalType.restType, eType, env); } @@ -2285,8 +4882,8 @@ public BType getRemainingType(BType originalType, BType typeToRemove, SymbolEnv getAllTypes(remainingType, true))); if (typeRemovedFromOriginalUnionType == symTable.nullSet || - isSubTypeOfReadOnly(typeRemovedFromOriginalUnionType) || - isSubTypeOfReadOnly(remainingType) || + isSubTypeOfReadOnly(typeRemovedFromOriginalUnionType, env) || + isSubTypeOfReadOnly(remainingType, env) || narrowsToUnionOfImmutableTypesOrDistinctBasicTypes(remainingType, typeToRemove, env)) { return remainingType; } @@ -2305,7 +4902,7 @@ public BType getRemainingType(BType originalType, BType typeToRemove, SymbolEnv return getRemainingType(refType, typeToRemove, env); } - if (Symbols.isFlagOn(getImpliedType(originalType).getFlags(), Flags.READONLY)) { + if (Symbols.isFlagOn(getImpliedType(originalType).flags, Flags.READONLY)) { return remainingType; } @@ -2331,12 +4928,10 @@ public BType getRemainingType(BType originalType, BType typeToRemove, SymbolEnv return originalType; } - public boolean isSubTypeOfReadOnly(SemType t) { - return isSubtype(t, PredefinedType.VAL_READONLY); - } - - public boolean isSubTypeOfReadOnly(BType type) { - return isSubTypeOfReadOnly(type.semType()); + public boolean isSubTypeOfReadOnly(BType type, SymbolEnv env) { + return isInherentlyImmutableType(type) || + (isSelectivelyImmutableType(type, env.enclPkg.packageID) && + Symbols.isFlagOn(type.flags, Flags.READONLY)); } private boolean isClosedRecordTypes(BType type) { @@ -2455,7 +5050,7 @@ private boolean narrowsToUnionOfImmutableTypesOrDistinctBasicTypes(BType remaini LinkedHashSet mutableRemainingTypes = filterMutableMembers(((BUnionType) referredRemainingType).getMemberTypes(), env); remainingType = mutableRemainingTypes.size() == 1 ? mutableRemainingTypes.iterator().next() : - BUnionType.create(typeEnv(), null, mutableRemainingTypes); + BUnionType.create(null, mutableRemainingTypes); BType referredTypeToRemove = getImpliedType(typeToRemove); @@ -2463,7 +5058,7 @@ private boolean narrowsToUnionOfImmutableTypesOrDistinctBasicTypes(BType remaini LinkedHashSet mutableTypesToRemove = filterMutableMembers(((BUnionType) referredTypeToRemove).getMemberTypes(), env); typeToRemove = mutableTypesToRemove.size() == 1 ? mutableTypesToRemove.iterator().next() : - BUnionType.create(typeEnv(), null, mutableTypesToRemove); + BUnionType.create(null, mutableTypesToRemove); } else { typeToRemove = referredTypeToRemove; } @@ -2476,7 +5071,7 @@ private LinkedHashSet filterMutableMembers(LinkedHashSet types, Sy for (BType type : types) { BType referredType = getImpliedType(type); - if (!isSubTypeOfReadOnly(referredType)) { + if (!isSubTypeOfReadOnly(referredType, env)) { remainingMemberTypes.add(referredType); } } @@ -2493,10 +5088,6 @@ private BType getRemainingType(BReadonlyType originalType, BType removeType) { return originalType; } - public boolean intersectionExists(SemType t1, SemType t2) { - return !Core.isEmpty(semTypeCtx, Core.intersect(t1, t2)); - } - public BType getTypeIntersection(IntersectionContext intersectionContext, BType lhsType, BType rhsType, SymbolEnv env) { return getTypeIntersection(intersectionContext, lhsType, rhsType, env, new LinkedHashSet<>()); @@ -2525,7 +5116,7 @@ private BType getTypeIntersection(IntersectionContext intersectionContext, BType if (intersection.size() == 1) { return intersection.toArray(new BType[0])[0]; } else { - return BUnionType.create(typeEnv(), null, intersection); + return BUnionType.create(null, intersection); } } @@ -2548,8 +5139,8 @@ private BType getIntersection(IntersectionContext intersectionContext, BType lhs // implementation, we cannot easily find the intersection between (A & readonly) and B. Instead, what we // do here is, first find the intersection between A and B then re-create the immutable type out of it. - if (Symbols.isFlagOn(referredLhsType.getFlags(), Flags.READONLY) && referredLhsType.tag == TypeTags.INTERSECTION - && getImpliedType(((BIntersectionType) referredLhsType).effectiveType).tag == TypeTags.UNION) { + if (Symbols.isFlagOn(referredLhsType.flags, Flags.READONLY) && referredLhsType.tag == TypeTags.INTERSECTION && + getImpliedType(((BIntersectionType) referredLhsType).effectiveType).tag == TypeTags.UNION) { BIntersectionType intersectionType = (BIntersectionType) referredLhsType; BType finalType = type; List types = intersectionType.getConstituentTypes().stream() @@ -2560,7 +5151,7 @@ && getImpliedType(((BIntersectionType) referredLhsType).effectiveType).tag == Ty if (types.size() == 1) { BType bType = types.get(0); - if (isInherentlyImmutableType(bType) || Symbols.isFlagOn(bType.getFlags(), Flags.READONLY)) { + if (isInherentlyImmutableType(bType) || Symbols.isFlagOn(bType.flags, Flags.READONLY)) { return bType; } @@ -2607,14 +5198,14 @@ && getImpliedType(((BIntersectionType) referredLhsType).effectiveType).tag == Ty isAssignable(referredLhsType, referredType)) { return lhsType; } else if (referredLhsType.tag == TypeTags.FINITE) { - Optional intersectionType = getFiniteTypeForAssignableValues(referredLhsType, type); - if (intersectionType.isPresent()) { - return intersectionType.get(); + BType intersectionType = getTypeForFiniteTypeValuesAssignableToType((BFiniteType) referredLhsType, type); + if (intersectionType != symTable.semanticError) { + return intersectionType; } } else if (referredType.tag == TypeTags.FINITE) { - Optional intersectionType = getFiniteTypeForAssignableValues(referredType, lhsType); - if (intersectionType.isPresent()) { - return intersectionType.get(); + BType intersectionType = getTypeForFiniteTypeValuesAssignableToType((BFiniteType) referredType, lhsType); + if (intersectionType != symTable.semanticError) { + return intersectionType; } } else if (referredLhsType.tag == TypeTags.UNION) { BType intersectionType = getTypeForUnionTypeMembersAssignableToType((BUnionType) referredLhsType, type, env, @@ -2634,7 +5225,7 @@ && getImpliedType(((BIntersectionType) referredLhsType).effectiveType).tag == Ty if (intersectionConstraintTypeType == null || intersectionConstraintTypeType == symTable.semanticError) { return null; } - return new BMapType(symTable.typeEnv(), TypeTags.MAP, intersectionConstraintTypeType, null); + return new BMapType(TypeTags.MAP, intersectionConstraintTypeType, null); } else if (referredType.tag == TypeTags.ARRAY && referredLhsType.tag == TypeTags.TUPLE) { BType intersectionType = createArrayAndTupleIntersection(intersectionContext, (BArrayType) referredType, (BTupleType) referredLhsType, env, visitedTypes); @@ -2690,14 +5281,14 @@ && getImpliedType(((BIntersectionType) referredLhsType).effectiveType).tag == Ty if (elementIntersection == null) { return null; } - return new BArrayType(typeEnv(), elementIntersection); + return new BArrayType(elementIntersection); } else if (referredType.tag == TypeTags.ARRAY && isAnydataOrJson(referredLhsType)) { BType elementIntersection = getIntersection(intersectionContext, lhsType, env, ((BArrayType) referredType).eType, visitedTypes); if (elementIntersection == null) { return null; } - return new BArrayType(typeEnv(), elementIntersection); + return new BArrayType(elementIntersection); } else if (referredType.tag == TypeTags.NULL_SET) { return type; } @@ -2740,8 +5331,8 @@ private BType createArrayAndTupleIntersection(IntersectionContext intersectionCo return tupleType; } List tupleTypes = tupleType.getTupleTypes(); - if (arrayType.state == BArrayState.CLOSED && tupleTypes.size() != arrayType.getSize()) { - if (tupleTypes.size() > arrayType.getSize()) { + if (arrayType.state == BArrayState.CLOSED && tupleTypes.size() != arrayType.size) { + if (tupleTypes.size() > arrayType.size) { return symTable.semanticError; } @@ -2763,15 +5354,15 @@ private BType createArrayAndTupleIntersection(IntersectionContext intersectionCo } if (tupleType.restType == null) { - return new BTupleType(typeEnv(), tupleMemberTypes); + return new BTupleType(null, tupleMemberTypes); } BType restIntersectionType = getTypeIntersection(intersectionContext, tupleType.restType, eType, env, visitedTypes); if (restIntersectionType == symTable.semanticError) { - return new BTupleType(typeEnv(), tupleMemberTypes); + return new BTupleType(null, tupleMemberTypes); } - return new BTupleType(typeEnv(), null, tupleMemberTypes, restIntersectionType, 0); + return new BTupleType(null, tupleMemberTypes, restIntersectionType, 0); } private BType createTupleAndTupleIntersection(IntersectionContext intersectionContext, @@ -2801,7 +5392,7 @@ private BType createTupleAndTupleIntersection(IntersectionContext intersectionCo if (intersectionType == symTable.semanticError) { return symTable.semanticError; } - BVarSymbol varSymbol = new BVarSymbol(intersectionType.getFlags(), null, null, intersectionType, + BVarSymbol varSymbol = new BVarSymbol(intersectionType.flags, null, null, intersectionType, null, null, null); tupleMemberTypes.add(new BTupleMember(intersectionType, varSymbol)); } @@ -2810,12 +5401,12 @@ private BType createTupleAndTupleIntersection(IntersectionContext intersectionCo BType restIntersectionType = getTypeIntersection(intersectionContext, tupleType.restType, lhsTupleType.restType, env, visitedTypes); if (restIntersectionType == symTable.semanticError) { - return new BTupleType(typeEnv(), tupleMemberTypes); + return new BTupleType(null, tupleMemberTypes); } - return new BTupleType(typeEnv(), null, tupleMemberTypes, restIntersectionType, 0); + return new BTupleType(null, tupleMemberTypes, restIntersectionType, 0); } - return new BTupleType(typeEnv(), tupleMemberTypes); + return new BTupleType(null, tupleMemberTypes); } private BType getIntersectionForErrorTypes(IntersectionContext intersectionContext, @@ -2886,7 +5477,7 @@ private BType createRecordIntersection(IntersectionContext intersectionContext, if ((newType.sealed || newType.restFieldType == symTable.neverType) && (newTypeFields.isEmpty() || allReadOnlyFields(newTypeFields))) { - newType.addFlags(Flags.READONLY); + newType.flags |= Flags.READONLY; newTypeSymbol.flags |= Flags.READONLY; } @@ -3039,14 +5630,14 @@ private BRecordType createAnonymousRecord(SymbolEnv env) { env.scope.owner, null, VIRTUAL); recordSymbol.name = Names.fromString( anonymousModelHelper.getNextAnonymousTypeKey(env.enclPkg.packageID)); - BInvokableType bInvokableType = new BInvokableType(typeEnv(), List.of(), symTable.nilType, null); + 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, false, symTable.builtinPos, VIRTUAL); initFuncSymbol.retType = symTable.nilType; recordSymbol.scope = new Scope(recordSymbol); - BRecordType recordType = new BRecordType(symTable.typeEnv(), recordSymbol); + BRecordType recordType = new BRecordType(recordSymbol); recordType.tsymbol = recordSymbol; recordSymbol.type = recordType; @@ -3054,7 +5645,7 @@ private BRecordType createAnonymousRecord(SymbolEnv env) { } private BRecordType getEquivalentRecordType(BMapType mapType) { - BRecordType equivalentRecordType = new BRecordType(symTable.typeEnv(), null); + BRecordType equivalentRecordType = new BRecordType(null); equivalentRecordType.sealed = false; equivalentRecordType.restFieldType = mapType.constraint; return equivalentRecordType; @@ -3064,19 +5655,11 @@ private BErrorType createErrorType(BType lhsType, BType rhsType, BType detailTyp BErrorType lhsErrorType = (BErrorType) lhsType; BErrorType rhsErrorType = (BErrorType) rhsType; - // Anonymous (generated) types are marked as public. - BErrorType errorType = createErrorType(detailType, lhsType.getFlags() | rhsType.getFlags() | Flags.PUBLIC, env); - - // This is to propagate same distinctId to effective type - lhsErrorType.setDistinctId(); - rhsErrorType.setDistinctId(); - if (lhsErrorType.distinctId != -1) { - errorType.distinctId = lhsErrorType.distinctId; - } else if (rhsErrorType.distinctId != -1) { - errorType.distinctId = rhsErrorType.distinctId; - } + long flags = lhsType.flags | rhsType.flags | Flags.PUBLIC; // Anonymous (generated) types are marked as public. + BErrorType errorType = createErrorType(detailType, flags, env); errorType.typeIdSet = BTypeIdSet.getIntersection(lhsErrorType.typeIdSet, rhsErrorType.typeIdSet); + return errorType; } @@ -3086,14 +5669,62 @@ public BErrorType createErrorType(BType detailType, long flags, SymbolEnv env) { env.enclPkg.symbol.pkgID, null, env.scope.owner, symTable.builtinPos, VIRTUAL); errorTypeSymbol.scope = new Scope(errorTypeSymbol); - BErrorType errorType = new BErrorType(symTable.typeEnv(), errorTypeSymbol, detailType); - errorType.addFlags(errorTypeSymbol.flags); + BErrorType errorType = new BErrorType(errorTypeSymbol, detailType); + errorType.flags |= errorTypeSymbol.flags; errorTypeSymbol.type = errorType; errorType.typeIdSet = BTypeIdSet.emptySet(); return errorType; } + private boolean populateRecordFields(IntersectionContext diagnosticContext, BRecordType newType, + BType originalType, SymbolEnv env, BType constraint) { + BTypeSymbol intersectionRecordSymbol = newType.tsymbol; + // If the detail type is BMapType simply ignore since the resulting detail type has `anydata` as rest type. + if (originalType.getKind() != TypeKind.RECORD) { + return true; + } + BRecordType originalRecordType = (BRecordType) originalType; + LinkedHashMap fields = new LinkedHashMap<>(); + for (BField origField : originalRecordType.fields.values()) { + org.wso2.ballerinalang.compiler.util.Name origFieldName = origField.name; + String nameString = origFieldName.value; + + if (!validateRecordFieldDefaultValueForIntersection(diagnosticContext, origField, originalRecordType)) { + return false; + } + + BType recordFieldType = validateRecordField(diagnosticContext, newType, origField, constraint, env); + if (recordFieldType == symTable.semanticError) { + return false; + } + + BVarSymbol recordFieldSymbol = new BVarSymbol(origField.symbol.flags, origFieldName, + env.enclPkg.packageID, recordFieldType, + intersectionRecordSymbol, origField.pos, SOURCE); + + if (recordFieldType == symTable.neverType && Symbols.isFlagOn(recordFieldSymbol.flags, Flags.OPTIONAL)) { + recordFieldSymbol.flags &= (~Flags.REQUIRED); + recordFieldSymbol.flags |= Flags.OPTIONAL; + } + + if (getImpliedType(recordFieldType).tag == TypeTags.INVOKABLE && recordFieldType.tsymbol != null) { + BInvokableTypeSymbol tsymbol = (BInvokableTypeSymbol) recordFieldType.tsymbol; + BInvokableSymbol invokableSymbol = (BInvokableSymbol) recordFieldSymbol; + invokableSymbol.params = tsymbol.params == null ? null : new ArrayList<>(tsymbol.params); + invokableSymbol.restParam = tsymbol.restParam; + invokableSymbol.retType = tsymbol.returnType; + invokableSymbol.flags = tsymbol.flags; + } + + fields.put(nameString, new BField(origFieldName, null, recordFieldSymbol)); + intersectionRecordSymbol.scope.define(origFieldName, recordFieldSymbol); + } + newType.fields.putAll(fields); + + return true; + } + private boolean validateRecordFieldDefaultValueForIntersection(IntersectionContext diagnosticContext, BField field, BRecordType recordType) { @@ -3104,6 +5735,52 @@ private boolean validateRecordFieldDefaultValueForIntersection(IntersectionConte return true; } + private BType validateRecordField(IntersectionContext intersectionContext, + BRecordType newType, BField origField, BType constraint, SymbolEnv env) { + if (hasField(newType, origField)) { + return validateOverlappingFields(newType, origField); + } + + if (constraint == null) { + return origField.type; + } + + BType fieldType = getTypeIntersection(intersectionContext, origField.type, constraint, env); + if (fieldType.tag == TypeTags.NEVER && !Symbols.isOptional(origField.symbol)) { + return symTable.semanticError; + } + + if (fieldType != symTable.semanticError) { + return fieldType; + } + + if (Symbols.isOptional(origField.symbol)) { + return symTable.neverType; + } + + return symTable.semanticError; + } + + private boolean hasField(BRecordType recordType, BField origField) { + return recordType.fields.containsKey(origField.name.value); + } + + private BType validateOverlappingFields(BRecordType newType, BField origField) { + if (!hasField(newType, origField)) { + return origField.type; + } + + BField overlappingField = newType.fields.get(origField.name.value); + if (isAssignable(overlappingField.type, origField.type)) { + return overlappingField.type; + } + + if (isAssignable(origField.type, overlappingField.type)) { + return origField.type; + } + return symTable.semanticError; + } + private void removeErrorFromReadonlyType(List remainingTypes) { Iterator remainingIterator = remainingTypes.listIterator(); boolean addAnyAndReadOnly = false; @@ -3157,23 +5834,28 @@ private BType getRemainingType(BUnionType originalType, List removeTypes) return symTable.nullSet; } - return BUnionType.create(typeEnv(), null, new LinkedHashSet<>(remainingTypes)); + return BUnionType.create(null, new LinkedHashSet<>(remainingTypes)); } private BType getRemainingType(BFiniteType originalType, List removeTypes) { - SemType removeSemType = PredefinedType.NEVER; - for (BType removeType : removeTypes) { - removeSemType = SemTypes.union(removeSemType, removeType.semType()); - } + Set remainingValueSpace = new LinkedHashSet<>(); + + for (BLangExpression valueExpr : originalType.getValueSpace()) { + boolean matchExists = false; + for (BType remType : removeTypes) { + if (isAssignable(valueExpr.getBType(), remType) || + isAssignableToFiniteType(remType, (BLangLiteral) valueExpr)) { + matchExists = true; + break; + } + } - List newValueSpace = new ArrayList<>(); - for (SemNamedType semNamedType : originalType.valueSpace) { - if (!SemTypes.isSubtype(semTypeCtx, semNamedType.semType(), removeSemType)) { - newValueSpace.add(semNamedType); + if (!matchExists) { + remainingValueSpace.add(valueExpr); } } - if (newValueSpace.isEmpty()) { + if (remainingValueSpace.isEmpty()) { return symTable.semanticError; } @@ -3182,21 +5864,9 @@ private BType getRemainingType(BFiniteType originalType, List removeTypes originalType.tsymbol.pkgID, null, originalType.tsymbol.owner, originalType.tsymbol.pos, VIRTUAL); - BFiniteType ft = new BFiniteType(finiteTypeSymbol, newValueSpace.toArray(SemNamedType[]::new)); - finiteTypeSymbol.type = ft; - return ft; - } - - public SemType getNilLiftType(SemType t) { - return Core.diff(t, PredefinedType.NIL); - } - - public SemType getErrorLiftType(SemType t) { - return Core.diff(t, PredefinedType.ERROR); - } - - public SemType getNilAndErrorLiftType(SemType t) { - return Core.diff(t, Core.union(PredefinedType.NIL, PredefinedType.ERROR)); + BFiniteType intersectingFiniteType = new BFiniteType(finiteTypeSymbol, remainingValueSpace); + finiteTypeSymbol.type = intersectingFiniteType; + return intersectingFiniteType; } public BType getSafeType(BType bType, boolean liftNil, boolean liftError) { @@ -3206,16 +5876,16 @@ public BType getSafeType(BType bType, boolean liftNil, boolean liftError) { if (liftNil) { switch (type.tag) { case TypeTags.JSON: - return BJSONType.newNilLiftedBJSONType((BJSONType) type); + return new BJSONType((BJSONType) type, false); case TypeTags.ANY: - return BAnyType.newNilLiftedBAnyType(); + return new BAnyType(type.tag, type.tsymbol, false); case TypeTags.ANYDATA: - return BAnydataType.newNilLiftedBAnydataType((BAnydataType) type); + return new BAnydataType((BAnydataType) type, false); case TypeTags.READONLY: if (liftError) { return symTable.anyAndReadonly; } - return BReadonlyType.newNilLiftedBReadonlyType(); + return new BReadonlyType(type.tag, type.tsymbol, false); } } @@ -3225,7 +5895,7 @@ public BType getSafeType(BType bType, boolean liftNil, boolean liftError) { BUnionType unionType = (BUnionType) type; LinkedHashSet memTypes = new LinkedHashSet<>(unionType.getMemberTypes()); - BUnionType errorLiftedType = BUnionType.create(typeEnv(), null, memTypes); + BUnionType errorLiftedType = BUnionType.create(null, memTypes); if (liftNil) { errorLiftedType.remove(symTable.nilType); @@ -3239,7 +5909,7 @@ public BType getSafeType(BType bType, boolean liftNil, boolean liftError) { } } memTypes = bTypes; - errorLiftedType = BUnionType.create(typeEnv(), null, memTypes); + errorLiftedType = BUnionType.create(null, memTypes); } if (errorLiftedType.getMemberTypes().size() == 1) { @@ -3310,7 +5980,8 @@ public boolean isAllowedConstantType(BType type) { yield true; } case TypeTags.FINITE -> { - yield isAllowedConstantType(SemTypeHelper.broadTypes(type.semType(), symTable).iterator().next()); + BLangExpression finiteValue = ((BFiniteType) type).getValueSpace().toArray(new BLangExpression[0])[0]; + yield isAllowedConstantType(finiteValue.getBType()); } default -> false; }; @@ -3366,8 +6037,61 @@ public boolean isSubTypeOfErrorOrNilContainingNil(BUnionType type) { return false; } - BasicTypeBitSet nilOrError = (BasicTypeBitSet) Core.union(PredefinedType.NIL, PredefinedType.ERROR); - return SemTypeHelper.isSubtypeSimpleNotNever(type, nilOrError); + for (BType memType : type.getMemberTypes()) { + BType referredMemType = getImpliedType(memType); + if (referredMemType.tag != TypeTags.NIL && referredMemType.tag != TypeTags.ERROR) { + return false; + } + } + return true; + } + + /** + * Type vector of size two, to hold the source and the target types. + * + * @since 0.982.0 + */ + private static class TypePair { + BType sourceType; + BType targetType; + + public TypePair(BType sourceType, BType targetType) { + this.sourceType = sourceType; + this.targetType = targetType; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof TypePair other)) { + return false; + } + + return this.sourceType.equals(other.sourceType) && this.targetType.equals(other.targetType); + } + + @Override + public int hashCode() { + return Objects.hash(sourceType, targetType); + } + } + + /** + * A functional interface for parameterizing the type of type checking that needs to be done on the source and + * target types. + * + * @since 0.995.0 + */ + private interface TypeEqualityPredicate { + boolean test(BType source, BType target, Set unresolvedTypes); + } + + /** + * A functional interface to validate numeric, string or xml type existence. + * + * @since 2201.1.0 + */ + private interface TypeExistenceValidationFunction { + boolean validate(BType type); } public boolean hasFillerValue(BType type) { @@ -3391,7 +6115,7 @@ public boolean hasFillerValue(BType type) { case TypeTags.ARRAY: return checkFillerValue((BArrayType) type); case TypeTags.FINITE: - return hasFiller(type.semType()); + return checkFillerValue((BFiniteType) type); case TypeTags.UNION: return checkFillerValue((BUnionType) type); case TypeTags.OBJECT: @@ -3432,42 +6156,45 @@ private boolean checkFillerValue(BObjectType type) { } /** - * Checks whether a SemType has a filler value. - *

- * Note: this is similar to computeFiller() in nBallerina - *

- * 1. if type contains nil, nil is the filler value.
- * 2. if all values belong to a single basic type B, and the filler value for B also included in the values.
- * 3. if type is a singleton, it is the filler value. - *

+ * This will handle two types. Singleton : As singleton can have one value that value should it self be a valid fill + * value Union : 1. if nil is a member it is the fill values 2. else all the values should belong to same type and + * the default value for that type should be a member of the union precondition : value space should have at least + * one element * - * @param t SemType to be checked - * @return whether there is a filler value + * @param type BFiniteType union or finite + * @return boolean whether type has a valid filler value or not */ - private boolean hasFiller(SemType t) { - if (Core.containsNil(t)) { + private boolean checkFillerValue(BFiniteType type) { + if (type.isNullable()) { + return true; + } + if (type.getValueSpace().size() == 1) { // For singleton types, that value is the implicit initial value return true; } + Iterator iterator = type.getValueSpace().iterator(); + BLangExpression firstElement = iterator.next(); + boolean defaultFillValuePresent = isImplicitDefaultValue(firstElement); + + while (iterator.hasNext()) { + BLangExpression value = iterator.next(); + if (!isSameBasicType(value.getBType(), firstElement.getBType())) { + return false; + } + if (!defaultFillValuePresent && isImplicitDefaultValue(value)) { + defaultFillValuePresent = true; + } + } - return hasImplicitDefaultValue(t) || Core.singleShape(t).isPresent(); + return defaultFillValuePresent; } - private boolean hasImplicitDefaultValue(SemType t) { - BasicTypeBitSet bitSet = Core.widenToBasicTypes(t); - Object value = null; - if (bitSet.equals(PredefinedType.BOOLEAN)) { - value = false; - } else if (bitSet.equals(PredefinedType.INT)) { - value = (long) 0; - } else if (bitSet.equals(PredefinedType.DECIMAL)) { - value = BigDecimal.valueOf(0); - } else if (bitSet.equals(PredefinedType.FLOAT)) { - value = (double) 0; - } else if (bitSet.equals(PredefinedType.STRING)) { - value = ""; + private boolean hasImplicitDefaultValue(Set valueSpace) { + for (BLangExpression expression : valueSpace) { + if (isImplicitDefaultValue(expression)) { + return true; + } } - - return value != null && (t instanceof BasicTypeBitSet || Core.containsConst(t, value)); + return false; } private boolean checkFillerValue(BUnionType type) { @@ -3484,9 +6211,9 @@ private boolean checkFillerValue(BUnionType type) { for (BType member : getAllTypes(type, true)) { if (member.tag == TypeTags.FINITE) { - Set broadTypes = SemTypeHelper.broadTypes((BFiniteType) member, symTable); - memberTypes.addAll(broadTypes); - if (!hasFillerValue && hasImplicitDefaultValue(member.semType())) { + Set uniqueValues = getValueTypes(((BFiniteType) member).getValueSpace()); + memberTypes.addAll(uniqueValues); + if (!hasFillerValue && hasImplicitDefaultValue(((BFiniteType) member).getValueSpace())) { hasFillerValue = true; } } else { @@ -3529,6 +6256,32 @@ private boolean isIntegerSubTypeTag(int typeTag) { return TypeTags.isIntegerTypeTag(typeTag) || typeTag == TypeTags.BYTE; } + private Set getValueTypes(Set valueSpace) { + Set uniqueType = new HashSet<>(); + for (BLangExpression expression : valueSpace) { + uniqueType.add(expression.getBType()); + } + return uniqueType; + } + + private boolean isImplicitDefaultValue(BLangExpression expression) { + if ((expression.getKind() == NodeKind.LITERAL) || (expression.getKind() == NodeKind.NUMERIC_LITERAL)) { + BLangLiteral literalExpression = (BLangLiteral) expression; + BType literalExprType = literalExpression.getBType(); + Object value = literalExpression.getValue(); + return switch (literalExprType.getKind()) { + case INT, BYTE -> value.equals(0L); + case STRING -> value == null || value.equals(""); + case DECIMAL -> value.equals(String.valueOf(0)) || value.equals(0L); + case FLOAT -> value.equals(String.valueOf(0.0)); + case BOOLEAN -> value.equals(Boolean.FALSE); + case NIL -> true; + default -> false; + }; + } + return false; + } + private boolean checkFillerValue(BRecordType type) { for (BField field : type.fields.values()) { if (Symbols.isFlagOn(field.symbol.flags, Flags.OPTIONAL)) { @@ -3542,146 +6295,138 @@ private boolean checkFillerValue(BRecordType type) { } private boolean checkFillerValue(BArrayType type) { - if (type.getSize() == -1) { + if (type.size == -1) { return true; } return hasFillerValue(type.eType); } /** - * Check whether a type is an ordered type. - * - * @param type type to be checked - * @return boolean whether the type is an ordered type or not - */ - public boolean isOrderedType(BType type) { - return isOrderedType(type.semType()); - } - - /** - * Checks whether a SemType is an ordered type. - *
- *

- * A type is an ordered type if all values belong to one of (), int?, boolean?, decimal?, float?, string? types. - * Additionally, - *

    - *
  • [T...] is ordered, if T is ordered;
  • - *
  • [] is ordered;
  • - *
  • [T, rest] is ordered if T is ordered and [rest] is ordered.
  • - *
+ * Get result type of the query output. * - * @param t SemType to be checked - * @return boolean + * @param type type of query expression. + * @return result type. */ - public boolean isOrderedType(SemType t) { - assert !Core.isNever(t); - SemType tButNil = Core.diff(t, PredefinedType.NIL); - BasicTypeBitSet basicTypeBitSet = Core.widenToBasicTypes(tButNil); - if (SemTypes.isSubtypeSimple(basicTypeBitSet, PredefinedType.SIMPLE_OR_STRING)) { - int bitCount = SemTypeHelper.bitCount(basicTypeBitSet.bitset); - return bitCount <= 1; - } - - if (SemTypes.isSubtypeSimple(tButNil, PredefinedType.LIST)) { - ListMemberTypes lmTypes = Core.listAllMemberTypesInner(typeCtx(), t); - for (SemType lmType : lmTypes.semTypes()) { - if (!isOrderedType(lmType)) { - return false; + public BType resolveExprType(BType type) { + switch (type.tag) { + case TypeTags.STREAM: + return ((BStreamType) type).constraint; + case TypeTags.TABLE: + return ((BTableType) type).constraint; + case TypeTags.ARRAY: + return ((BArrayType) type).eType; + case TypeTags.UNION: + List exprTypes = new ArrayList<>(((BUnionType) type).getMemberTypes()); + for (BType returnType : exprTypes) { + switch (returnType.tag) { + case TypeTags.STREAM: + return ((BStreamType) returnType).constraint; + case TypeTags.TABLE: + return ((BTableType) returnType).constraint; + case TypeTags.ARRAY: + return ((BArrayType) returnType).eType; + case TypeTags.STRING: + case TypeTags.XML: + return returnType; + } } - } - return true; + default: + return type; } - - return false; - } - - boolean comparable(BType t1, BType t2) { - return comparable(t1.semType(), t2.semType()); } /** - * Checks whether a SemType pair is comparable. - *
- *

- * Note: this is similar to comparable() in nBallerina. However, nBallerina API does not have - * "There must be an ordered type to which the static type of both operands belong" part from spec, implemented - *

+ * Check whether a type is an ordered type. * - * @param t1 first semType - * @param t2 second semType - * @return boolean + * @param type type. + * @param hasCycle whether there is a cycle. + * @return boolean whether the type is an ordered type or not. */ - boolean comparable(SemType t1, SemType t2) { - assert !Core.isNever(t1) && !Core.isNever(t2); - if (PredefinedType.NIL.equals(t1)) { - return isOrderedType(t2); - } - - if (PredefinedType.NIL.equals(t2)) { - return isOrderedType(t1); - } - - SemType tButNil = Core.diff(Core.union(t1, t2), PredefinedType.NIL); - BasicTypeBitSet basicTypeBitSet = Core.widenToBasicTypes(tButNil); - if (SemTypes.isSubtypeSimple(basicTypeBitSet, PredefinedType.SIMPLE_OR_STRING)) { - int bitCount = SemTypeHelper.bitCount(basicTypeBitSet.bitset); - return bitCount <= 1; - } - if (SemTypes.isSubtypeSimple(tButNil, PredefinedType.LIST)) { - return comparableNillableList(typeCtx(), t1, t2); - } - return false; - } - - private boolean comparableNillableList(Context cx, SemType t1, SemType t2) { - SemTypePair semPair = SemTypePair.from(t1, t2); - Boolean b = cx.comparableMemo.get(semPair); - if (b != null) { - return b; - } - - ListMemberTypes lmTypes1 = Core.listAllMemberTypesInner(cx, t1); - ListMemberTypes lmTypes2 = Core.listAllMemberTypesInner(cx, t2); - CombinedRange[] combinedRanges = combineRanges( - lmTypes1.ranges().toArray(Range[]::new), - lmTypes2.ranges().toArray(Range[]::new) - ); - SemType accum = PredefinedType.NIL; - for (CombinedRange combinedRange : combinedRanges) { - Long i1 = combinedRange.i1(); - Long i2 = combinedRange.i2(); - if (i1 == null) { - SemType lmType = lmTypes2.semTypes().get(Math.toIntExact(i2)); - if (!comparable(accum, lmType)) { - return false; + public boolean isOrderedType(BType type, boolean hasCycle) { + type = getImpliedType(type); + switch (type.tag) { + case TypeTags.UNION: + BUnionType unionType = (BUnionType) type; + if (hasCycle) { + return true; } - accum = Core.union(accum, lmType); - continue; - } - - if (i2 == null) { - SemType lmType = lmTypes1.semTypes().get(Math.toIntExact(i1)); - if (!comparable(accum, lmType)) { - return false; + if (unionType.isCyclic) { + hasCycle = true; } - accum = Core.union(accum, lmType); - continue; - } - - - if (!comparable(lmTypes1.semTypes().get(Math.toIntExact(i1)), - lmTypes2.semTypes().get(Math.toIntExact(i2)))) { - cx.comparableMemo.put(semPair, false); - return false; - } + Set memberTypes = unionType.getMemberTypes(); + boolean allMembersOrdered = false; + BType firstTypeInUnion = getTypeWithEffectiveIntersectionTypes(getImpliedType( + memberTypes.stream().filter(m -> !isNil(m)).findFirst().orElse(memberTypes.iterator().next()))); + if (isNil(firstTypeInUnion)) { + // Union contains only the nil type. + return true; + } + boolean isFirstTypeInUnionFinite = firstTypeInUnion.tag == TypeTags.FINITE; + for (BType memType : memberTypes) { + memType = getImpliedType(memType); + if (isFirstTypeInUnionFinite && memType.tag == TypeTags.FINITE && !isNil(memType)) { + Set valSpace = ((BFiniteType) firstTypeInUnion).getValueSpace(); + BType baseExprType = valSpace.iterator().next().getBType(); + if (!checkValueSpaceHasSameType((BFiniteType) memType, baseExprType)) { + return false; + } + } else if (memType.tag == TypeTags.UNION || memType.tag == TypeTags.ARRAY || + memType.tag == TypeTags.TUPLE) { + if (isSameOrderedType(memType, firstTypeInUnion)) { + allMembersOrdered = true; + continue; + } + return false; + } else if (memType.tag != firstTypeInUnion.tag && !isNil(memType) && + !isIntOrStringType(memType.tag, firstTypeInUnion.tag)) { + return false; + } + allMembersOrdered = isOrderedType(memType, hasCycle); + if (!allMembersOrdered) { + break; + } + } + return allMembersOrdered; + case TypeTags.ARRAY: + BType elementType = ((BArrayType) type).eType; + return isOrderedType(elementType, hasCycle); + case TypeTags.TUPLE: + List tupleMemberTypes = ((BTupleType) type).getTupleTypes(); + for (BType memType : tupleMemberTypes) { + if (!isOrderedType(memType, hasCycle)) { + return false; + } + } + BType restType = ((BTupleType) type).restType; + return restType == null || isOrderedType(restType, hasCycle); + case TypeTags.FINITE: + boolean isValueSpaceOrdered = false; + Set valSpace = ((BFiniteType) type).getValueSpace(); + BType baseExprType = valSpace.iterator().next().getBType(); + for (BLangExpression expr : valSpace) { + if (!checkValueSpaceHasSameType((BFiniteType) type, baseExprType)) { + return false; + } + isValueSpaceOrdered = isOrderedType(expr.getBType(), hasCycle); + if (!isValueSpaceOrdered) { + break; + } + } + return isValueSpaceOrdered; + default: + return isSimpleBasicType(type.tag); } - cx.comparableMemo.put(semPair, true); - return true; + } + + private boolean isIntOrStringType(int firstTypeTag, int secondTypeTag) { + return ((TypeTags.isIntegerTypeTag(firstTypeTag) || firstTypeTag == TypeTags.BYTE) && + (TypeTags.isIntegerTypeTag(secondTypeTag) || secondTypeTag == TypeTags.BYTE)) || + ((TypeTags.isStringTypeTag(firstTypeTag)) && (TypeTags.isStringTypeTag(secondTypeTag))); } public boolean isSubTypeOfSimpleBasicTypeOrString(BType bType) { return isAssignable(getImpliedType(bType), - BUnionType.create(typeEnv(), null, symTable.nilType, symTable.booleanType, symTable.intType, + BUnionType.create(null, symTable.nilType, symTable.booleanType, symTable.intType, symTable.floatType, symTable.decimalType, symTable.stringType)); } @@ -3710,25 +6455,69 @@ public BType findCompatibleType(BType type) { yield findCompatibleType(memberTypes.iterator().next()); } default -> { - Set broadTypes = SemTypeHelper.broadTypes(type.semType(), symTable); - assert broadTypes.size() == 1; // all values should belong to a single basic type - yield broadTypes.iterator().next(); + Set valueSpace = ((BFiniteType) type).getValueSpace(); + yield findCompatibleType(valueSpace.iterator().next().getBType()); } }; } public boolean isNonNilSimpleBasicTypeOrString(BType bType) { - return SemTypeHelper.isSubtypeSimpleNotNever(bType, - (BasicTypeBitSet) Core.diff(PredefinedType.SIMPLE_OR_STRING, PredefinedType.NIL)); + BType type = getImpliedType(bType); + if (type.tag == TypeTags.UNION) { + Set memberTypes = ((BUnionType) type).getMemberTypes(); + for (BType member : memberTypes) { + BType memType = getImpliedType(member); + if (memType.tag == TypeTags.FINITE || memType.tag == TypeTags.UNION) { + isNonNilSimpleBasicTypeOrString(memType); + continue; + } + if (memType.tag == TypeTags.NIL || !isSimpleBasicType(memType.tag)) { + return false; + } + } + return true; + } else if (type.tag == TypeTags.FINITE) { + for (BLangExpression expression: ((BFiniteType) type).getValueSpace()) { + BType exprType = getImpliedType(expression.getBType()); + if (exprType.tag == TypeTags.NIL || !isSimpleBasicType(exprType.tag)) { + return false; + } + } + return true; + } + return type.tag != TypeTags.NIL && isSimpleBasicType(type.tag); } public boolean isSubTypeOfReadOnlyOrIsolatedObjectUnion(BType bType) { - return SemTypes.isSubtype(semTypeCtx, bType.semType(), - SemTypes.union(PredefinedType.VAL_READONLY, createIsolatedObject(semTypeCtx))); + BType type = getImpliedType(bType); + if (isInherentlyImmutableType(type) || Symbols.isFlagOn(type.flags, Flags.READONLY)) { + return true; + } + + int tag = type.tag; + + if (tag == TypeTags.OBJECT) { + return isIsolated(type); + } + + if (tag != TypeTags.UNION) { + return false; + } + + for (BType memberType : ((BUnionType) type).getMemberTypes()) { + if (!isSubTypeOfReadOnlyOrIsolatedObjectUnion(memberType)) { + return false; + } + } + return true; + } + + private boolean isIsolated(BType type) { + return Symbols.isFlagOn(type.flags, Flags.ISOLATED); } private boolean isImmutable(BType type) { - return Symbols.isFlagOn(type.getFlags(), Flags.READONLY); + return Symbols.isFlagOn(type.flags, Flags.READONLY); } BType getTypeWithoutNil(BType type) { @@ -3753,19 +6542,11 @@ BType getTypeWithoutNil(BType type) { return nonNilTypes.get(0); } - return BUnionType.create(typeEnv(), null, new LinkedHashSet<>(nonNilTypes)); + return BUnionType.create(null, new LinkedHashSet<>(nonNilTypes)); } public boolean isFixedLengthTuple(BTupleType bTupleType) { - return isFixedLengthList(bTupleType); - } - - public boolean isFixedLengthList(BType type) { - // Using int:MIN_VALUE to project the rest type. - // This checks the type of effectively infinite list member, which should be the rest type. - SemType rest = Core.listMemberTypeInnerVal(semTypeCtx, type.semType(), - IntSubtype.intConst(Long.MAX_VALUE)); - return Core.isNever(rest); + return bTupleType.restType == null || isNeverTypeOrStructureTypeWithARequiredNeverMember(bTupleType.restType); } public boolean isNeverTypeOrStructureTypeWithARequiredNeverMember(BType type) { @@ -3830,18 +6611,25 @@ boolean isNeverTypeOrStructureTypeWithARequiredNeverMember(BType type, Set memberTypes = ((BUnionType) type).getMemberTypes(); + return memberTypes.stream().allMatch(this::isNeverType); + } + return false; } boolean isSingletonType(BType bType) { BType type = getImpliedType(bType); - return type.tag == TypeTags.FINITE && Core.singleShape(type.semType()).isPresent(); + return type.tag == TypeTags.FINITE && ((BFiniteType) type).getValueSpace().size() == 1; } boolean isSameSingletonType(BFiniteType type1, BFiniteType type2) { - SemType t1 = type1.semType(); - SemType t2 = type2.semType(); - return SemTypes.isSameType(semTypeCtx, t1, t2); + BLangLiteral expr1 = (BLangLiteral) type1.getValueSpace().iterator().next(); + BLangLiteral expr2 = (BLangLiteral) type2.getValueSpace().iterator().next(); + return expr1.value.equals(expr2.value); } public static void addImmutableType(SymbolTable symTable, PackageID packageId, @@ -3884,19 +6672,11 @@ public static Optional getImmutableType(SymbolTable symTable, return Optional.empty(); } - public static Name getImmutableTypeName(String origName) { - if (origName.isEmpty()) { - return Names.EMPTY; - } - - return Names.fromString("(".concat(origName).concat(AND_READONLY_SUFFIX).concat(")")); - } - public static String getPackageIdString(PackageID packageID) { return packageID.isTestPkg ? packageID.toString() + "_testable" : packageID.toString(); } - private class ListenerValidationModel { + private static class ListenerValidationModel { private final Types types; private final SymbolTable symtable; private final BType serviceNameType; @@ -3910,8 +6690,7 @@ public ListenerValidationModel(Types types, SymbolTable symTable) { this.types = types; this.symtable = symTable; this.serviceNameType = - BUnionType.create(symTable.typeEnv(), null, symtable.stringType, symtable.arrayStringType, - symtable.nilType); + BUnionType.create(null, symtable.stringType, symtable.arrayStringType, symtable.nilType); } boolean isValidListener() { @@ -4016,7 +6795,21 @@ private boolean checkAttachMethod(BAttachedFunction func) { } private boolean isServiceObject(BType bType) { - return types.isSubtype(bType, createServiceObject(semTypeCtx)); + BType type = getImpliedType(bType); + if (type.tag == TypeTags.UNION) { + for (BType memberType : ((BUnionType) type).getMemberTypes()) { + if (!isServiceObject(memberType)) { + return false; + } + } + return true; + } + + if (type.tag != TypeTags.OBJECT) { + return false; + } + + return Symbols.isService(type.tsymbol); } } @@ -4275,8 +7068,9 @@ private void populateBasicTypes(BType type, Set basicTypes) { basicTypes.add(BasicTypes.OBJECT); return; case TypeTags.FINITE: - SemType semType = type.semType(); - populateBasicTypes(semType, basicTypes); + for (BLangExpression expression : ((BFiniteType) type).getValueSpace()) { + populateBasicTypes(expression.getBType(), basicTypes); + } return; case TypeTags.HANDLE: basicTypes.add(BasicTypes.HANDLE); @@ -4289,35 +7083,6 @@ private void populateBasicTypes(BType type, Set basicTypes) { } } - private void populateBasicTypes(SemType t, Set basicTypes) { - int bitset; - if (t instanceof BasicTypeBitSet b) { - bitset = b.bitset; - } else { - ComplexSemType cst = (ComplexSemType) t; - bitset = cst.all() | cst.some(); - } - - if ((bitset & PredefinedType.NIL.bitset) != 0) { - basicTypes.add(BasicTypes.NIL); - } - if ((bitset & PredefinedType.BOOLEAN.bitset) != 0) { - basicTypes.add(BasicTypes.BOOLEAN); - } - if ((bitset & PredefinedType.INT.bitset) != 0) { - basicTypes.add(BasicTypes.INT); - } - if ((bitset & PredefinedType.FLOAT.bitset) != 0) { - basicTypes.add(BasicTypes.FLOAT); - } - if ((bitset & PredefinedType.DECIMAL.bitset) != 0) { - basicTypes.add(BasicTypes.DECIMAL); - } - if ((bitset & PredefinedType.STRING.bitset) != 0) { - basicTypes.add(BasicTypes.STRING); - } - } - private enum BasicTypes { NIL, BOOLEAN, @@ -4449,14 +7214,4 @@ public boolean isMappingConstructorCompatibleType(BType type) { int tag = getImpliedType(type).tag; return tag == TypeTags.RECORD || tag == TypeTags.MAP; } - - // Maybe it is a better idea to directly make Env accessible via the CompilerContext but that means SemType module - // will have a dependency on compiler - public Env typeEnv() { - return semTypeCtx.env; - } - - public Context typeCtx() { - return semTypeCtx; - } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/SymbolTable.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/SymbolTable.java index a1109b10a97c..5d3bfba21165 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/SymbolTable.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/SymbolTable.java @@ -18,9 +18,6 @@ package org.wso2.ballerinalang.compiler.semantics.model; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.Env; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemTypes; import org.ballerinalang.model.TreeBuilder; import org.ballerinalang.model.elements.PackageID; import org.ballerinalang.model.symbols.SymbolOrigin; @@ -29,6 +26,7 @@ import org.ballerinalang.model.types.TypeKind; import org.wso2.ballerinalang.compiler.diagnostic.BLangDiagnosticLocation; import org.wso2.ballerinalang.compiler.semantics.analyzer.Types; +import org.wso2.ballerinalang.compiler.semantics.model.symbols.BConstructorSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BErrorTypeSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableTypeSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BOperatorSymbol; @@ -50,6 +48,8 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BInvokableType; import org.wso2.ballerinalang.compiler.semantics.model.types.BJSONType; import org.wso2.ballerinalang.compiler.semantics.model.types.BMapType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BNeverType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BNilType; import org.wso2.ballerinalang.compiler.semantics.model.types.BNoType; import org.wso2.ballerinalang.compiler.semantics.model.types.BObjectType; import org.wso2.ballerinalang.compiler.semantics.model.types.BReadonlyType; @@ -76,6 +76,7 @@ import org.wso2.ballerinalang.util.Lists; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -113,45 +114,49 @@ public class SymbolTable { public final Scope rootScope; public final BType noType = new BNoType(TypeTags.NONE); - public final BType nilType = BType.createNilType(); - public final BType neverType = BType.createNeverType(); - public final BType intType = new BType(TypeTags.INT, null, Flags.READONLY, PredefinedType.INT); - public final BType byteType = new BType(TypeTags.BYTE, null, Flags.READONLY, PredefinedType.BYTE); - public final BType floatType = new BType(TypeTags.FLOAT, null, Flags.READONLY, PredefinedType.FLOAT); - public final BType decimalType = new BType(TypeTags.DECIMAL, null, Flags.READONLY, PredefinedType.DECIMAL); - public final BType stringType = new BType(TypeTags.STRING, null, Flags.READONLY, PredefinedType.STRING); - public final BType booleanType = new BType(TypeTags.BOOLEAN, null, Flags.READONLY, PredefinedType.BOOLEAN); - - public final BType anyType = new BAnyType(); - public final BMapType mapType; - public final BMapType mapStringType; - - public final BFutureType futureType; - public final BArrayType arrayType; - public final BArrayType byteArrayType; - public final BArrayType arrayStringType; + public final BType nilType = new BNilType(); + public final BType neverType = new BNeverType(); + public final BType intType = new BType(TypeTags.INT, null, Flags.READONLY); + public final BType byteType = new BType(TypeTags.BYTE, null, Flags.READONLY); + public final BType floatType = new BType(TypeTags.FLOAT, null, Flags.READONLY); + public final BType decimalType = new BType(TypeTags.DECIMAL, null, Flags.READONLY); + public final BType stringType = new BType(TypeTags.STRING, null, Flags.READONLY); + public final BType booleanType = new BType(TypeTags.BOOLEAN, null, Flags.READONLY); + + public final BType anyType = new BAnyType(TypeTags.ANY, null); + public final BMapType mapType = new BMapType(TypeTags.MAP, anyType, null); + public final BMapType mapStringType = new BMapType(TypeTags.MAP, stringType, null); + + public final BFutureType futureType = new BFutureType(TypeTags.FUTURE, nilType, null); + public final BArrayType arrayType = new BArrayType(anyType); + public final BArrayType byteArrayType = new BArrayType(byteType); + public final BArrayType arrayStringType = new BArrayType(stringType); BVarSymbol varSymbol = new BVarSymbol(0, null, null, noType, null, null, SymbolOrigin.VIRTUAL); - public final BType tupleType; - public final BType recordType; - public final BType stringArrayType; - public final BType handleType = new BHandleType(); - public final BTypedescType typeDesc; - public final BType readonlyType = new BReadonlyType(); - public final BType pathParamAllowedType; + public final BType tupleType = new BTupleType(Lists.of(new BTupleMember(noType, varSymbol))); + public final BType recordType = new BRecordType(null); + public final BType stringArrayType = new BArrayType(stringType); + public final BType handleType = new BHandleType(TypeTags.HANDLE, null); + public final BTypedescType typeDesc = new BTypedescType(this.anyType, null); + public final BType readonlyType = new BReadonlyType(TypeTags.READONLY, null); + public final BType pathParamAllowedType = BUnionType.create(null, + intType, stringType, floatType, booleanType, decimalType); public final BIntersectionType anyAndReadonly; public BUnionType anyAndReadonlyOrError; - public final BType semanticError = new BType(TypeTags.SEMANTIC_ERROR, null, PredefinedType.NEVER); - public final BType nullSet = new BType(TypeTags.NULL_SET, null, PredefinedType.NEVER); - public final BType invokableType; + public final BType errorIntersectionType = new BErrorType(null, null); + + public final BType semanticError = new BType(TypeTags.SEMANTIC_ERROR, null); + public final BType nullSet = new BType(TypeTags.NULL_SET, null); + public final BType invokableType = new BInvokableType(null, null, null, null); public final BType empty = new BType(TypeTags.EMPTY, null); + public BConstructorSymbol errorConstructor; public BUnionType anyOrErrorType; public BUnionType pureType; public BUnionType errorOrNilType; - public BType trueType; - public BType falseType; + public BFiniteType trueType; + public BFiniteType falseType; public BObjectType intRangeType; public BMapType mapAllType; public BArrayType arrayAllType; @@ -159,26 +164,24 @@ public class SymbolTable { public BObjectType iterableType; // builtin subtypes - public final BIntSubType signed32IntType = BIntSubType.SIGNED32; - public final BIntSubType signed16IntType = BIntSubType.SIGNED16; - public final BIntSubType signed8IntType = BIntSubType.SIGNED8; - public final BIntSubType unsigned32IntType = BIntSubType.UNSIGNED32; - public final BIntSubType unsigned16IntType = BIntSubType.UNSIGNED16; - public final BIntSubType unsigned8IntType = BIntSubType.UNSIGNED8; - - public final BStringSubType charStringType = BStringSubType.CHAR; - - public final BXMLSubType xmlElementType = BXMLSubType.XML_ELEMENT; - public final BXMLSubType xmlPIType = BXMLSubType.XML_PI; - public final BXMLSubType xmlCommentType = BXMLSubType.XML_COMMENT; - public final BXMLSubType xmlTextType = BXMLSubType.XML_TEXT; - - public final BRegexpType regExpType = new BRegexpType(); + public final BIntSubType signed32IntType = new BIntSubType(TypeTags.SIGNED32_INT, Names.SIGNED32); + public final BIntSubType signed16IntType = new BIntSubType(TypeTags.SIGNED16_INT, Names.SIGNED16); + public final BIntSubType signed8IntType = new BIntSubType(TypeTags.SIGNED8_INT, Names.SIGNED8); + public final BIntSubType unsigned32IntType = new BIntSubType(TypeTags.UNSIGNED32_INT, Names.UNSIGNED32); + public final BIntSubType unsigned16IntType = new BIntSubType(TypeTags.UNSIGNED16_INT, Names.UNSIGNED16); + public final BIntSubType unsigned8IntType = new BIntSubType(TypeTags.UNSIGNED8_INT, Names.UNSIGNED8); + public final BStringSubType charStringType = new BStringSubType(TypeTags.CHAR_STRING, Names.CHAR); + public final BXMLSubType xmlElementType = new BXMLSubType(TypeTags.XML_ELEMENT, Names.XML_ELEMENT); + public final BXMLSubType xmlPIType = new BXMLSubType(TypeTags.XML_PI, Names.XML_PI); + public final BXMLSubType xmlCommentType = new BXMLSubType(TypeTags.XML_COMMENT, Names.XML_COMMENT); + public final BXMLSubType xmlTextType = new BXMLSubType(TypeTags.XML_TEXT, Names.XML_TEXT, Flags.READONLY); + public final BRegexpType regExpType = new BRegexpType(TypeTags.REGEXP, Names.REGEXP_TYPE); public final BType xmlNeverType = new BXMLType(neverType, null); - - public final BType xmlType; public final BType xmlElementSeqType = new BXMLType(xmlElementType, null); + public final BType xmlType = new BXMLType(BUnionType.create(null, xmlElementType, xmlCommentType, + xmlPIType, xmlTextType), null); + public BAnydataType anydataType; public BArrayType arrayAnydataType; public BMapType mapAnydataType; @@ -222,7 +225,6 @@ public class SymbolTable { private final Names names; private final Types types; - public Map pkgEnvMap = new HashMap<>(); public Map predeclaredModules = new HashMap<>(); public Map> immutableTypeMaps = new HashMap<>(); @@ -242,7 +244,7 @@ private SymbolTable(CompilerContext context) { this.names = Names.getInstance(context); this.types = Types.getInstance(context); - this.rootPkgNode = (BLangPackage) TreeBuilder.createPackageNode(types.typeEnv()); + this.rootPkgNode = (BLangPackage) TreeBuilder.createPackageNode(); this.rootPkgSymbol = new BPackageSymbol(PackageID.ANNOTATIONS, null, null, BUILTIN); this.builtinPos = new BLangDiagnosticLocation(Names.EMPTY.value, -1, -1, -1, -1); @@ -261,10 +263,15 @@ private SymbolTable(CompilerContext context) { initializeType(decimalType, TypeKind.DECIMAL.typeName(), BUILTIN); initializeType(stringType, TypeKind.STRING.typeName(), BUILTIN); initializeType(booleanType, TypeKind.BOOLEAN.typeName(), BUILTIN); + initializeType(xmlType, TypeKind.XML.typeName(), BUILTIN); + initializeType(mapType, TypeKind.MAP.typeName(), VIRTUAL); + initializeType(mapStringType, TypeKind.MAP.typeName(), VIRTUAL); + initializeType(futureType, TypeKind.FUTURE.typeName(), BUILTIN); initializeType(anyType, TypeKind.ANY.typeName(), BUILTIN); initializeType(nilType, TypeKind.NIL.typeName(), BUILTIN); initializeType(neverType, TypeKind.NEVER.typeName(), BUILTIN); initializeType(handleType, TypeKind.HANDLE.typeName(), BUILTIN); + initializeType(typeDesc, TypeKind.TYPEDESC.typeName(), BUILTIN); initializeType(readonlyType, TypeKind.READONLY.typeName(), BUILTIN); // Define subtypes @@ -289,41 +296,22 @@ private SymbolTable(CompilerContext context) { falseLiteral.setBType(this.booleanType); falseLiteral.value = Boolean.FALSE; - arrayType = new BArrayType(types.typeEnv(), anyType); - byteArrayType = new BArrayType(types.typeEnv(), byteType); - arrayStringType = new BArrayType(types.typeEnv(), stringType); - stringArrayType = new BArrayType(types.typeEnv(), stringType); - - mapType = new BMapType(typeEnv(), TypeTags.MAP, anyType, null); - mapStringType = new BMapType(typeEnv(), TypeTags.MAP, stringType, null); - initializeType(mapType, TypeKind.MAP.typeName(), VIRTUAL); - initializeType(mapStringType, TypeKind.MAP.typeName(), VIRTUAL); - - pathParamAllowedType = BUnionType.create(types.typeEnv(), null, - intType, stringType, floatType, booleanType, decimalType); - tupleType = new BTupleType(types.typeEnv(), Lists.of(new BTupleMember(noType, varSymbol))); - recordType = new BRecordType(typeEnv(), null); - invokableType = new BInvokableType(types.typeEnv(), List.of(), null, null, null); - - xmlType = new BXMLType(BUnionType.create(types.typeEnv(), null, xmlElementType, xmlCommentType, - xmlPIType, xmlTextType), null); - futureType = new BFutureType(types.typeEnv(), nilType, null, PredefinedType.FUTURE); - typeDesc = new BTypedescType(types.typeEnv(), this.anyType, null, PredefinedType.TYPEDESC); - initializeType(xmlType, TypeKind.XML.typeName(), BUILTIN); - initializeType(futureType, TypeKind.FUTURE.typeName(), BUILTIN); - initializeType(typeDesc, TypeKind.TYPEDESC.typeName(), BUILTIN); - defineCyclicUnionBasedInternalTypes(); - BTypeSymbol trueFiniteTypeSymbol = Symbols.createTypeSymbol(SymTag.FINITE_TYPE, Flags.PUBLIC, - Names.fromString("$anonType$TRUE"), rootPkgNode.packageID, null, rootPkgNode.symbol.owner, - this.builtinPos, VIRTUAL); - this.trueType = BFiniteType.newSingletonBFiniteType(trueFiniteTypeSymbol, SemTypes.booleanConst(true)); + BTypeSymbol finiteTypeSymbol = Symbols.createTypeSymbol(SymTag.FINITE_TYPE, Flags.PUBLIC, + Names.fromString("$anonType$TRUE"), + rootPkgNode.packageID, null, rootPkgNode.symbol.owner, + this.builtinPos, VIRTUAL); + this.trueType = new BFiniteType(finiteTypeSymbol, new HashSet<>() {{ + add(trueLiteral); + }}); BTypeSymbol falseFiniteTypeSymbol = Symbols.createTypeSymbol(SymTag.FINITE_TYPE, Flags.PUBLIC, Names.fromString("$anonType$FALSE"), rootPkgNode.packageID, null, rootPkgNode.symbol.owner, this.builtinPos, VIRTUAL); - this.falseType = BFiniteType.newSingletonBFiniteType(falseFiniteTypeSymbol, SemTypes.booleanConst(false)); + this.falseType = new BFiniteType(falseFiniteTypeSymbol, new HashSet<>() {{ + add(falseLiteral); + }}); this.anyAndReadonly = ImmutableTypeCloner.getImmutableIntersectionType(this.anyType, this, names, this.types, @@ -331,7 +319,7 @@ private SymbolTable(CompilerContext context) { initializeType(this.anyAndReadonly, this.anyAndReadonly.effectiveType.name.getValue(), BUILTIN); // Initialize the invokable type - this.invokableType.setFlags(Flags.ANY_FUNCTION); + this.invokableType.flags = Flags.ANY_FUNCTION; BInvokableTypeSymbol tSymbol = Symbols.createInvokableTypeSymbol(SymTag.FUNCTION_TYPE, Flags.ANY_FUNCTION, rootPkgSymbol.pkgID, this.invokableType, rootPkgNode.symbol.scope.owner, builtinPos, BUILTIN); tSymbol.params = null; @@ -343,7 +331,7 @@ private SymbolTable(CompilerContext context) { } private void defineReadonlyCompoundType() { - anyAndReadonlyOrError = BUnionType.create(typeEnv(), null, anyAndReadonly, errorType); + anyAndReadonlyOrError = BUnionType.create(null, anyAndReadonly, errorType); } public BType getTypeFromTag(int tag) { @@ -651,7 +639,9 @@ private void defineIntegerUnaryOperations() { } private BUnionType getNilableBType(BType type) { - return BUnionType.create(typeEnv(), null, type, nilType); + BUnionType nilableType = BUnionType.create(null, type, nilType); + nilableType.setNullable(true); + return nilableType; } private void defineNilableIntegerUnaryOperations() { @@ -1113,7 +1103,7 @@ private void defineUnaryOperator(OperatorKind kind, private void defineOperator(Name name, List paramTypes, BType retType) { - BInvokableType opType = new BInvokableType(typeEnv(), paramTypes, retType, null); + BInvokableType opType = new BInvokableType(paramTypes, retType, null); BOperatorSymbol symbol = new BOperatorSymbol(name, rootPkgSymbol.pkgID, opType, rootPkgSymbol, this.builtinPos, BUILTIN); @@ -1133,7 +1123,7 @@ private void defineCyclicUnionBasedInternalTypes() { } private void defineCloneableCyclicTypeAndDependentTypes() { - cloneableType = BUnionType.create(typeEnv(), null, readonlyType, xmlType); + cloneableType = BUnionType.create(null, readonlyType, xmlType); addCyclicArrayMapTableOfMapMembers(cloneableType); // `cloneableType` and its symbol gets replaced by `Cloneable` type defined in lang value module. To prevent @@ -1142,31 +1132,31 @@ private void defineCloneableCyclicTypeAndDependentTypes() { cloneableType.tsymbol = new BTypeSymbol(SymTag.TYPE, Flags.PRIVATE, Names.CLONEABLE, rootPkgSymbol.pkgID, cloneableType, rootPkgSymbol, builtinPos, BUILTIN); - detailType = new BMapType(typeEnv(), TypeTags.MAP, cloneableType, null); - errorType = new BErrorType(typeEnv(), null, detailType); + detailType = new BMapType(TypeTags.MAP, cloneableType, null); + errorType = new BErrorType(null, detailType); errorType.tsymbol = new BErrorTypeSymbol(SymTag.ERROR, Flags.PUBLIC, Names.ERROR, rootPkgSymbol.pkgID, errorType, rootPkgSymbol, builtinPos, BUILTIN); - errorOrNilType = BUnionType.create(typeEnv(), null, errorType, nilType); - anyOrErrorType = BUnionType.create(typeEnv(), null, anyType, errorType); + errorOrNilType = BUnionType.create(null, errorType, nilType); + anyOrErrorType = BUnionType.create(null, anyType, errorType); - mapAllType = new BMapType(typeEnv(), TypeTags.MAP, anyOrErrorType, null); - arrayAllType = new BArrayType(typeEnv(), anyOrErrorType); + mapAllType = new BMapType(TypeTags.MAP, anyOrErrorType, null); + arrayAllType = new BArrayType(anyOrErrorType); typeDesc.constraint = anyOrErrorType; futureType.constraint = anyOrErrorType; - pureType = BUnionType.create(typeEnv(), null, anydataType, errorType); - streamType = new BStreamType(typeEnv(), TypeTags.STREAM, pureType, nilType, null); - tableType = new BTableType(typeEnv(), pureType, null); + pureType = BUnionType.create(null, anydataType, errorType); + streamType = new BStreamType(TypeTags.STREAM, pureType, nilType, null); + tableType = new BTableType(TypeTags.TABLE, pureType, null); initializeType(streamType, TypeKind.STREAM.typeName(), BUILTIN); initializeType(tableType, TypeKind.TABLE.typeName(), BUILTIN); } private void addCyclicArrayMapTableOfMapMembers(BUnionType unionType) { - BArrayType arrayCloneableType = new BArrayType(typeEnv(), unionType); - BMapType mapCloneableType = new BMapType(typeEnv(), TypeTags.MAP, unionType, null); - BType tableMapCloneableType = new BTableType(typeEnv(), mapCloneableType, null); + BArrayType arrayCloneableType = new BArrayType(unionType); + BMapType mapCloneableType = new BMapType(TypeTags.MAP, unionType, null); + BType tableMapCloneableType = new BTableType(TypeTags.TABLE, mapCloneableType, null); unionType.add(arrayCloneableType); unionType.add(mapCloneableType); unionType.add(tableMapCloneableType); @@ -1174,16 +1164,15 @@ private void addCyclicArrayMapTableOfMapMembers(BUnionType unionType) { } private void defineJsonCyclicTypeAndDependentTypes() { - BUnionType jsonInternal = - BUnionType.create(typeEnv(), null, nilType, booleanType, intType, floatType, decimalType, + BUnionType jsonInternal = BUnionType.create(null, nilType, booleanType, intType, floatType, decimalType, stringType); - BArrayType arrayJsonTypeInternal = new BArrayType(typeEnv(), jsonInternal); - BMapType mapJsonTypeInternal = new BMapType(typeEnv(), TypeTags.MAP, jsonInternal, null); + BArrayType arrayJsonTypeInternal = new BArrayType(jsonInternal); + BMapType mapJsonTypeInternal = new BMapType(TypeTags.MAP, jsonInternal, null); jsonInternal.add(arrayJsonTypeInternal); jsonInternal.add(mapJsonTypeInternal); jsonInternal.isCyclic = true; - jsonType = new BJSONType(types.typeCtx(), jsonInternal); + jsonType = new BJSONType(jsonInternal); PackageID pkgID = rootPkgSymbol.pkgID; Optional immutableType = Types.getImmutableType(this, pkgID, jsonInternal); if (immutableType.isPresent()) { @@ -1192,17 +1181,16 @@ private void defineJsonCyclicTypeAndDependentTypes() { jsonType.tsymbol = new BTypeSymbol(SymTag.TYPE, Flags.PUBLIC, Names.JSON, pkgID, jsonType, rootPkgSymbol, builtinPos, BUILTIN); - arrayJsonType = new BArrayType(typeEnv(), jsonType); - mapJsonType = new BMapType(typeEnv(), TypeTags.MAP, jsonType, null); + arrayJsonType = new BArrayType(jsonType); + mapJsonType = new BMapType(TypeTags.MAP, jsonType, null); } private void defineAnydataCyclicTypeAndDependentTypes() { - BUnionType anyDataInternal = - BUnionType.create(typeEnv(), null, nilType, booleanType, intType, floatType, decimalType, + BUnionType anyDataInternal = BUnionType.create(null, nilType, booleanType, intType, floatType, decimalType, stringType, xmlType); addCyclicArrayMapTableOfMapMembers(anyDataInternal); - anydataType = new BAnydataType(types.typeCtx(), anyDataInternal); + anydataType = new BAnydataType(anyDataInternal); PackageID pkgID = rootPkgSymbol.pkgID; Optional immutableType = Types.getImmutableType(this, pkgID, anyDataInternal); if (immutableType.isPresent()) { @@ -1211,15 +1199,10 @@ private void defineAnydataCyclicTypeAndDependentTypes() { anydataType.tsymbol = new BTypeSymbol(SymTag.TYPE, Flags.PUBLIC, Names.ANYDATA, pkgID, anydataType, rootPkgSymbol, builtinPos, BUILTIN); - arrayAnydataType = new BArrayType(typeEnv(), anydataType); - mapAnydataType = new BMapType(typeEnv(), TypeTags.MAP, anydataType, null); - anydataOrReadonly = BUnionType.create(typeEnv(), null, anydataType, readonlyType); + arrayAnydataType = new BArrayType(anydataType); + mapAnydataType = new BMapType(TypeTags.MAP, anydataType, null); + anydataOrReadonly = BUnionType.create(null, anydataType, readonlyType); initializeType(mapAnydataType, TypeKind.MAP.typeName(), VIRTUAL); } - - public Env typeEnv() { - assert types.typeEnv() != null; - return types.typeEnv(); - } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/TypeVisitor.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/TypeVisitor.java index 9cf5163e54c2..86e84538855b 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/TypeVisitor.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/TypeVisitor.java @@ -22,6 +22,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BAnyType; import org.wso2.ballerinalang.compiler.semantics.model.types.BAnydataType; import org.wso2.ballerinalang.compiler.semantics.model.types.BArrayType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BBuiltInRefType; import org.wso2.ballerinalang.compiler.semantics.model.types.BErrorType; import org.wso2.ballerinalang.compiler.semantics.model.types.BFiniteType; import org.wso2.ballerinalang.compiler.semantics.model.types.BFutureType; @@ -31,6 +32,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BJSONType; import org.wso2.ballerinalang.compiler.semantics.model.types.BMapType; import org.wso2.ballerinalang.compiler.semantics.model.types.BNeverType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BNilType; import org.wso2.ballerinalang.compiler.semantics.model.types.BNoType; import org.wso2.ballerinalang.compiler.semantics.model.types.BObjectType; import org.wso2.ballerinalang.compiler.semantics.model.types.BPackageType; @@ -45,77 +47,70 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BTypedescType; import org.wso2.ballerinalang.compiler.semantics.model.types.BUnionType; import org.wso2.ballerinalang.compiler.semantics.model.types.BXMLType; -import org.wso2.ballerinalang.compiler.util.TypeTags; /** * Visit ballerina types and maps them to instances T. * * @since 0.995.0 */ -public abstract class TypeVisitor { +public interface TypeVisitor { - public abstract void visit(BAnnotationType bAnnotationType); + void visit(BAnnotationType bAnnotationType); - public abstract void visit(BArrayType bArrayType); + void visit(BArrayType bArrayType); - public abstract void visit(BAnyType bAnyType); + void visit(BBuiltInRefType bBuiltInRefType); - public abstract void visit(BAnydataType bAnydataType); + void visit(BAnyType bAnyType); - public abstract void visit(BErrorType bErrorType); + void visit(BAnydataType bAnydataType); - public abstract void visit(BFiniteType bFiniteType); + void visit(BErrorType bErrorType); - public abstract void visit(BInvokableType bInvokableType); + void visit(BFiniteType bFiniteType); - public abstract void visit(BJSONType bjsonType); + void visit(BInvokableType bInvokableType); - public abstract void visit(BMapType bMapType); + void visit(BJSONType bjsonType); - public abstract void visit(BStreamType bStreamType); + void visit(BMapType bMapType); - public abstract void visit(BTypedescType bTypedescType); + void visit(BStreamType bStreamType); - public abstract void visit(BTypeReferenceType bTypeReferenceType); + void visit(BTypedescType bTypedescType); - public abstract void visit(BParameterizedType bTypedescType); + void visit(BTypeReferenceType bTypeReferenceType); - public abstract void visit(BNeverType bNeverType); + void visit(BParameterizedType bTypedescType); - public abstract void visitNilType(BType bType); + void visit(BNeverType bNeverType); - public abstract void visit(BNoType bNoType); + void visit(BNilType bNilType); - public abstract void visit(BPackageType bPackageType); + void visit(BNoType bNoType); - public abstract void visit(BStructureType bStructureType); + void visit(BPackageType bPackageType); - public abstract void visit(BTupleType bTupleType); + void visit(BStructureType bStructureType); - public abstract void visit(BUnionType bUnionType); + void visit(BTupleType bTupleType); - public abstract void visit(BIntersectionType bIntersectionType); + void visit(BUnionType bUnionType); - public abstract void visit(BXMLType bxmlType); + void visit(BIntersectionType bIntersectionType); - public abstract void visit(BTableType bTableType); + void visit(BXMLType bxmlType); - public abstract void visit(BRecordType bRecordType); + void visit(BTableType bTableType); - public abstract void visit(BObjectType bObjectType); + void visit(BRecordType bRecordType); - public void visit(BType type) { - if (type == null) { // TODO: see if we can remove - return; - } + void visit(BObjectType bObjectType); - switch (type.tag) { - case TypeTags.NIL: - visitNilType(type); - } - } + void visit(BType bType); - public abstract void visit(BFutureType bFutureType); + void visit(BFutureType bFutureType); + + void visit(BHandleType bHandleType); - public abstract void visit(BHandleType bHandleType); } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/UniqueTypeVisitor.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/UniqueTypeVisitor.java index 273ca80f2dc6..3f574d7c81f6 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/UniqueTypeVisitor.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/UniqueTypeVisitor.java @@ -22,6 +22,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BAnyType; import org.wso2.ballerinalang.compiler.semantics.model.types.BAnydataType; import org.wso2.ballerinalang.compiler.semantics.model.types.BArrayType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BBuiltInRefType; import org.wso2.ballerinalang.compiler.semantics.model.types.BErrorType; import org.wso2.ballerinalang.compiler.semantics.model.types.BFiniteType; import org.wso2.ballerinalang.compiler.semantics.model.types.BFutureType; @@ -32,11 +33,11 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BJSONType; import org.wso2.ballerinalang.compiler.semantics.model.types.BMapType; import org.wso2.ballerinalang.compiler.semantics.model.types.BNeverType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BNilType; import org.wso2.ballerinalang.compiler.semantics.model.types.BNoType; import org.wso2.ballerinalang.compiler.semantics.model.types.BObjectType; import org.wso2.ballerinalang.compiler.semantics.model.types.BPackageType; import org.wso2.ballerinalang.compiler.semantics.model.types.BParameterizedType; -import org.wso2.ballerinalang.compiler.semantics.model.types.BReadonlyType; import org.wso2.ballerinalang.compiler.semantics.model.types.BRecordType; import org.wso2.ballerinalang.compiler.semantics.model.types.BStreamType; import org.wso2.ballerinalang.compiler.semantics.model.types.BStructureType; @@ -55,75 +56,75 @@ * @param return type of visit methods * @since Swan Lake */ -public abstract class UniqueTypeVisitor { +public interface UniqueTypeVisitor { - R visit(UniqueTypeVisitor visitor) { + default R visit(UniqueTypeVisitor visitor) { return visitor.visit(this); } - public abstract boolean isVisited(BType type); + boolean isVisited(BType type); - public abstract void reset(); + void reset(); - public abstract R visit(BAnnotationType bAnnotationType); + R visit(BAnnotationType bAnnotationType); - public abstract R visit(BArrayType bArrayType); + R visit(BArrayType bArrayType); - public abstract R visit(BReadonlyType bReadonlyType); + R visit(BBuiltInRefType bBuiltInRefType); - public abstract R visit(BAnyType bAnyType); + R visit(BAnyType bAnyType); - public abstract R visit(BAnydataType bAnydataType); + R visit(BAnydataType bAnydataType); - public abstract R visit(BErrorType bErrorType); + R visit(BErrorType bErrorType); - public abstract R visit(BFiniteType bFiniteType); + R visit(BFiniteType bFiniteType); - public abstract R visit(BInvokableType bInvokableType); + R visit(BInvokableType bInvokableType); - public abstract R visit(BJSONType bjsonType); + R visit(BJSONType bjsonType); - public abstract R visit(BMapType bMapType); + R visit(BMapType bMapType); - public abstract R visit(BStreamType bStreamType); + R visit(BStreamType bStreamType); - public abstract R visit(BTypedescType bTypedescType); + R visit(BTypedescType bTypedescType); - public abstract R visit(BParameterizedType bTypedescType); + R visit(BParameterizedType bTypedescType); - public abstract R visit(BNeverType bNeverType); + R visit(BNeverType bNeverType); - public abstract R visitNilType(BType bType); + R visit(BNilType bNilType); - public abstract R visit(BNoType bNoType); + R visit(BNoType bNoType); - public abstract R visit(BPackageType bPackageType); + R visit(BPackageType bPackageType); - public abstract R visit(BStructureType bStructureType); + R visit(BStructureType bStructureType); - public abstract R visit(BTupleType bTupleType); + R visit(BTupleType bTupleType); - public abstract R visit(BUnionType bUnionType); + R visit(BUnionType bUnionType); - public abstract R visit(BIntersectionType bIntersectionType); + R visit(BIntersectionType bIntersectionType); - public abstract R visit(BTypeReferenceType bTypeReferenceType); + R visit(BTypeReferenceType bTypeReferenceType); - public abstract R visit(BXMLType bxmlType); + R visit(BXMLType bxmlType); - public abstract R visit(BTableType bTableType); + R visit(BTableType bTableType); - public abstract R visit(BRecordType bRecordType); + R visit(BRecordType bRecordType); - public abstract R visit(BObjectType bObjectType); + R visit(BObjectType bObjectType); - public abstract R visit(BType bType); + R visit(BType bType); - public abstract R visit(BFutureType bFutureType); + R visit(BFutureType bFutureType); - public abstract R visit(BHandleType bHandleType); + R visit(BHandleType bHandleType); - public abstract R visit(BIntSubType intSubType); + R visit(BIntSubType intSubType); - public abstract R visit(BXMLSubType bxmlSubType); + R visit(BXMLSubType bxmlSubType); } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BAttachedFunction.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BAttachedFunction.java index d425df9b2822..4bff7d56f36b 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BAttachedFunction.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BAttachedFunction.java @@ -18,7 +18,6 @@ package org.wso2.ballerinalang.compiler.semantics.model.symbols; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.SemType; import org.wso2.ballerinalang.compiler.semantics.model.types.BInvokableType; import org.wso2.ballerinalang.compiler.util.Name; import org.wso2.ballerinalang.util.Flags; @@ -46,17 +45,13 @@ public BAttachedFunction(Name funcName, BInvokableSymbol symbol, BInvokableType public String toString() { StringBuilder sb = new StringBuilder(); - if (Symbols.isFlagOn(type.getFlags(), Flags.ISOLATED)) { + if (Symbols.isFlagOn(type.flags, Flags.ISOLATED)) { sb.append("isolated "); } - if (Symbols.isFlagOn(type.getFlags(), Flags.TRANSACTIONAL)) { + if (Symbols.isFlagOn(type.flags, Flags.TRANSACTIONAL)) { sb.append("transactional "); } sb.append("function ").append(funcName).append(" ").append(type.getTypeSignature()); return sb.toString(); } - - public SemType semType() { - return type.semType(); - } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BResourceFunction.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BResourceFunction.java index 7b552f438272..7cc5fd7eea01 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BResourceFunction.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BResourceFunction.java @@ -18,10 +18,6 @@ package org.wso2.ballerinalang.compiler.semantics.model.symbols; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypes; -import io.ballerina.types.definition.FunctionDefinition; import org.ballerinalang.model.symbols.SymbolKind; import org.wso2.ballerinalang.compiler.semantics.model.types.BInvokableType; import org.wso2.ballerinalang.compiler.semantics.model.types.BType; @@ -29,7 +25,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.Objects; /** * {@code BResourceFunction} represents a resource function in Ballerina. @@ -82,17 +77,4 @@ public String toString() { type.paramTypes = originalParamTypes; return sb.toString(); } - - @Override - public SemType semType() { - List params = new ArrayList<>(); - params.add(SemTypes.stringConst(accessor.value)); - for (var each : pathSegmentSymbols) { - params.add(Objects.requireNonNullElse(each.type.semType(), PredefinedType.NEVER)); - } - for (var param : this.type.paramTypes) { - params.add(Objects.requireNonNullElse(param.semType(), PredefinedType.NEVER)); - } - return this.type.getSemTypeWithParams(params, new FunctionDefinition()); - } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BAnyType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BAnyType.java index ff9a6f4efe09..0991d500ead1 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BAnyType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BAnyType.java @@ -17,54 +17,40 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.Core; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; import org.ballerinalang.model.Name; import org.ballerinalang.model.types.SelectivelyImmutableReferenceType; import org.ballerinalang.model.types.TypeKind; -import org.wso2.ballerinalang.compiler.semantics.analyzer.Types; 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.Symbols; -import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.util.Flags; -import static io.ballerina.types.PredefinedType.ANY; -import static io.ballerina.types.PredefinedType.VAL_READONLY; - /** * @since 0.94 */ -public class BAnyType extends BType implements SelectivelyImmutableReferenceType { - +public class BAnyType extends BBuiltInRefType implements SelectivelyImmutableReferenceType { private boolean nullable = true; - public BAnyType() { - this(ANY); - } - - public BAnyType(Name name, long flag) { - this(name, flag, Symbols.isFlagOn(flag, Flags.READONLY) ? Core.intersect(ANY, VAL_READONLY) : ANY); + public BAnyType(int tag, BTypeSymbol tsymbol) { + super(tag, tsymbol); } - private BAnyType(Name name, long flags, SemType semType) { - super(TypeTags.ANY, null, semType); + public BAnyType(int tag, BTypeSymbol tsymbol, Name name, long flag) { + super(tag, tsymbol); this.name = name; - this.setFlags(flags); + this.flags = flag; } - private BAnyType(SemType semType) { - super(TypeTags.ANY, null, semType); + public BAnyType(int tag, BTypeSymbol tsymbol, boolean nullable) { + super(tag, tsymbol); + this.nullable = nullable; } - public static BAnyType newNilLiftedBAnyType() { - BAnyType result = new BAnyType(Core.diff(ANY, PredefinedType.NIL)); - result.nullable = false; - return result; - } - - public static BAnyType newImmutableBAnyType() { - return new BAnyType(Types.getImmutableTypeName(TypeKind.ANY.typeName()), Flags.READONLY); + public BAnyType(int tag, BTypeSymbol tsymbol, Name name, long flags, boolean nullable) { + super(tag, tsymbol); + this.name = name; + this.flags = flags; + this.nullable = nullable; } @Override @@ -89,7 +75,7 @@ public void accept(TypeVisitor visitor) { @Override public String toString() { - return !Symbols.isFlagOn(getFlags(), Flags.READONLY) ? getKind().typeName() : + return !Symbols.isFlagOn(flags, Flags.READONLY) ? getKind().typeName() : getKind().typeName().concat(" & readonly"); } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BAnydataType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BAnydataType.java index 4c2c3b9b08ca..cdfe4f488060 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BAnydataType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BAnydataType.java @@ -17,10 +17,6 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.Context; -import io.ballerina.types.Core; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; import org.ballerinalang.model.Name; import org.ballerinalang.model.types.TypeKind; import org.wso2.ballerinalang.compiler.semantics.model.TypeVisitor; @@ -37,54 +33,52 @@ * @since 0.985.0 */ public class BAnydataType extends BUnionType { - private boolean nullable; + private static final int INITIAL_CAPACITY = 10; - private final Context typeCtx; - private BAnydataType(Context typeCtx, BTypeSymbol tsymbol, Name name, long flags, boolean nullable) { - super(typeCtx.env, tsymbol, new LinkedHashSet<>(INITIAL_CAPACITY), false); + public BAnydataType(BTypeSymbol tsymbol, Name name, long flags) { + this(tsymbol, name, flags, true); + } + + public BAnydataType(BTypeSymbol tsymbol, boolean nullable) { + super(tsymbol, new LinkedHashSet<>(INITIAL_CAPACITY), nullable, false); this.tag = TypeTags.ANYDATA; - this.setFlags(flags); + this.isCyclic = true; + } + + public BAnydataType(BTypeSymbol tsymbol, Name name, long flags, boolean nullable) { + super(tsymbol, new LinkedHashSet<>(INITIAL_CAPACITY), nullable, false); + this.tag = TypeTags.ANYDATA; + this.flags = flags; this.name = name; this.isCyclic = true; - this.nullable = nullable; - this.typeCtx = typeCtx; } - public BAnydataType(Context typeCtx, BUnionType type) { - super(type.env, type.tsymbol, new LinkedHashSet<>(type.memberTypes.size()), - Symbols.isFlagOn(type.getFlags(), Flags.READONLY)); + public BAnydataType(BUnionType type) { + super(type.tsymbol, new LinkedHashSet<>(type.memberTypes.size()), type.isNullable(), + Symbols.isFlagOn(type.flags, Flags.READONLY)); this.tag = TypeTags.ANYDATA; this.isCyclic = true; this.name = type.name; - this.setFlags(type.getFlags()); - this.nullable = type.isNullable(); + this.flags = type.flags; mergeUnionType(type); - this.typeCtx = typeCtx; - } - - public static BAnydataType newNilLiftedBAnydataType(BAnydataType type) { - BAnydataType result = new BAnydataType(type.typeCtx, type); - result.nullable = false; - return result; } - public static BAnydataType newImmutableBAnydataType(BAnydataType type, BTypeSymbol typeSymbol, Name name, - boolean nullable) { - return new BAnydataType(type.typeCtx, typeSymbol, name, type.getFlags() | Flags.READONLY, nullable); + public BAnydataType(BAnydataType type, boolean nullable) { + super(type.tsymbol, new LinkedHashSet<>(INITIAL_CAPACITY), nullable, + Symbols.isFlagOn(type.flags, Flags.READONLY)); + this.flags = type.flags; + this.tag = TypeTags.ANYDATA; + this.isCyclic = true; + mergeUnionType(type); } @Override public String toString() { - return !Symbols.isFlagOn(getFlags(), Flags.READONLY) ? getKind().typeName() : + return !Symbols.isFlagOn(flags, Flags.READONLY) ? getKind().typeName() : getKind().typeName().concat(" & readonly"); } - @Override - public boolean isNullable() { - return nullable; - } - @Override public TypeKind getKind() { return TypeKind.ANYDATA; @@ -100,15 +94,4 @@ public R accept(BTypeVisitor visitor, T t) { return visitor.visit(this, t); } - @Override - public SemType semType() { - SemType anydata = Core.createAnydata(typeCtx); - if (!nullable) { - anydata = Core.diff(anydata, PredefinedType.NIL); - } - if (Symbols.isFlagOn(getFlags(), Flags.READONLY)) { - anydata = Core.intersect(anydata, PredefinedType.VAL_READONLY); - } - return anydata; - } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BArrayType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BArrayType.java index 855dfe0c1919..be1b2986bb68 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BArrayType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BArrayType.java @@ -17,10 +17,6 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.CellAtomicType; -import io.ballerina.types.Env; -import io.ballerina.types.SemType; -import io.ballerina.types.definition.ListDefinition; import org.ballerinalang.model.types.ArrayType; import org.ballerinalang.model.types.TypeKind; import org.wso2.ballerinalang.compiler.semantics.model.TypeVisitor; @@ -30,63 +26,40 @@ import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.util.Flags; -import java.util.List; - -import static io.ballerina.types.CellAtomicType.CellMutability.CELL_MUT_LIMITED; -import static io.ballerina.types.CellAtomicType.CellMutability.CELL_MUT_NONE; -import static io.ballerina.types.PredefinedType.NEVER; -import static io.ballerina.types.PredefinedType.VAL; - /** * @since 0.94 */ public class BArrayType extends BType implements ArrayType { - - private static final int NO_FIXED_SIZE = -1; public BType eType; - private int size = NO_FIXED_SIZE; + public int size = -1; public BArrayState state = BArrayState.OPEN; public BArrayType mutableType; - private final Env env; - private ListDefinition ld = null; - public BArrayType(Env env, BType elementType) { + public BArrayType(BType elementType) { super(TypeTags.ARRAY, null); this.eType = elementType; - this.env = env; } - public BArrayType(Env env, BType elementType, BTypeSymbol tsymbol) { + public BArrayType(BType elementType, BTypeSymbol tsymbol) { super(TypeTags.ARRAY, tsymbol); this.eType = elementType; - this.env = env; } - public BArrayType(Env env, BType elementType, BTypeSymbol tsymbol, int size, BArrayState state) { + public BArrayType(BType elementType, BTypeSymbol tsymbol, int size, BArrayState state) { super(TypeTags.ARRAY, tsymbol); this.eType = elementType; this.size = size; this.state = state; - this.env = env; } - public BArrayType(Env env, BType elementType, BTypeSymbol tsymbol, int size, BArrayState state, long flags) { + public BArrayType(BType elementType, BTypeSymbol tsymbol, int size, BArrayState state, long flags) { super(TypeTags.ARRAY, tsymbol, flags); this.eType = elementType; this.size = size; this.state = state; - this.env = env; - } - - /** - * It is required to reset {@link #ld} when the type gets mutated. - * This method is used for that. e.g. When changing Flags.READONLY - */ - protected void restLd() { - ld = null; } @Override @@ -94,17 +67,6 @@ public int getSize() { return size; } - public void setSize(int size) { - if (ld != null) { - // This is dangerous since someone have already captured the SemType may use it in the future. But we have - // cases where we actually do "proper" (i.e not accidental type checks like `isNullable`) type checks and - // then update the size. One option for this may be to poison the semtype, so that using it after this - // point trigger an exception. - ld = null; - } - this.size = size; - } - @Override public BType getElementType() { return eType; @@ -142,66 +104,6 @@ public String toString() { sb.append("[]"); } } - return !Symbols.isFlagOn(getFlags(), Flags.READONLY) ? sb.toString() : sb.append(" & readonly").toString(); - } - - private boolean hasTypeHoles() { - return eType instanceof BNoType; - } - - /** - * When the type is mutated we need to reset the definition used for the semType. - */ - @Override - public void resetSemType() { - ld = null; - } - - // If the element type has a semtype component then it will be represented by that component otherwise with never. - // This means we depend on properly partitioning types to semtype components. Also, we need to ensure member types - // are "ready" when we call this - @Override - public SemType semType() { - if (ld != null) { - return ld.getSemType(env); - } - ld = new ListDefinition(); - if (hasTypeHoles()) { - return ld.defineListTypeWrapped(env, VAL); - } - SemType elementTypeSemType = eType.semType(); - if (elementTypeSemType == null) { - elementTypeSemType = NEVER; - } - boolean isReadonly = Symbols.isFlagOn(getFlags(), Flags.READONLY); - CellAtomicType.CellMutability mut = isReadonly ? CELL_MUT_NONE : CELL_MUT_LIMITED; - // Not entirely sure if I understand this correctly, - // if size == -1 it means T[] - // if size < 0 && not -1 it means T[abs(size)] (and size was inferred) - // else it is the fixed size - if (size != NO_FIXED_SIZE) { - return ld.defineListTypeWrapped(env, List.of(elementTypeSemType), Math.abs(size), NEVER, mut); - } else { - return ld.defineListTypeWrapped(env, List.of(), 0, elementTypeSemType, mut); - } - } - - // This is to ensure call to isNullable won't call semType. In case this is a member of a recursive union otherwise - // this will have an invalid list type since parent union type call this while it is filling its members - @Override - public boolean isNullable() { - return false; - } - - @Override - public void setFlags(long flags) { - super.setFlags(flags); - restLd(); - } - - @Override - public void addFlags(long flags) { - super.addFlags(flags); - restLd(); + return !Symbols.isFlagOn(flags, Flags.READONLY) ? sb.toString() : sb.append(" & readonly").toString(); } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BBuiltInRefType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BBuiltInRefType.java new file mode 100644 index 000000000000..cb8965ec71e1 --- /dev/null +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BBuiltInRefType.java @@ -0,0 +1,67 @@ +/* +* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. licenses this file to you under the Apache License, +* Version 2.0 (the "License"); you may not use this file except +* in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package org.wso2.ballerinalang.compiler.semantics.model.types; + +import org.ballerinalang.model.types.ReferenceType; +import org.ballerinalang.model.types.TypeKind; +import org.wso2.ballerinalang.compiler.semantics.model.symbols.BTypeSymbol; + +import static org.wso2.ballerinalang.compiler.util.TypeTags.ANY; +import static org.wso2.ballerinalang.compiler.util.TypeTags.ANYDATA; +import static org.wso2.ballerinalang.compiler.util.TypeTags.FUTURE; +import static org.wso2.ballerinalang.compiler.util.TypeTags.JSON; +import static org.wso2.ballerinalang.compiler.util.TypeTags.MAP; +import static org.wso2.ballerinalang.compiler.util.TypeTags.STREAM; +import static org.wso2.ballerinalang.compiler.util.TypeTags.TABLE; +import static org.wso2.ballerinalang.compiler.util.TypeTags.TYPEDESC; +import static org.wso2.ballerinalang.compiler.util.TypeTags.XML; + +/** + * @since 0.94 + */ +public class BBuiltInRefType extends BType implements ReferenceType { + + public BBuiltInRefType(int tag, BTypeSymbol tsymbol) { + super(tag, tsymbol); + } + + public BBuiltInRefType(int tag, BTypeSymbol tsymbol, long flags) { + super(tag, tsymbol, flags); + } + + @Override + public R accept(BTypeVisitor visitor, T t) { + return visitor.visit(this, t); + } + + @Override + public TypeKind getKind() { + return switch (tag) { + case JSON -> TypeKind.JSON; + case XML -> TypeKind.XML; + case STREAM -> TypeKind.STREAM; + case TABLE -> TypeKind.TABLE; + case ANY -> TypeKind.ANY; + case ANYDATA -> TypeKind.ANYDATA; + case MAP -> TypeKind.MAP; + case FUTURE -> TypeKind.FUTURE; + case TYPEDESC -> TypeKind.TYPEDESC; + default -> TypeKind.OTHER; + }; + } +} diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BErrorType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BErrorType.java index 972299acb5db..89e0892f9910 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BErrorType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BErrorType.java @@ -17,25 +17,12 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.Core; -import io.ballerina.types.Env; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypes; import org.ballerinalang.model.types.ErrorType; 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.Symbols; import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.util.Flags; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.WeakHashMap; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Supplier; - /** * Represents error type in Ballerina. * @@ -49,23 +36,15 @@ public class BErrorType extends BType implements ErrorType { private static final String ERROR = "error<"; private static final String CLOSE_ERROR = ">"; - private final Env env; - public int distinctId = -1; - private final DistinctIdSupplier distinctIdSupplier; - - public BErrorType(Env env, BTypeSymbol tSymbol, BType detailType) { + public BErrorType(BTypeSymbol tSymbol, BType detailType) { super(TypeTags.ERROR, tSymbol, Flags.READONLY); this.detailType = detailType; this.typeIdSet = BTypeIdSet.emptySet(); - this.env = env; - this.distinctIdSupplier = new DistinctIdSupplier(env); } - public BErrorType(Env env, BTypeSymbol tSymbol) { + public BErrorType(BTypeSymbol tSymbol) { super(TypeTags.ERROR, tSymbol, Flags.READONLY); this.typeIdSet = BTypeIdSet.emptySet(); - this.env = env; - this.distinctIdSupplier = new DistinctIdSupplier(env); } @Override @@ -91,58 +70,4 @@ public String toString() { } return ERROR + detailType + CLOSE_ERROR; } - - public void setDistinctId() { - if (Symbols.isFlagOn(this.getFlags(), Flags.DISTINCT)) { - distinctId = env.distinctAtomCountGetAndIncrement(); - } - } - - @Override - public SemType semType() { - return distinctIdWrapper(semTypeInner()); - } - - SemType distinctIdWrapper(SemType semTypeInner) { - return distinctIdSupplier.get().stream().map(SemTypes::errorDistinct).reduce(semTypeInner, Core::intersect); - } - - private SemType semTypeInner() { - if (this.semType != null) { - return this.semType; - } - - if (detailType == null || detailType.semType() == null) { - // semtype will be null for semantic error - this.semType = PredefinedType.ERROR; - } else { - SemType detail = detailType.semType(); - this.semType = SemTypes.errorDetail(detail); - } - return this.semType; - } - - private final class DistinctIdSupplier implements Supplier> { - - private List ids = null; - private static final Map> allocatedIds = - Collections.synchronizedMap(new WeakHashMap<>()); - private final Env env; - - private DistinctIdSupplier(Env env) { - this.env = env; - allocatedIds.putIfAbsent(env, new ConcurrentHashMap<>()); - } - - public synchronized List get() { - if (ids != null) { - return ids; - } - Map envAllocatedIds = allocatedIds.get(env); - ids = typeIdSet.getAll().stream() - .map(each -> envAllocatedIds.computeIfAbsent(each, (key) -> env.distinctAtomCountGetAndIncrement())) - .toList(); - return ids; - } - } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BFiniteType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BFiniteType.java index 100134cd1fec..45c5512ef81f 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BFiniteType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BFiniteType.java @@ -18,82 +18,50 @@ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.ComplexSemType; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypes; -import io.ballerina.types.subtypedata.BooleanSubtype; -import io.ballerina.types.subtypedata.DecimalSubtype; -import io.ballerina.types.subtypedata.FloatSubtype; -import io.ballerina.types.subtypedata.IntSubtype; -import io.ballerina.types.subtypedata.StringSubtype; +import org.ballerinalang.model.types.FiniteType; 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.util.Names; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangExpression; import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.util.Flags; -import java.util.Optional; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; import java.util.StringJoiner; -import static io.ballerina.types.Core.getComplexSubtypeData; -import static io.ballerina.types.Core.singleShape; -import static io.ballerina.types.SemTypes.isSubtypeSimple; -import static io.ballerina.types.BasicTypeCode.BT_BOOLEAN; -import static io.ballerina.types.BasicTypeCode.BT_DECIMAL; -import static io.ballerina.types.BasicTypeCode.BT_FLOAT; -import static io.ballerina.types.BasicTypeCode.BT_INT; -import static io.ballerina.types.BasicTypeCode.BT_STRING; - /** * {@code BFiniteType} represents the finite type in Ballerina. * */ -public class BFiniteType extends BType { +public class BFiniteType extends BType implements FiniteType { - public SemNamedType[] valueSpace; + private final Set valueSpace; + private boolean nullable = false; + public Boolean isAnyData = null; - public BFiniteType(BTypeSymbol tsymbol, SemNamedType[] valueSpace) { - super(TypeTags.FINITE, tsymbol, Flags.READONLY); - this.valueSpace = valueSpace; - assert validValueSpace(valueSpace); - } - public static BFiniteType newSingletonBFiniteType(BTypeSymbol tsymbol, SemType singletonSemType) { - return new BFiniteType(tsymbol, new SemNamedType[]{ - new SemNamedType(singletonSemType, Optional.empty()) - }); + public BFiniteType(BTypeSymbol tsymbol) { + super(TypeTags.FINITE, tsymbol); + valueSpace = new LinkedHashSet<>(); + this.flags |= Flags.READONLY; } - private boolean validValueSpace(SemNamedType[] valueSpace) { - for (SemNamedType semNamedType : valueSpace) { - if (singleShape(semNamedType.semType()).isEmpty()) { - return false; - } - } - return true; + public BFiniteType(BTypeSymbol tsymbol, Set valueSpace) { + super(TypeTags.FINITE, tsymbol); + this.valueSpace = valueSpace; + this.flags |= Flags.READONLY; } @Override - public TypeKind getKind() { - return TypeKind.FINITE; + public Set getValueSpace() { + return Collections.unmodifiableSet(valueSpace); } @Override - public SemType semType() { - if (this.semType == null) { - this.semType = computeResultantSemType(valueSpace); - } - return this.semType; - } - - private SemType computeResultantSemType(SemNamedType[] valueSpace) { - SemType s = PredefinedType.NEVER; - for (SemNamedType semNamedType : valueSpace) { - s = SemTypes.union(s, semNamedType.semType()); - } - return s; + public TypeKind getKind() { + return TypeKind.FINITE; } @Override @@ -106,47 +74,37 @@ public R accept(BTypeVisitor visitor, T t) { return visitor.visit(this, t); } - @SuppressWarnings("OptionalGetWithoutIsPresent") // xxxSubtypeSingleValue() are guaranteed to have a value @Override public String toString() { StringJoiner joiner = new StringJoiner("|"); - for (SemNamedType semNamedType : valueSpace) { - SemType semType = semNamedType.semType(); - Optional name = semNamedType.optName(); - - if (PredefinedType.NIL.equals(semType)) { - joiner.add(name.orElse(Names.NIL_VALUE.value)); - continue; - } - - ComplexSemType cs = (ComplexSemType) semType; - if (isSubtypeSimple(semType, PredefinedType.BOOLEAN)) { - joiner.add(name.orElse( - BooleanSubtype.booleanSubtypeSingleValue(getComplexSubtypeData(cs, BT_BOOLEAN)).get() ? - Names.TRUE.value : Names.FALSE.value - )); - } else if (isSubtypeSimple(semType, PredefinedType.INT)) { - joiner.add(name.orElse( - Long.toString(IntSubtype.intSubtypeSingleValue(getComplexSubtypeData(cs, BT_INT)).get()) - )); - } else if (isSubtypeSimple(semType, PredefinedType.FLOAT)) { - joiner.add(name.orElse( - Double.toString(FloatSubtype.floatSubtypeSingleValue(getComplexSubtypeData(cs, BT_FLOAT)).get()) - ) + "f"); - } else if (isSubtypeSimple(semType, PredefinedType.DECIMAL)) { - joiner.add(name.orElse( - DecimalSubtype.decimalSubtypeSingleValue(getComplexSubtypeData(cs, BT_DECIMAL)).get() - .toPlainString() - ) + "d"); - } else if (isSubtypeSimple(semType, PredefinedType.STRING)) { - joiner.add("\"" + name.orElse( - StringSubtype.stringSubtypeSingleValue(getComplexSubtypeData(cs, BT_STRING)).get() - ) + "\""); - } else { - throw new IllegalStateException("Unexpected value space type in BFiniteType: " + semType); + for (BLangExpression value : this.valueSpace) { + switch (value.getBType().tag) { + case TypeTags.FLOAT: + joiner.add(value + "f"); + break; + case TypeTags.DECIMAL: + joiner.add(value + "d"); + break; + case TypeTags.STRING: + case TypeTags.CHAR_STRING: + joiner.add("\"" + value + "\""); + break; + default: + joiner.add(value.toString()); } } - return joiner.toString(); } + + @Override + public boolean isNullable() { + return nullable; + } + + public void addValue(BLangExpression value) { + this.valueSpace.add(value); + if (!this.nullable && value.getBType() != null && value.getBType().isNullable()) { + this.nullable = true; + } + } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BFutureType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BFutureType.java index 33065fa3c05b..4cb0b0b72cd7 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BFutureType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BFutureType.java @@ -16,12 +16,7 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.Env; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypes; import org.ballerinalang.model.types.ConstrainedType; -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.util.TypeTags; @@ -31,48 +26,31 @@ * * @since 0.965.0 */ -public class BFutureType extends BType implements ConstrainedType { +public class BFutureType extends BBuiltInRefType implements ConstrainedType { public BType constraint; public boolean workerDerivative; - private final Env env; - public BFutureType(Env env, BType constraint, BTypeSymbol tsymbol) { - super(TypeTags.FUTURE, tsymbol); + public BFutureType(int tag, BType constraint, BTypeSymbol tsymbol) { + super(tag, tsymbol); this.constraint = constraint; - this.env = env; } - public BFutureType(Env env, BType constraint, BTypeSymbol tsymbol, boolean workerDerivative) { - this(env, constraint, tsymbol); + public BFutureType(int tag, BType constraint, BTypeSymbol tsymbol, boolean workerDerivative) { + this(tag, constraint, tsymbol); this.workerDerivative = workerDerivative; } - public BFutureType(Env env, BType constraint, BTypeSymbol tsymbol, SemType semType) { - this(env, constraint, tsymbol); - this.semType = semType; - } - @Override public BType getConstraint() { return constraint; } - public void setConstraint(BType constraint) { - this.constraint = constraint; - this.semType = null; - } - @Override public R accept(BTypeVisitor visitor, T t) { return visitor.visit(this, t); } - - @Override - public TypeKind getKind() { - return TypeKind.FUTURE; - } - + @Override public String toString() { if (constraint.tag == TypeTags.NONE || constraint.tag == TypeTags.SEMANTIC_ERROR @@ -87,18 +65,4 @@ public String toString() { public void accept(TypeVisitor visitor) { visitor.visit(this); } - - @Override - public SemType semType() { - if (this.semType != null) { - return this.semType; - } - - if (constraint == null || constraint instanceof BNoType) { - this.semType = PredefinedType.FUTURE; - } else { - this.semType = SemTypes.futureContaining(env, constraint.semType()); - } - return this.semType; - } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BHandleType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BHandleType.java index dcc4540cb8e9..8c535433699d 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BHandleType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BHandleType.java @@ -17,10 +17,9 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.PredefinedType; import org.ballerinalang.model.types.TypeKind; import org.wso2.ballerinalang.compiler.semantics.model.TypeVisitor; -import org.wso2.ballerinalang.compiler.util.TypeTags; +import org.wso2.ballerinalang.compiler.semantics.model.symbols.BTypeSymbol; import org.wso2.ballerinalang.util.Flags; /** @@ -30,10 +29,10 @@ * * @since 1.0.0 */ -public class BHandleType extends BType { +public class BHandleType extends BBuiltInRefType { - public BHandleType() { - super(TypeTags.HANDLE, null, Flags.READONLY, PredefinedType.HANDLE); + public BHandleType(int tag, BTypeSymbol tsymbol) { + super(tag, tsymbol, Flags.READONLY); } @Override diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BIntSubType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BIntSubType.java index 675fa600ccc2..13dd337a6c39 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BIntSubType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BIntSubType.java @@ -17,12 +17,10 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypes; import org.ballerinalang.model.Name; import org.ballerinalang.model.types.TypeKind; +import org.wso2.ballerinalang.compiler.semantics.model.TypeVisitor; import org.wso2.ballerinalang.compiler.util.Names; -import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.util.Flags; /** @@ -32,44 +30,55 @@ */ public class BIntSubType extends BType { - public static final BIntSubType SIGNED32 = new BIntSubType(TypeTags.SIGNED32_INT, Names.SIGNED32, SemTypes.SINT32); - public static final BIntSubType SIGNED16 = new BIntSubType(TypeTags.SIGNED16_INT, Names.SIGNED16, SemTypes.SINT16); - public static final BIntSubType SIGNED8 = new BIntSubType(TypeTags.SIGNED8_INT, Names.SIGNED8, SemTypes.SINT8); + public BIntSubType(int tag, Name name) { - public static final BIntSubType UNSIGNED32 = new BIntSubType(TypeTags.UNSIGNED32_INT, Names.UNSIGNED32, - SemTypes.UINT32); - public static final BIntSubType UNSIGNED16 = new BIntSubType(TypeTags.UNSIGNED16_INT, Names.UNSIGNED16, - SemTypes.UINT16); - public static final BIntSubType UNSIGNED8 = new BIntSubType(TypeTags.UNSIGNED8_INT, Names.UNSIGNED8, - SemTypes.UINT8); - - private BIntSubType(int tag, Name name, SemType semType) { - super(tag, null, name, Flags.READONLY, semType); + super(tag, null, name, Flags.READONLY); } @Override public boolean isNullable() { + return false; } @Override public R accept(BTypeVisitor visitor, T t) { + return visitor.visit(this, t); } @Override public TypeKind getKind() { + return TypeKind.INT; } + @Override + public void accept(TypeVisitor visitor) { + + visitor.visit(this); + } + @Override public String toString() { + return Names.INT.value + Names.ALIAS_SEPARATOR + name; } @Override public String getQualifiedTypeName() { + return Names.BALLERINA_ORG.value + Names.ORG_NAME_SEPARATOR.value + Names.LANG.value + Names.DOT.value + Names.INT.value + Names.ALIAS_SEPARATOR + name; } + + public boolean isAnydata() { + + return true; + } + + public boolean isPureType() { + + return true; + } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BIntersectionType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BIntersectionType.java index bd80e473972f..6c3bba3fcfe5 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BIntersectionType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BIntersectionType.java @@ -17,12 +17,8 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypes; import org.ballerinalang.model.types.IntersectionType; import org.ballerinalang.model.types.TypeKind; -import org.wso2.ballerinalang.compiler.semantics.analyzer.Types; 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.Symbols; @@ -49,14 +45,14 @@ public BIntersectionType(BTypeSymbol tsymbol, LinkedHashSet types, BType effectiveType) { super(TypeTags.INTERSECTION, tsymbol); this.constituentTypes = toFlatTypeSet(types); + this.effectiveType = effectiveType; for (BType constituentType : this.constituentTypes) { if (constituentType.tag == TypeTags.READONLY) { - this.addFlags(Flags.READONLY); + this.flags |= Flags.READONLY; break; } } - this.effectiveType = effectiveType; } public BIntersectionType(BTypeSymbol tsymbol) { @@ -85,13 +81,18 @@ public void accept(TypeVisitor visitor) { visitor.visit(this); } + @Override + public boolean isNullable() { + return this.effectiveType.isNullable(); + } + @Override public R accept(BTypeVisitor visitor, T t) { return visitor.visit(this, t); } public void setConstituentTypes(LinkedHashSet constituentTypes) { - this.constituentTypes = toFlatTypeSet(constituentTypes); + this.constituentTypes = toFlatTypeSet(constituentTypes); } @Override @@ -133,34 +134,4 @@ private static LinkedHashSet toFlatTypeSet(LinkedHashSet types) { public BType getEffectiveType() { return this.effectiveType; } - - /** - * When the type is mutated we need to reset resolved semType. - */ - public void resetSemType() { - this.semType = null; - } - - @Override - public SemType semType() { - // We have to recalculate this everytime since the actual BTypes inside constituent types do mutate and we - // can't detect those mutations. - return computeResultantIntersection(); - } - - private SemType computeResultantIntersection() { - SemType t = PredefinedType.VAL; - for (BType constituentType : this.getConstituentTypes()) { - t = SemTypes.intersect(t, constituentType.semType()); - } - - // TODO: this is a temporary workaround to propagate effective typeIds - BType referredType = Types.getReferredType(this.effectiveType); - if (referredType instanceof BErrorType effErr) { - t = effErr.distinctIdWrapper(t); - } else if (referredType instanceof BObjectType effObj) { - t = effObj.distinctIdWrapper(t); - } - return t; - } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BInvokableType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BInvokableType.java index 86d23257ed77..3882ba40fde0 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BInvokableType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BInvokableType.java @@ -17,17 +17,8 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.CellAtomicType; -import io.ballerina.types.Env; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypes; -import io.ballerina.types.definition.FunctionDefinition; -import io.ballerina.types.definition.FunctionQualifiers; -import io.ballerina.types.definition.ListDefinition; import org.ballerinalang.model.types.InvokableType; import org.ballerinalang.model.types.TypeKind; -import org.wso2.ballerinalang.compiler.semantics.analyzer.Types; 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.Symbols; @@ -35,10 +26,7 @@ import org.wso2.ballerinalang.util.Flags; import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; import java.util.List; -import java.util.Set; /** * @since 0.94 @@ -46,39 +34,23 @@ public class BInvokableType extends BType implements InvokableType { public List paramTypes; - // TODO: make these final public BType restType; public BType retType; - private final Env env; - private FunctionDefinition defn; - public BInvokableType(Env env, List paramTypes, BType restType, BType retType, BTypeSymbol tsymbol) { + public BInvokableType(List paramTypes, BType restType, BType retType, BTypeSymbol tsymbol) { super(TypeTags.INVOKABLE, tsymbol, Flags.READONLY); - this.paramTypes = Collections.unmodifiableList(paramTypes); - assert restType == null || restType instanceof BArrayType || restType.tag == TypeTags.SEMANTIC_ERROR; + this.paramTypes = paramTypes; this.restType = restType; this.retType = retType; - this.env = env; } - public BInvokableType(Env env, List paramTypes, BType retType, BTypeSymbol tsymbol) { - this(env, paramTypes, null, retType, tsymbol); + public BInvokableType(List paramTypes, BType retType, BTypeSymbol tsymbol) { + this(paramTypes, null, retType, tsymbol); } - public BInvokableType(Env env, BTypeSymbol tSymbol) { + public BInvokableType(BTypeSymbol tSymbol) { super(TypeTags.INVOKABLE, tSymbol, Flags.READONLY); - this.paramTypes = List.of(); - this.env = env; - } - - public void addParamType(BType type) { - List newParams = new ArrayList<>(paramTypes); - newParams.add(type); - paramTypes = Collections.unmodifiableList(newParams); - } - - public void setParamTypes(List paramTypes) { - this.paramTypes = Collections.unmodifiableList(paramTypes); + this.paramTypes = new ArrayList<>(); } @Override @@ -104,13 +76,13 @@ public R accept(BTypeVisitor visitor, T t) { @Override public String toString() { String flagStr = ""; - if (Symbols.isFlagOn(getFlags(), Flags.ISOLATED)) { + if (Symbols.isFlagOn(flags, Flags.ISOLATED)) { flagStr = "isolated "; } - if (Symbols.isFlagOn(getFlags(), Flags.TRANSACTIONAL)) { + if (Symbols.isFlagOn(flags, Flags.TRANSACTIONAL)) { flagStr += "transactional "; } - if (Symbols.isFlagOn(getFlags(), Flags.ANY_FUNCTION)) { + if (Symbols.isFlagOn(flags, Flags.ANY_FUNCTION)) { return flagStr + "function"; } return flagStr + "function " + getTypeSignature(); @@ -125,7 +97,7 @@ public boolean equals(Object o) { return false; } - if (this.getFlags() != that.getFlags()) { + if (this.flags != that.flags) { return false; } @@ -183,129 +155,4 @@ private static String getBTypeListAsString(List typeNames) { public void accept(TypeVisitor visitor) { visitor.visit(this); } - - @Override - public boolean isNullable() { - return false; - } - - /** - * When the type is mutated we need to reset the definition used for the semType. - */ - @Override - public void resetSemType() { - defn = null; - } - - @Override - public SemType semType() { - if (isFunctionTop()) { - if (Symbols.isFlagOn(getFlags(), Flags.ISOLATED) || Symbols.isFlagOn(getFlags(), Flags.TRANSACTIONAL)) { - FunctionQualifiers qualifiers = - FunctionQualifiers.from(env, Symbols.isFlagOn(getFlags(), Flags.ISOLATED), - Symbols.isFlagOn(getFlags(), Flags.TRANSACTIONAL)); - FunctionDefinition definition = new FunctionDefinition(); - return definition.define(env, PredefinedType.NEVER, PredefinedType.VAL, qualifiers); - } - return PredefinedType.FUNCTION; - } - if (defn != null) { - return defn.getSemType(env); - } - FunctionDefinition fd = new FunctionDefinition(); - this.defn = fd; - List params = this.paramTypes.stream().map(BInvokableType::from).toList(); - return getSemTypeWithParams(params, fd); - } - - public SemType getSemTypeWithParams(List params, FunctionDefinition fd) { - SemType rest; - if (restType instanceof BArrayType arrayType) { - rest = from(arrayType.eType); - } else { - // Is this correct even when type is semantic error? - rest = PredefinedType.NEVER; - } - SemType returnType = resolveReturnType(); - ListDefinition paramListDefinition = new ListDefinition(); - SemType paramTypes = paramListDefinition.defineListTypeWrapped(env, params, params.size(), rest, - CellAtomicType.CellMutability.CELL_MUT_NONE); - // TODO: probably we need to move this method from Types. - boolean isGeneric = Types.containsTypeParams(this); - FunctionQualifiers qualifiers = FunctionQualifiers.from(env, Symbols.isFlagOn(getFlags(), Flags.ISOLATED), - Symbols.isFlagOn(getFlags(), Flags.TRANSACTIONAL)); - if (isGeneric) { - return fd.defineGeneric(env, paramTypes, returnType, qualifiers); - } - return fd.define(env, paramTypes, returnType, qualifiers); - } - - private SemType resolveReturnType() { - if (retType == null) { - return PredefinedType.NIL; - } - SemType innerType = from(retType); - ListDefinition ld = new ListDefinition(); - return ld.tupleTypeWrapped(env, isDependentlyTyped(retType, - new HashSet<>()) ? SemTypes.booleanConst(true) : PredefinedType.BOOLEAN, innerType); - } - - private static boolean isDependentlyTyped(BType returnType, Set visited) { - if (visited.contains(returnType)) { - return false; - } - - visited.add(returnType); - - // it doesn't seem we actually have a flag to check this, may be the correct way to do this is to have a - // method in BType for this, but given this is a temporary thing, this should be enough. - if (returnType instanceof BParameterizedType) { - return true; - } - if (returnType instanceof BUnionType unionType) { - return unionType.getMemberTypes().stream().anyMatch(returnType1 -> - isDependentlyTyped(returnType1, visited)); - } - if (returnType instanceof BMapType mapType) { - return isDependentlyTyped(mapType.constraint, visited); - } - if (returnType instanceof BRecordType recordType) { - return recordType.fields.values().stream().anyMatch(field -> isDependentlyTyped(field.type, visited)) || - isDependentlyTyped(recordType.restFieldType, visited); - } - if (returnType instanceof BArrayType arrayType) { - return isDependentlyTyped(arrayType.eType, visited); - } - if (returnType instanceof BTupleType tupleType) { - return tupleType.getTupleTypes().stream().anyMatch(returnType1 -> isDependentlyTyped(returnType1, visited)); - } - if (returnType instanceof BInvokableType invokableType) { - return invokableType.paramTypes.stream().anyMatch(returnType1 -> - isDependentlyTyped(returnType1, visited)) || - isDependentlyTyped(invokableType.retType, visited) || - isDependentlyTyped(invokableType.restType, visited); - } - if (returnType instanceof BFutureType futureType) { - return isDependentlyTyped(futureType.constraint, visited); - } - if (returnType instanceof BTableType tableType) { - return isDependentlyTyped(tableType.constraint, visited); - } - if (returnType instanceof BStreamType streamType) { - return isDependentlyTyped(streamType.constraint, visited); - } - return false; - } - - private static SemType from(BType type) { - SemType semType = type.semType(); - if (semType == null) { - semType = PredefinedType.NEVER; - } - return semType; - } - - private boolean isFunctionTop() { - return paramTypes.isEmpty() && restType == null && retType == null; - } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BJSONType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BJSONType.java index 78f81599f2e3..46b3c81d955b 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BJSONType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BJSONType.java @@ -17,10 +17,6 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.Context; -import io.ballerina.types.Core; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; import org.ballerinalang.model.types.TypeKind; import org.wso2.ballerinalang.compiler.semantics.model.TypeVisitor; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BTypeSymbol; @@ -34,49 +30,37 @@ * @since 0.94 */ public class BJSONType extends BUnionType { - private boolean nullable = true; + private static final int INITIAL_CAPACITY = 8; - private final Context typeCtx; - public BJSONType(Context typeCtx, BUnionType type) { - super(type.env, type.tsymbol, new LinkedHashSet<>(INITIAL_CAPACITY), Symbols.isFlagOn(type.getFlags(), - Flags.READONLY)); + public BJSONType(BJSONType type, boolean nullable) { + super(type.tsymbol, new LinkedHashSet<>(INITIAL_CAPACITY), nullable, + Symbols.isFlagOn(type.flags, Flags.READONLY)); mergeUnionType(type); this.tag = TypeTags.JSON; this.isCyclic = true; - this.typeCtx = typeCtx; } - private BJSONType(Context typeCtx, BTypeSymbol typeSymbol, boolean nullable, long flags) { - super(typeCtx.env, typeSymbol, new LinkedHashSet<>(INITIAL_CAPACITY), Symbols.isFlagOn(flags, Flags.READONLY)); - this.setFlags(flags); + public BJSONType(BUnionType type) { + super(type.tsymbol, new LinkedHashSet<>(INITIAL_CAPACITY), type.isNullable(), Symbols.isFlagOn(type.flags, + Flags.READONLY)); + mergeUnionType(type); this.tag = TypeTags.JSON; - this.isCyclic = true; - this.nullable = nullable; - this.typeCtx = typeCtx; - } - - public static BJSONType newNilLiftedBJSONType(BJSONType type) { - BJSONType result = new BJSONType(type.typeCtx, type); - result.nullable = false; - return result; } - public static BJSONType newImmutableBJSONType(BJSONType type, BTypeSymbol typeSymbol, boolean nullable) { - return new BJSONType(type.typeCtx, typeSymbol, nullable, type.getFlags() | Flags.READONLY); + public BJSONType(BTypeSymbol typeSymbol, boolean nullable, long flags) { + super(typeSymbol, new LinkedHashSet<>(INITIAL_CAPACITY), nullable, Symbols.isFlagOn(flags, Flags.READONLY)); + this.flags = flags; + this.tag = TypeTags.JSON; + this.isCyclic = true; } @Override public String toString() { - return !Symbols.isFlagOn(getFlags(), Flags.READONLY) ? getKind().typeName() : + return !Symbols.isFlagOn(flags, Flags.READONLY) ? getKind().typeName() : getKind().typeName().concat(" & readonly"); } - @Override - public boolean isNullable() { - return nullable; - } - @Override public TypeKind getKind() { return TypeKind.JSON; @@ -91,17 +75,4 @@ public void accept(TypeVisitor visitor) { public R accept(BTypeVisitor visitor, T t) { return visitor.visit(this, t); } - - @Override - public SemType semType() { - SemType json = Core.createJson(typeCtx); - // TODO: refer to https://github.com/ballerina-platform/ballerina-lang/issues/43343#issuecomment-2485247172 -// if (!nullable) { -// json = Core.diff(json, PredefinedType.NIL); -// } - if (Symbols.isFlagOn(getFlags(), Flags.READONLY)) { - json = Core.intersect(json, PredefinedType.VAL_READONLY); - } - return json; - } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BMapType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BMapType.java index 6efc4a020d33..3112abb1d6c8 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BMapType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BMapType.java @@ -17,54 +17,29 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.CellAtomicType; -import io.ballerina.types.Env; -import io.ballerina.types.SemType; -import io.ballerina.types.definition.MappingDefinition; import org.ballerinalang.model.types.ConstrainedType; import org.ballerinalang.model.types.SelectivelyImmutableReferenceType; -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.Symbols; import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.util.Flags; -import java.util.List; - -import static io.ballerina.types.CellAtomicType.CellMutability.CELL_MUT_LIMITED; -import static io.ballerina.types.CellAtomicType.CellMutability.CELL_MUT_NONE; -import static io.ballerina.types.PredefinedType.NEVER; -import static io.ballerina.types.PredefinedType.VAL; - /** * @since 0.94 */ -public class BMapType extends BType implements ConstrainedType, SelectivelyImmutableReferenceType { +public class BMapType extends BBuiltInRefType implements ConstrainedType, SelectivelyImmutableReferenceType { public BType constraint; public BMapType mutableType; - private final Env env; - private MappingDefinition md = null; - - public BMapType(Env env, int tag, BType constraint, BTypeSymbol tsymbol) { + public BMapType(int tag, BType constraint, BTypeSymbol tsymbol) { super(tag, tsymbol); this.constraint = constraint; - this.env = env; } - public BMapType(Env env, int tag, BType constraint, BTypeSymbol tsymbol, long flags) { + public BMapType(int tag, BType constraint, BTypeSymbol tsymbol, long flags) { super(tag, tsymbol, flags); this.constraint = constraint; - this.env = env; - } - - /** - * It is required to reset {@link #md} when the type gets mutated. - * This method is used for that. e.g. When changing Flags.READONLY - */ - protected void restMd() { - md = null; } @Override @@ -77,11 +52,6 @@ public R accept(BTypeVisitor visitor, T t) { return visitor.visit(this, t); } - @Override - public TypeKind getKind() { - return TypeKind.MAP; - } - @Override public String toString() { String stringRep; @@ -92,63 +62,11 @@ public String toString() { stringRep = super.toString() + "<" + constraint + ">"; } - return !Symbols.isFlagOn(getFlags(), Flags.READONLY) ? stringRep : stringRep.concat(" & readonly"); + return !Symbols.isFlagOn(flags, Flags.READONLY) ? stringRep : stringRep.concat(" & readonly"); } @Override public void accept(TypeVisitor visitor) { visitor.visit(this); } - - private boolean hasTypeHoles() { - return constraint instanceof BNoType; - } - - /** - * When the type is mutated we need to reset the definition used for the semType. - */ - @Override - public void resetSemType() { - md = null; - } - - // If the member has a semtype component then it will be represented by that component otherwise with never. This - // means we depend on properly partitioning types to semtype components. Also, we need to ensure member types are - // "ready" when we call this - @Override - public SemType semType() { - if (md != null) { - return md.getSemType(env); - } - md = new MappingDefinition(); - if (hasTypeHoles()) { - return md.defineMappingTypeWrapped(env, List.of(), VAL); - } - SemType elementTypeSemType = constraint.semType(); - if (elementTypeSemType == null) { - elementTypeSemType = NEVER; - } - boolean isReadonly = Symbols.isFlagOn(getFlags(), Flags.READONLY); - CellAtomicType.CellMutability mut = isReadonly ? CELL_MUT_NONE : CELL_MUT_LIMITED; - return md.defineMappingTypeWrapped(env, List.of(), elementTypeSemType, mut); - } - - // This is to ensure call to isNullable won't call semType. In case this is a member of a recursive union otherwise - // this will have an invalid map type since parent union type call this while it is filling its members - @Override - public boolean isNullable() { - return false; - } - - @Override - public void setFlags(long flags) { - super.setFlags(flags); - restMd(); - } - - @Override - public void addFlags(long flags) { - super.addFlags(flags); - restMd(); - } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BNeverType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BNeverType.java index 7dd18758dbfb..fd43d8e3d06f 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BNeverType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BNeverType.java @@ -17,7 +17,6 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.PredefinedType; import org.wso2.ballerinalang.compiler.semantics.model.TypeVisitor; import org.wso2.ballerinalang.compiler.util.Names; import org.wso2.ballerinalang.compiler.util.TypeTags; @@ -32,8 +31,13 @@ public class BNeverType extends BType { - protected BNeverType() { - super(TypeTags.NEVER, null, Flags.READONLY, PredefinedType.NEVER); + public BNeverType() { + super(TypeTags.NEVER, null, Flags.READONLY); + } + + @Override + public boolean isNullable() { + return false; } @Override diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BNilType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BNilType.java index 0b821361a5c9..8abb31ab1370 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BNilType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BNilType.java @@ -17,7 +17,8 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.PredefinedType; +import org.ballerinalang.model.types.NullType; +import org.wso2.ballerinalang.compiler.semantics.model.TypeVisitor; import org.wso2.ballerinalang.compiler.util.Names; import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.util.Flags; @@ -28,14 +29,24 @@ * * @since 0.970.0 */ -public class BNilType extends BType { +public class BNilType extends BType implements NullType { - BNilType() { - super(TypeTags.NIL, null, Flags.READONLY, PredefinedType.NIL); + public BNilType() { + super(TypeTags.NIL, null, Flags.READONLY); + } + + @Override + public boolean isNullable() { + return true; } @Override public String toString() { return Names.NIL_VALUE.value; } + + @Override + public void accept(TypeVisitor visitor) { + visitor.visit(this); + } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BNoType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BNoType.java index f3a95d660c68..3a4abd20fde8 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BNoType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BNoType.java @@ -17,7 +17,6 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.PredefinedType; import org.ballerinalang.model.types.NoType; import org.wso2.ballerinalang.compiler.semantics.model.TypeVisitor; @@ -27,7 +26,7 @@ public class BNoType extends BType implements NoType { public BNoType(int tag) { - super(tag, null, PredefinedType.UNDEF); + super(tag, null); } @Override diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BObjectType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BObjectType.java index 59ac8e697a79..8abd29cc8474 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BObjectType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BObjectType.java @@ -17,14 +17,6 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.Core; -import io.ballerina.types.Env; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypes; -import io.ballerina.types.definition.Member; -import io.ballerina.types.definition.ObjectDefinition; -import io.ballerina.types.definition.ObjectQualifiers; import org.ballerinalang.model.types.ObjectType; import org.ballerinalang.model.types.TypeKind; import org.wso2.ballerinalang.compiler.semantics.model.TypeVisitor; @@ -36,17 +28,6 @@ import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.util.Flags; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.WeakHashMap; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Supplier; - /** * {@code BObjectType} represents object type in Ballerina. * @@ -61,7 +42,6 @@ public class BObjectType extends BStructureType implements ObjectType { private static final String RIGHT_CURL = "}"; private static final String SEMI_COLON = ";"; private static final String READONLY = "readonly"; - private final Env env; public boolean markedIsolatedness; public BObjectType mutableType = null; @@ -69,21 +49,12 @@ public class BObjectType extends BStructureType implements ObjectType { public BTypeIdSet typeIdSet = new BTypeIdSet(); - private ObjectDefinition od = null; - private final DistinctIdSupplier distinctIdSupplier; - - public BObjectType(Env env, BTypeSymbol tSymbol) { + public BObjectType(BTypeSymbol tSymbol) { super(TypeTags.OBJECT, tSymbol); - assert env != null; - this.env = env; - this.distinctIdSupplier = new DistinctIdSupplier(env); } - public BObjectType(Env env, BTypeSymbol tSymbol, long flags) { + public BObjectType(BTypeSymbol tSymbol, long flags) { super(TypeTags.OBJECT, tSymbol, flags); - assert env != null; - this.env = env; - this.distinctIdSupplier = new DistinctIdSupplier(env); } @Override @@ -101,104 +72,6 @@ public R accept(BTypeVisitor visitor, T t) { return visitor.visit(this, t); } - private boolean hasTypeHoles() { - return fields.values().stream().anyMatch(field -> field.type instanceof BNoType); - } - - /** - * When the type is mutated we need to reset the definition used for the semType. - */ - @Override - public void resetSemType() { - od = null; - } - - @Override - public SemType semType() { - return distinctIdWrapper(semTypeInner()); - } - - SemType distinctIdWrapper(SemType semTypeInner) { - return distinctIdSupplier.get().stream().map(SemTypes::objectDistinct).reduce(semTypeInner, Core::intersect); - } - - private SemType semTypeInner() { - if (od != null) { - return od.getSemType(env); - } - od = new ObjectDefinition(); - // I don't think this is actually possible - assert !hasTypeHoles() : "unimplemented"; - List members = new ArrayList<>(fields.size()); - ObjectQualifiers qualifiers = getObjectQualifiers(); - Set memberNames = new HashSet<>(); - for (BField field : fields.values()) { - Optional member = createMember(field, qualifiers.readonly(), memberNames); - member.ifPresent(members::add); - } - - BObjectTypeSymbol objectSymbol = (BObjectTypeSymbol) this.tsymbol; - for (BAttachedFunction fun : objectSymbol.attachedFuncs) { - Optional member = createMember(fun, memberNames); - member.ifPresent(members::add); - } - return od.define(env, qualifiers, members); - } - - private static Optional createMember(BAttachedFunction func, Set visitedFields) { - String name = func.funcName.value; - if (Symbols.isFlagOn(func.symbol.flags, Flags.REMOTE)) { - name = "$remote$" + name; - } - if (visitedFields.contains(name)) { - return Optional.empty(); - } - visitedFields.add(name); - Member.Visibility visibility = Symbols.isFlagOn(func.symbol.flags, Flags.PUBLIC) ? - Member.Visibility.Public : Member.Visibility.Private; - SemType type = func.semType(); - assert type != null : "function type is fully implemented"; - assert !Core.isNever(type) : "method can't be never"; - return Optional.of(new Member(name, type, Member.Kind.Method, visibility, true)); - } - - private static Optional createMember(BField field, boolean readonlyObject, Set visitedFields) { - String name = field.name.value; - if (visitedFields.contains(name)) { - return Optional.empty(); - } - visitedFields.add(name); - Member.Visibility visibility = Symbols.isFlagOn(field.symbol.flags, Flags.PUBLIC) ? - Member.Visibility.Public : Member.Visibility.Private; - SemType type = field.type.semType(); - if (type == null) { - type = PredefinedType.NEVER; - } - boolean immutableField; - if (readonlyObject || Symbols.isFlagOn(field.symbol.flags, Flags.READONLY)) { - type = Core.intersect(type, PredefinedType.VAL_READONLY); - immutableField = true; - } else { - immutableField = false; - } - return Optional.of(new Member(name, type, Member.Kind.Field, visibility, immutableField)); - } - - private ObjectQualifiers getObjectQualifiers() { - long flags = tsymbol.flags; - boolean isolated = Symbols.isFlagOn(this.tsymbol.flags, Flags.ISOLATED); - ObjectQualifiers.NetworkQualifier networkQualifier; - if (Symbols.isFlagOn(flags, Flags.SERVICE)) { - networkQualifier = ObjectQualifiers.NetworkQualifier.Service; - } else if (Symbols.isFlagOn(flags, Flags.CLIENT)) { - networkQualifier = ObjectQualifiers.NetworkQualifier.Client; - } else { - networkQualifier = ObjectQualifiers.NetworkQualifier.None; - } - boolean readonly = Symbols.isFlagOn(this.tsymbol.flags, Flags.READONLY); - return new ObjectQualifiers(isolated, readonly, networkQualifier); - } - @Override public String toString() { if (shouldPrintShape()) { @@ -246,35 +119,4 @@ public String toString() { } return this.tsymbol.toString(); } - - // This is to ensure call to isNullable won't call semType. In case this is a member of a recursive union otherwise - // this will have an invalid object type since parent union type call this while it is filling its members - @Override - public boolean isNullable() { - return false; - } - - private final class DistinctIdSupplier implements Supplier> { - - private List ids = null; - private static final Map> allocatedIds = - Collections.synchronizedMap(new WeakHashMap<>()); - private final Env env; - - private DistinctIdSupplier(Env env) { - this.env = env; - allocatedIds.putIfAbsent(env, new ConcurrentHashMap<>()); - } - - public synchronized List get() { - if (ids != null) { - return ids; - } - Map envAllocatedIds = allocatedIds.get(env); - ids = typeIdSet.getAll().stream() - .map(each -> envAllocatedIds.computeIfAbsent(each, (key) -> env.distinctAtomCountGetAndIncrement())) - .toList(); - return ids; - } - } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BParameterizedType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BParameterizedType.java index b4aa3a60a095..f966d588da46 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BParameterizedType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BParameterizedType.java @@ -17,7 +17,6 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.SemType; 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; @@ -46,6 +45,11 @@ public BParameterizedType(BType valueType, BVarSymbol paramSymbol, BTypeSymbol t this.paramIndex = paramIndex; } + @Override + public boolean isNullable() { + return false; + } + @Override public String toString() { return this.paramSymbol.name.toString(); @@ -60,9 +64,4 @@ public void accept(TypeVisitor visitor) { public R accept(BTypeVisitor visitor, T t) { return visitor.visit(this, t); } - - @Override - public SemType semType() { - return this.paramValueType.semType(); - } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BReadonlyType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BReadonlyType.java index eab400866809..b59d62a41f4a 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BReadonlyType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BReadonlyType.java @@ -17,40 +17,36 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.Core; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; +import org.ballerinalang.model.Name; import org.ballerinalang.model.types.TypeKind; -import org.wso2.ballerinalang.compiler.util.TypeTags; +import org.wso2.ballerinalang.compiler.semantics.model.symbols.BTypeSymbol; import org.wso2.ballerinalang.util.Flags; -import static io.ballerina.types.PredefinedType.VAL_READONLY; - /** * {@code BReadonlyType} represents the shapes that have their read-only bit on. * * @since 1.3.0 */ -public class BReadonlyType extends BType { +public class BReadonlyType extends BBuiltInRefType { private boolean nullable = true; - public BReadonlyType() { - this(VAL_READONLY); - } - - public BReadonlyType(long flag) { - super(TypeTags.READONLY, null, flag | Flags.READONLY, VAL_READONLY); + public BReadonlyType(int tag, BTypeSymbol tsymbol) { + super(tag, tsymbol); + this.flags |= Flags.READONLY; } - private BReadonlyType(SemType semType) { - super(TypeTags.READONLY, null, Flags.READONLY, semType); + public BReadonlyType(int tag, BTypeSymbol tsymbol, Name name, long flag) { + super(tag, tsymbol); + this.name = name; + this.flags = flag; + this.flags |= Flags.READONLY; } - public static BReadonlyType newNilLiftedBReadonlyType() { - BReadonlyType result = new BReadonlyType(Core.diff(VAL_READONLY, PredefinedType.NIL)); - result.nullable = false; - return result; + public BReadonlyType(int tag, BTypeSymbol tsymbol, boolean nullable) { + super(tag, tsymbol); + this.nullable = nullable; + this.flags |= Flags.READONLY; } @Override 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 95200e5c6a57..a6933f7e6856 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 @@ -17,12 +17,6 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.CellAtomicType; -import io.ballerina.types.Core; -import io.ballerina.types.Env; -import io.ballerina.types.SemType; -import io.ballerina.types.definition.Field; -import io.ballerina.types.definition.MappingDefinition; import org.ballerinalang.model.types.RecordType; import org.ballerinalang.model.types.TypeKind; import org.wso2.ballerinalang.compiler.semantics.model.TypeVisitor; @@ -31,14 +25,6 @@ import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.util.Flags; -import java.util.ArrayList; -import java.util.List; - -import static io.ballerina.types.CellAtomicType.CellMutability.CELL_MUT_LIMITED; -import static io.ballerina.types.CellAtomicType.CellMutability.CELL_MUT_NONE; -import static io.ballerina.types.PredefinedType.NEVER; -import static io.ballerina.types.PredefinedType.VAL; - /** * {@code BRecordType} represents record type in Ballerina. * @@ -56,28 +42,16 @@ public class BRecordType extends BStructureType implements RecordType { public static final String READONLY = "readonly"; public boolean sealed; public BType restFieldType; + public Boolean isAnyData = null; public BRecordType mutableType; - private final Env env; - private MappingDefinition md = null; - - public BRecordType(Env env, BTypeSymbol tSymbol) { + public BRecordType(BTypeSymbol tSymbol) { super(TypeTags.RECORD, tSymbol); - this.env = env; } - public BRecordType(Env env, BTypeSymbol tSymbol, long flags) { + public BRecordType(BTypeSymbol tSymbol, long flags) { super(TypeTags.RECORD, tSymbol, flags); - this.env = env; - } - - /** - * It is required to reset {@link #md} when the type gets mutated. - * This method is used for that. e.g. When changing Flags.READONLY - */ - protected void restMd() { - md = null; } @Override @@ -121,102 +95,12 @@ public String toString() { } if (sealed) { sb.append(SPACE).append(CLOSE_RIGHT); - return !Symbols.isFlagOn(this.getFlags(), Flags.READONLY) ? sb.toString() : + return !Symbols.isFlagOn(this.flags, Flags.READONLY) ? sb.toString() : sb.toString().concat(" & readonly"); } sb.append(SPACE).append(restFieldType).append(REST).append(SEMI).append(SPACE).append(CLOSE_RIGHT); - return !Symbols.isFlagOn(this.getFlags(), Flags.READONLY) ? sb.toString() : - sb.toString().concat(" & readonly"); + return !Symbols.isFlagOn(this.flags, Flags.READONLY) ? sb.toString() : sb.toString().concat(" & readonly"); } return this.tsymbol.toString(); } - - private boolean hasTypeHoles() { - if (this.fields != null) { - for (BField member : this.fields.values()) { - if (member.type instanceof BNoType) { - return true; - } - } - } - - // Note: restFieldType will be null/BNoType for closed records - return false; - } - - /** - * When the type is mutated we need to reset the definition used for the semType. - */ - @Override - public void resetSemType() { - md = null; - } - - // If the member has a semtype component then it will be represented by that component otherwise with never. This - // means we depend on properly partitioning types to semtype components. Also, we need to ensure member types are - // "ready" when we call this - @Override - public SemType semType() { - if (md != null) { - return md.getSemType(env); - } - md = new MappingDefinition(); - if (hasTypeHoles()) { - return md.defineMappingTypeWrapped(env, List.of(), VAL); - } - - SemType restFieldSemType; - if (restFieldType == null || restFieldType instanceof BNoType || restFieldType.semType() == null) { - restFieldSemType = NEVER; - } else { - restFieldSemType = restFieldType.semType(); - } - - List semFields = new ArrayList<>(this.fields.size()); - for (BField field : this.fields.values()) { - boolean optional = Symbols.isOptional(field.symbol); - BType bType = field.type; - SemType ty = bType.semType(); - if (ty == null || NEVER.equals(ty)) { - if (!optional) { - // if there is a non-optional field with `never` type, it is not possible to create a value. - // Hence, the whole record type is considered as `never`. - md.setSemTypeToNever(); - return NEVER; - } - - if (Core.isNever(restFieldSemType)) { - // record { never x?; never...;} is equivalent to record { never... } - // ignore the field - continue; - } - } - Field semField = Field.from(field.name.value, ty, Symbols.isFlagOn(field.symbol.flags, Flags.READONLY), - optional); - semFields.add(semField); - } - - boolean isReadonly = Symbols.isFlagOn(getFlags(), Flags.READONLY); - CellAtomicType.CellMutability mut = isReadonly ? CELL_MUT_NONE : CELL_MUT_LIMITED; - return md.defineMappingTypeWrapped(env, semFields, restFieldSemType, mut); - } - - // This is to ensure call to isNullable won't call semType. In case this is a member of a recursive union otherwise - // this will have an invalid record type since parent union type call this while it is filling its members - @Override - public boolean isNullable() { - return false; - } - - @Override - public void setFlags(long flags) { - super.setFlags(flags); - restMd(); - } - - @Override - public void addFlags(long flags) { - super.addFlags(flags); - restMd(); - } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BRegexpType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BRegexpType.java index 16f005bc8d06..900216e6fef0 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BRegexpType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BRegexpType.java @@ -17,11 +17,10 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.PredefinedType; +import org.ballerinalang.model.Name; import org.ballerinalang.model.types.TypeKind; import org.wso2.ballerinalang.compiler.semantics.model.TypeVisitor; import org.wso2.ballerinalang.compiler.util.Names; -import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.util.Flags; /** @@ -31,8 +30,13 @@ */ public class BRegexpType extends BType { - public BRegexpType() { - super(TypeTags.REGEXP, null, Names.REGEXP_TYPE, Flags.READONLY, PredefinedType.REGEXP); + public BRegexpType(int tag, Name name) { + super(tag, null, name, Flags.READONLY); + } + + @Override + public boolean isNullable() { + return false; } @Override @@ -60,4 +64,12 @@ public String getQualifiedTypeName() { return Names.BALLERINA_ORG.value + Names.ORG_NAME_SEPARATOR.value + Names.LANG.value + Names.DOT.value + Names.REGEXP.value + Names.ALIAS_SEPARATOR + name; } + + public boolean isAnydata() { + return true; + } + + public boolean isPureType() { + return true; + } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BSequenceType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BSequenceType.java index 571887ad0c55..fee674386469 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BSequenceType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BSequenceType.java @@ -17,15 +17,8 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.Env; -import io.ballerina.types.SemType; -import io.ballerina.types.definition.ListDefinition; import org.wso2.ballerinalang.compiler.util.TypeTags; -import java.util.List; - -import static io.ballerina.types.CellAtomicType.CellMutability.CELL_MUT_LIMITED; - /** * Represents type for sequence variable. * @@ -33,25 +26,13 @@ */ public class BSequenceType extends BType { public BType elementType; - private final Env env; - - public BSequenceType(Env env, BType elementType) { + public BSequenceType(BType elementType) { super(TypeTags.SEQUENCE, null); this.elementType = elementType; - this.env = env; } @Override public String toString() { return "seq " + elementType; } - - public SemType semType() { - if (this.semType != null) { - return this.semType; - } - ListDefinition ld = new ListDefinition(); - this.semType = ld.defineListTypeWrapped(env, List.of(), 0, elementType.semType(), CELL_MUT_LIMITED); - return this.semType; - } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BStreamType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BStreamType.java index 5f218cf9a3d6..e71f6997b6f1 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BStreamType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BStreamType.java @@ -18,13 +18,8 @@ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.Env; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.definition.StreamDefinition; import org.ballerinalang.model.types.StreamType; import org.ballerinalang.model.types.Type; -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.util.TypeTags; @@ -34,19 +29,15 @@ * * @since 1.2.0 */ -public class BStreamType extends BType implements StreamType { +public class BStreamType extends BBuiltInRefType implements StreamType { public BType constraint; public BType completionType; - private final Env env; - private StreamDefinition d = null; - - public BStreamType(Env env, int tag, BType constraint, BType completionType, BTypeSymbol tsymbol) { + public BStreamType(int tag, BType constraint, BType completionType, BTypeSymbol tsymbol) { super(tag, tsymbol); this.constraint = constraint; - this.completionType = completionType != null ? completionType : BType.createNilType(); - this.env = env; + this.completionType = completionType != null ? completionType : new BNilType(); } @Override @@ -64,11 +55,6 @@ public R accept(BTypeVisitor visitor, T t) { return visitor.visit(this, t); } - @Override - public TypeKind getKind() { - return TypeKind.STREAM; - } - @Override public String toString() { if (constraint.tag == TypeTags.ANY) { @@ -83,26 +69,4 @@ public String toString() { public void accept(TypeVisitor visitor) { visitor.visit(this); } - - /** - * When the type is mutated we need to reset the definition used for the semType. - */ - @Override - public void resetSemType() { - d = null; - } - - @Override - public SemType semType() { - if (constraint == null || constraint instanceof BNoType) { - return PredefinedType.STREAM; - } - - if (d != null) { - return d.getSemType(env); - } - - d = new StreamDefinition(); - return d.define(env, constraint.semType(), completionType.semType()); - } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BStringSubType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BStringSubType.java index af7beacd9ec3..d63c962f96d9 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BStringSubType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BStringSubType.java @@ -17,11 +17,10 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.SemTypes; +import org.ballerinalang.model.Name; import org.ballerinalang.model.types.TypeKind; import org.wso2.ballerinalang.compiler.semantics.model.TypeVisitor; import org.wso2.ballerinalang.compiler.util.Names; -import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.util.Flags; /** @@ -31,40 +30,55 @@ */ public class BStringSubType extends BType { - public static final BStringSubType CHAR = new BStringSubType(); + public BStringSubType(int tag, Name name) { - private BStringSubType() { - super(TypeTags.CHAR_STRING, null, Names.CHAR, Flags.READONLY, SemTypes.CHAR); + super(tag, null, name, Flags.READONLY); } @Override public boolean isNullable() { + return false; } @Override public R accept(BTypeVisitor visitor, T t) { + return visitor.visit(this, t); } @Override public TypeKind getKind() { + return TypeKind.STRING; } @Override public void accept(TypeVisitor visitor) { + visitor.visit(this); } @Override public String toString() { + return Names.STRING.value + Names.ALIAS_SEPARATOR + name; } @Override public String getQualifiedTypeName() { + return Names.BALLERINA_ORG.value + Names.ORG_NAME_SEPARATOR.value + Names.LANG.value + Names.DOT.value + Names.STRING.value + Names.ALIAS_SEPARATOR + name; } + + public boolean isAnydata() { + + return true; + } + + public boolean isPureType() { + + return true; + } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BTableType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BTableType.java index f5bb090449b5..d4c3ce7fea6d 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BTableType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BTableType.java @@ -15,21 +15,15 @@ * specific language governing permissions and limitations * under the License. */ + package org.wso2.ballerinalang.compiler.semantics.model.types; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.Context; -import io.ballerina.types.Env; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypes; import org.ballerinalang.model.types.TableType; import org.ballerinalang.model.types.TypeKind; -import org.wso2.ballerinalang.compiler.semantics.analyzer.Types; 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.Symbols; -import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.util.Flags; import java.util.ArrayList; @@ -49,29 +43,21 @@ public class BTableType extends BType implements TableType { public Location constraintPos; public BTableType mutableType; - private final Env env; - public BTableType(Env env, BType constraint, BTypeSymbol tSymbol) { - super(TypeTags.TABLE, tSymbol); + public BTableType(int tag, BType constraint, BTypeSymbol tSymbol) { + super(tag, tSymbol); this.constraint = constraint; - this.env = env; } - public BTableType(Env env, BType constraint, BTypeSymbol tSymbol, long flags) { - super(TypeTags.TABLE, tSymbol, flags); + public BTableType(int tag, BType constraint, BTypeSymbol tSymbol, long flags) { + super(tag, tSymbol, flags); this.constraint = constraint; - this.env = env; } public BType getConstraint() { return this.constraint; } - public void setConstraint(BType constraint) { - this.constraint = constraint; - this.semType = null; - } - @Override public R accept(BTypeVisitor visitor, T t) { return visitor.visit(this, t); @@ -79,7 +65,7 @@ public R accept(BTypeVisitor visitor, T t) { @Override public String toString() { - boolean readonly = Symbols.isFlagOn(getFlags(), Flags.READONLY); + boolean readonly = Symbols.isFlagOn(flags, Flags.READONLY); if (constraint == null) { return readonly ? super.toString().concat(" & readonly") : super.toString(); } @@ -111,50 +97,4 @@ public TypeKind getKind() { public void accept(TypeVisitor visitor) { visitor.visit(this); } - - @Override - public SemType semType() { - if (this.semType != null) { - return this.semType; - } - - SemType s = semTypeInner(); - boolean readonly = Symbols.isFlagOn(this.getFlags(), Flags.READONLY); - this.semType = readonly ? SemTypes.intersect(PredefinedType.VAL_READONLY, s) : s; - return this.semType; - } - - private SemType semTypeInner() { - BType constraintType = Types.getReferredType(constraint); - if (constraintType.tag == TypeTags.TABLE || constraintType.tag == TypeTags.SEMANTIC_ERROR) { - // this is to handle negative table recursions. e.g. type T table - return PredefinedType.TABLE; - } else if (constraintType instanceof BIntersectionType intersectionType) { - for (BType memberType : intersectionType.getConstituentTypes()) { - if (Types.getReferredType(memberType).tag == TypeTags.TABLE) { - // Negative scenario - return PredefinedType.TABLE; - } - } - } - - SemType tableConstraint = constraintType instanceof BParameterizedType p ? p.paramValueType.semType() : - constraintType.semType(); - tableConstraint = SemTypes.intersect(tableConstraint, PredefinedType.MAPPING); - - Context cx = Context.from(env); // apis calling with 'cx' here are only accessing the env field internally - String[] fieldNames = fieldNameList.toArray(String[]::new); - if (!fieldNameList.isEmpty()) { - return SemTypes.tableContainingKeySpecifier(cx, tableConstraint, fieldNames); - } - - BType keyConstraintType = Types.getReferredType(keyTypeConstraint); - if (keyTypeConstraint != null && keyConstraintType.tag != TypeTags.NEVER && - keyTypeConstraint.tag != TypeTags.SEMANTIC_ERROR) { - SemType keyConstraint = keyTypeConstraint.semType(); - return SemTypes.tableContainingKeyConstraint(cx, tableConstraint, keyConstraint); - } - - return SemTypes.tableContaining(env, tableConstraint); - } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BTupleType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BTupleType.java index 54c93ad0f200..6b647c1c2052 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BTupleType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BTupleType.java @@ -16,10 +16,6 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.CellAtomicType; -import io.ballerina.types.Env; -import io.ballerina.types.SemType; -import io.ballerina.types.definition.ListDefinition; import org.ballerinalang.model.types.TupleType; import org.ballerinalang.model.types.TypeKind; import org.wso2.ballerinalang.compiler.semantics.model.TypeVisitor; @@ -30,14 +26,8 @@ import java.util.ArrayList; import java.util.List; -import java.util.Objects; import java.util.stream.Collectors; -import static io.ballerina.types.CellAtomicType.CellMutability.CELL_MUT_LIMITED; -import static io.ballerina.types.CellAtomicType.CellMutability.CELL_MUT_NONE; -import static io.ballerina.types.PredefinedType.NEVER; -import static io.ballerina.types.PredefinedType.VAL; - /** * {@code {@link BTupleType }} represents the tuple type. * @@ -47,71 +37,56 @@ public class BTupleType extends BType implements TupleType { private List members; private List memberTypes; public BType restType; + public Boolean isAnyData = null; public boolean resolvingToString = false; public boolean isCyclic = false; public BTupleType mutableType; - private final Env env; - private ListDefinition ld = null; - public BTupleType(Env env, List members) { + public BTupleType(List members) { super(TypeTags.TUPLE, null); this.members = members; - this.env = env; } - public BTupleType(Env env, BTypeSymbol tsymbol, List members) { + public BTupleType(BTypeSymbol tsymbol, List members) { super(TypeTags.TUPLE, tsymbol); this.members = members; - this.env = env; } - public BTupleType(Env env, BTypeSymbol tsymbol, List members, boolean isCyclic) { + public BTupleType(BTypeSymbol tsymbol, List members, boolean isCyclic) { super(TypeTags.TUPLE, tsymbol); this.members = members; this.isCyclic = isCyclic; - this.env = env; } - public BTupleType(Env env, BTypeSymbol tsymbol, List members, BType restType, long flags) { + public BTupleType(BTypeSymbol tsymbol, List members, BType restType, long flags) { super(TypeTags.TUPLE, tsymbol, flags); this.members = members; this.restType = restType; - this.env = env; } - public BTupleType(Env env, BTypeSymbol tsymbol, List members, BType restType, long flags, + public BTupleType(BTypeSymbol tsymbol, List members, BType restType, long flags, boolean isCyclic) { super(TypeTags.TUPLE, tsymbol, flags); this.members = members; this.restType = restType; this.isCyclic = isCyclic; - this.env = env; } - public BTupleType(Env env, BTypeSymbol tsymbol) { - this(env, tsymbol, true); + public BTupleType(BTypeSymbol tsymbol) { + this(tsymbol, true); } - private BTupleType(Env env, BTypeSymbol tsymbol, boolean readonly) { + private BTupleType(BTypeSymbol tsymbol, boolean readonly) { super(TypeTags.TUPLE, tsymbol); if (readonly) { - this.addFlags(Flags.READONLY); + this.flags |= Flags.READONLY; if (tsymbol != null) { this.tsymbol.flags |= Flags.READONLY; } } - this.env = env; - } - - /** - * It is required to reset {@link #ld} when the type gets mutated. - * This method is used for that. e.g. When changing Flags.READONLY - */ - protected void restLd() { - ld = null; } @Override @@ -157,13 +132,12 @@ public String toString() { + ((restType != null) ? (!members.isEmpty() ? "," : "") + restType.toString() + "...]" : "]"); this.resolvingToString = false; - return !Symbols.isFlagOn(getFlags(), Flags.READONLY) ? stringRep : stringRep.concat(" & readonly"); + return !Symbols.isFlagOn(flags, Flags.READONLY) ? stringRep : stringRep.concat(" & readonly"); } // In the case of a cyclic tuple, this aids in //adding resolved members to a previously defined empty tuple shell in main scope public boolean addMembers(BTupleMember member) { - ld = null; // Prevent cyclic types of same type ex: type Foo [int, Foo]; if (member.type instanceof BTupleType && ((BTupleType) member.type).isCyclic && member.type.getQualifiedTypeName().equals(this.getQualifiedTypeName())) { @@ -173,9 +147,8 @@ public boolean addMembers(BTupleMember member) { if (this.memberTypes != null) { this.memberTypes.add(member.type); } - if (Symbols.isFlagOn(this.getFlags(), Flags.READONLY) && - !Symbols.isFlagOn(member.type.getFlags(), Flags.READONLY)) { - this.setFlags(this.getFlags() ^ Flags.READONLY); + if (Symbols.isFlagOn(this.flags, Flags.READONLY) && !Symbols.isFlagOn(member.type.flags, Flags.READONLY)) { + this.flags ^= Flags.READONLY; } setCyclicFlag(member.type); return true; @@ -185,15 +158,13 @@ public boolean addMembers(BTupleMember member) { // adding rest type of resolved node to a previously defined // empty tuple shell in main scope public boolean addRestType(BType restType) { - ld = null; if (restType != null && restType instanceof BTupleType && ((BTupleType) restType).isCyclic && restType.getQualifiedTypeName().equals(this.getQualifiedTypeName()) && this.members.isEmpty()) { return false; } this.restType = restType; - if (Symbols.isFlagOn(this.getFlags(), Flags.READONLY) && - !Symbols.isFlagOn(restType.getFlags(), Flags.READONLY)) { - this.setFlags(this.getFlags() ^ Flags.READONLY); + if (Symbols.isFlagOn(this.flags, Flags.READONLY) && !Symbols.isFlagOn(restType.flags, Flags.READONLY)) { + this.flags ^= Flags.READONLY; } setCyclicFlag(restType); return true; @@ -203,7 +174,6 @@ public void setMembers(List members) { assert members.isEmpty(); this.memberTypes = null; this.members = members; - ld = null; } private void setCyclicFlag(BType type) { @@ -235,82 +205,4 @@ private void setCyclicFlag(BType type) { } } } - - // This is to ensure call to isNullable won't call semType. In case this is a member of a recursive union otherwise - // this will have an invalid list type since parent union type call this while it is filling its members - @Override - public boolean isNullable() { - return false; - } - - private boolean hasTypeHoles() { - if (members != null) { - for (BTupleMember member : members) { - if (member.type instanceof BNoType) { - return true; - } - } - } - if (restType != null) { - return restType instanceof BNoType; - } - return false; - } - - /** - * When the type is mutated we need to reset the definition used for the semType. - */ - @Override - public void resetSemType() { - ld = null; - } - - // If the member has a semtype component then it will be represented by that component otherwise with never. This - // means we depend on properly partitioning types to semtype components. Also, we need to ensure member types are - // "ready" when we call this - @Override - public SemType semType() { - if (ld != null) { - return ld.getSemType(env); - } - ld = new ListDefinition(); - if (hasTypeHoles()) { - return ld.defineListTypeWrapped(env, VAL); - } - boolean isReadonly = Symbols.isFlagOn(getFlags(), Flags.READONLY); - CellAtomicType.CellMutability mut = isReadonly ? CELL_MUT_NONE : CELL_MUT_LIMITED; - if (members == null) { - if (restType == null) { - throw new IllegalStateException("Both members and rest type can't be null"); - } - SemType restSemType = restType.semType(); - return ld.defineListTypeWrapped(env, List.of(), 0, Objects.requireNonNullElse(restSemType, NEVER), mut); - } - List memberSemTypes = new ArrayList<>(members.size()); - for (BTupleMember member : members) { - BType memberType = member.type; - SemType semType = memberType.semType(); - if (semType == null) { - semType = NEVER; - } - memberSemTypes.add(semType); - } - SemType restSemType = restType != null ? restType.semType() : NEVER; - if (restSemType == null) { - restSemType = NEVER; - } - return ld.defineListTypeWrapped(env, memberSemTypes, memberSemTypes.size(), restSemType, mut); - } - - @Override - public void setFlags(long flags) { - super.setFlags(flags); - restLd(); - } - - @Override - public void addFlags(long flags) { - super.addFlags(flags); - restLd(); - } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BType.java index 3704a586bb7b..a60272975151 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BType.java @@ -17,8 +17,6 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.Core; -import io.ballerina.types.SemType; import org.ballerinalang.model.Name; import org.ballerinalang.model.types.TypeKind; import org.ballerinalang.model.types.ValueType; @@ -53,52 +51,27 @@ public class BType implements ValueType { // sometimes we loose type param information down the line. which is a problem. // TODO: Refactor this after JBallerina 1.0. public Name name; - private long flags; - - protected SemType semType; + public long flags; public BType(int tag, BTypeSymbol tsymbol) { - this(tag, tsymbol, Names.EMPTY, 0, null); - } - - public BType(int tag, BTypeSymbol tsymbol, SemType semType) { - this(tag, tsymbol, Names.EMPTY, 0, semType); + this.tag = tag; + this.tsymbol = tsymbol; + this.name = Names.EMPTY; + this.flags = 0; } public BType(int tag, BTypeSymbol tsymbol, long flags) { - this(tag, tsymbol, Names.EMPTY, flags, null); + this.tag = tag; + this.tsymbol = tsymbol; + this.name = Names.EMPTY; + this.flags = flags; } public BType(int tag, BTypeSymbol tsymbol, Name name, long flags) { - this(tag, tsymbol, name, flags, null); - } - - public BType(int tag, BTypeSymbol tsymbol, long flags, SemType semType) { - this(tag, tsymbol, Names.EMPTY, flags, semType); - } - - public BType(int tag, BTypeSymbol tsymbol, Name name, long flags, SemType semType) { this.tag = tag; this.tsymbol = tsymbol; this.name = name; this.flags = flags; - this.semType = semType; - } - - public static BType createNilType() { - return new BNilType(); - } - - public static BType createNeverType() { - return new BNeverType(); - } - - public SemType semType() { - return semType; - } - - public void semType(SemType semtype) { - this.semType = semtype; } public BType getReturnType() { @@ -106,7 +79,7 @@ public BType getReturnType() { } public boolean isNullable() { - return Core.containsNil(semType()); + return false; } public R accept(BTypeVisitor visitor, T t) { @@ -146,25 +119,6 @@ public String getQualifiedTypeName() { return tsymbol.pkgID.toString() + ":" + tsymbol.name; } - public final long getFlags() { - return flags; - } - - public void setFlags(long flags) { - this.flags = flags; - } - - public void addFlags(long flags) { - this.flags |= flags; - this.resetSemType(); - } - - /** - * When the type is mutated we need to reset resolved semType. - */ - public void resetSemType() { - } - /** * A data holder to hold the type associated with an expression. */ diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BTypeReferenceType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BTypeReferenceType.java index 91edd117538c..4914628e9a6d 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BTypeReferenceType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BTypeReferenceType.java @@ -17,7 +17,7 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.SemType; +import org.ballerinalang.model.types.ReferenceType; import org.ballerinalang.model.types.TypeKind; import org.wso2.ballerinalang.compiler.semantics.model.TypeVisitor; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BTypeSymbol; @@ -27,10 +27,11 @@ /** * @since 2.0.0 */ -public class BTypeReferenceType extends BType { +public class BTypeReferenceType extends BType implements ReferenceType { public BType referredType; public final String definitionName; + private Boolean nilable = null; public BTypeReferenceType(BType referredType, BTypeSymbol tsymbol, long flags) { super(TYPEREFDESC, tsymbol, flags); @@ -38,9 +39,9 @@ public BTypeReferenceType(BType referredType, BTypeSymbol tsymbol, long flags) { this.definitionName = tsymbol.getName().getValue(); } - @Override - public SemType semType() { - return referredType.semType(); + public BTypeReferenceType(BType referredType, BTypeSymbol tsymbol, long flags, boolean nilable) { + this(referredType, tsymbol, flags); + this.nilable = nilable; } @Override @@ -63,4 +64,14 @@ public void accept(TypeVisitor visitor) { public TypeKind getKind() { return TypeKind.TYPEREFDESC; } + + @Override + public boolean isNullable() { + if (this.nilable != null) { + return this.nilable; + } + + this.nilable = this.referredType.isNullable(); + return this.nilable; + } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BTypeVisitor.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BTypeVisitor.java index ac742e46f36d..fa8d92c78151 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BTypeVisitor.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BTypeVisitor.java @@ -25,6 +25,8 @@ public interface BTypeVisitor { R visit(BType t, T s); + R visit(BBuiltInRefType t, T s); + R visit(BAnyType t, T s); R visit(BAnydataType t, T s); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BTypedescType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BTypedescType.java index 5c92251bfe7b..cdd883b5b4e5 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BTypedescType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BTypedescType.java @@ -17,12 +17,7 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.Env; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypes; import org.ballerinalang.model.types.ConstrainedType; -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.util.TypeTags; @@ -31,39 +26,31 @@ /** * @since 0.94 */ -public class BTypedescType extends BType implements ConstrainedType { +public class BTypedescType extends BBuiltInRefType implements ConstrainedType { public BType constraint; - private final Env env; - public BTypedescType(Env env, BType constraint, BTypeSymbol tsymbol) { + public BTypedescType(BType constraint, BTypeSymbol tsymbol) { + super(TypeTags.TYPEDESC, tsymbol, Flags.READONLY); this.constraint = constraint; - this.env = env; - } - - public BTypedescType(Env env, BType constraint, BTypeSymbol tsymbol, SemType semType) { - this(env, constraint, tsymbol); - this.semType = semType; } @Override public BType getConstraint() { + return constraint; } @Override public R accept(BTypeVisitor visitor, T t) { - return visitor.visit(this, t); - } - @Override - public TypeKind getKind() { - return TypeKind.TYPEDESC; + return visitor.visit(this, t); } @Override public String toString() { + if (constraint.tag == TypeTags.ANY) { return super.toString(); } @@ -73,20 +60,7 @@ public String toString() { @Override public void accept(TypeVisitor visitor) { - visitor.visit(this); - } - - @Override - public SemType semType() { - if (this.semType != null) { - return this.semType; - } - if (constraint == null || constraint instanceof BNoType) { - this.semType = PredefinedType.TYPEDESC; - } else { - this.semType = SemTypes.typedescContaining(env, constraint.semType()); - } - return this.semType; + visitor.visit(this); } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BUnionType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BUnionType.java index d414330d321b..b73167676809 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BUnionType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BUnionType.java @@ -17,10 +17,6 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.Env; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypes; import org.ballerinalang.model.types.TypeKind; import org.ballerinalang.model.types.UnionType; import org.wso2.ballerinalang.compiler.semantics.model.TypeVisitor; @@ -48,50 +44,59 @@ */ public class BUnionType extends BType implements UnionType { public boolean resolvingToString = false; + private boolean nullable; private String cachedToString; protected LinkedHashSet memberTypes; - + public Boolean isAnyData = null; + public Boolean isPureType = null; public boolean isCyclic = false; + private LinkedHashSet originalMemberTypes; private static final String INT_CLONEABLE = "__Cloneable"; private static final String CLONEABLE = "Cloneable"; private static final String CLONEABLE_TYPE = "CloneableType"; private static final Pattern pCloneable = Pattern.compile(INT_CLONEABLE); private static final Pattern pCloneableType = Pattern.compile(CLONEABLE_TYPE); - public final Env env; - public BUnionType(Env env, BTypeSymbol tsymbol, LinkedHashSet memberTypes, boolean readonly) { - this(env, tsymbol, memberTypes, memberTypes, readonly, false); + public BUnionType(BTypeSymbol tsymbol, LinkedHashSet memberTypes, boolean nullable, boolean readonly) { + this(tsymbol, memberTypes, memberTypes, nullable, readonly); } - private BUnionType(Env env, BTypeSymbol tsymbol, LinkedHashSet originalMemberTypes, - LinkedHashSet memberTypes, boolean readonly) { - this(env, tsymbol, originalMemberTypes, memberTypes, readonly, false); - } + private BUnionType(BTypeSymbol tsymbol, LinkedHashSet originalMemberTypes, LinkedHashSet memberTypes, + boolean nullable, boolean readonly) { + super(TypeTags.UNION, tsymbol); + + if (readonly) { + this.flags |= Flags.READONLY; - private BUnionType(Env env, BTypeSymbol tsymbol, LinkedHashSet memberTypes, - boolean readonly, boolean isCyclic) { - this(env, tsymbol, null, memberTypes, readonly, isCyclic); + if (tsymbol != null) { + this.tsymbol.flags |= Flags.READONLY; + } + } + + this.originalMemberTypes = originalMemberTypes; + this.memberTypes = memberTypes; + this.nullable = nullable; } - private BUnionType(Env env, BTypeSymbol tsymbol, LinkedHashSet originalMemberTypes, - LinkedHashSet memberTypes, boolean readonly, boolean isCyclic) { + private BUnionType(BTypeSymbol tsymbol, LinkedHashSet memberTypes, boolean nullable, boolean readonly, + boolean isCyclic) { super(TypeTags.UNION, tsymbol); if (readonly) { - this.addFlags(Flags.READONLY); + this.flags |= Flags.READONLY; if (tsymbol != null) { this.tsymbol.flags |= Flags.READONLY; } } - this.originalMemberTypes = originalMemberTypes; + this.originalMemberTypes = memberTypes; this.memberTypes = memberTypes; + this.nullable = nullable; this.isCyclic = isCyclic; - this.env = env; } @Override @@ -124,6 +129,11 @@ public void accept(TypeVisitor visitor) { visitor.visit(this); } + @Override + public boolean isNullable() { + return nullable; + } + @Override public R accept(BTypeVisitor visitor, T t) { return visitor.visit(this, t); @@ -140,35 +150,38 @@ public String toString() { return cachedToString; } + public void setNullable(boolean nullable) { + this.nullable = nullable; + } + /** * Creates an empty union for cyclic union types. * - * @param env The environment to be used to create the union type. * @param tsymbol Type symbol for the union. * @param types The types to be used to define the union. * @param isCyclic The cyclic indicator. * @return The created union type. */ - public static BUnionType create(Env env, BTypeSymbol tsymbol, LinkedHashSet types, boolean isCyclic) { + public static BUnionType create(BTypeSymbol tsymbol, LinkedHashSet types, boolean isCyclic) { LinkedHashSet memberTypes = new LinkedHashSet<>(types.size()); boolean isImmutable = true; - return new BUnionType(env, tsymbol, memberTypes, isImmutable, isCyclic); + boolean hasNilableType = false; + return new BUnionType(tsymbol, memberTypes, hasNilableType, isImmutable, isCyclic); } /** * Creates a union type using the types specified in the `types` set. The created union will not have union types in * its member types set. If the set contains the nil type, calling isNullable() will return true. * - * @param env The environment to be used to create the union type. * @param tsymbol Type symbol for the union. * @param types The types to be used to define the union. * @return The created union type. */ - public static BUnionType create(Env env, BTypeSymbol tsymbol, LinkedHashSet types) { + public static BUnionType create(BTypeSymbol tsymbol, LinkedHashSet types) { LinkedHashSet memberTypes = new LinkedHashSet<>(types.size()); if (types.isEmpty()) { - return new BUnionType(env, tsymbol, memberTypes, true); + return new BUnionType(tsymbol, memberTypes, false, true); } boolean isImmutable = true; @@ -177,32 +190,54 @@ public static BUnionType create(Env env, BTypeSymbol tsymbol, LinkedHashSet bTypes = new LinkedHashSet<>(memberTypes.size()); + for (BType t : memberTypes) { + if (t.tag != TypeTags.NIL) { + bTypes.add(t); + } + } + memberTypes = bTypes; + } + + for (BType memberType : memberTypes) { + if (memberType.isNullable()) { + return new BUnionType(tsymbol, types, memberTypes, true, isImmutable); + } + } + + return new BUnionType(tsymbol, types, memberTypes, false, isImmutable); } /** * Creates a union type using the provided types. If the set contains the nil type, calling isNullable() will return * true. * - * @param env The environment to be used to create the union type. * @param tsymbol Type symbol for the union. * @param types The types to be used to define the union. * @return The created union type. */ - public static BUnionType create(Env env, BTypeSymbol tsymbol, BType... types) { + public static BUnionType create(BTypeSymbol tsymbol, BType... types) { LinkedHashSet memberTypes = new LinkedHashSet<>(types.length); memberTypes.addAll(Arrays.asList(types)); - return create(env, tsymbol, memberTypes); + return create(tsymbol, memberTypes); } /** @@ -227,12 +262,13 @@ public void add(BType type) { this.memberTypes.add(type); } - if (Symbols.isFlagOn(this.getFlags(), Flags.READONLY) && !Symbols.isFlagOn(type.getFlags(), Flags.READONLY)) { - this.setFlags(this.getFlags() ^ Flags.READONLY); + if (Symbols.isFlagOn(this.flags, Flags.READONLY) && !Symbols.isFlagOn(type.flags, Flags.READONLY)) { + this.flags ^= Flags.READONLY; } setCyclicFlag(type); - this.semType = null; // reset cached sem-type if exists + + this.nullable = this.nullable || type.isNullable(); } private void setCyclicFlag(BType type) { @@ -283,20 +319,24 @@ public void remove(BType type) { } this.originalMemberTypes.remove(type); - if (Symbols.isFlagOn(this.getFlags(), Flags.READONLY)) { + if (type.isNullable()) { + this.nullable = false; + } + + if (Symbols.isFlagOn(this.flags, Flags.READONLY)) { return; } boolean isImmutable = true; for (BType memBType : this.memberTypes) { - if (!Symbols.isFlagOn(memBType.getFlags(), Flags.READONLY)) { + if (!Symbols.isFlagOn(memBType.flags, Flags.READONLY)) { isImmutable = false; break; } } if (isImmutable) { - this.addFlags(Flags.READONLY); + this.flags |= Flags.READONLY; } } @@ -311,28 +351,28 @@ public void mergeUnionType(BUnionType unionType) { for (BType member : unionType.getMemberTypes()) { if (member instanceof BArrayType arrayType) { if (getImpliedType(arrayType.eType) == unionType) { - BArrayType newArrayType = new BArrayType(env, this, arrayType.tsymbol, arrayType.getSize(), - arrayType.state, arrayType.getFlags()); + BArrayType newArrayType = new BArrayType(this, arrayType.tsymbol, arrayType.size, + arrayType.state, arrayType.flags); this.add(newArrayType); continue; } } else if (member instanceof BMapType mapType) { if (getImpliedType(mapType.constraint) == unionType) { - BMapType newMapType = new BMapType(env, mapType.tag, this, mapType.tsymbol, mapType.getFlags()); + BMapType newMapType = new BMapType(mapType.tag, this, mapType.tsymbol, mapType.flags); this.add(newMapType); continue; } } else if (member instanceof BTableType tableType) { if (getImpliedType(tableType.constraint) == unionType) { - BTableType newTableType = new BTableType(env, this, tableType.tsymbol, - tableType.getFlags()); + BTableType newTableType = new BTableType(tableType.tag, this, tableType.tsymbol, + tableType.flags); this.add(newTableType); continue; } else if (tableType.constraint instanceof BMapType mapType) { if (getImpliedType(mapType.constraint) == unionType) { - BMapType newMapType = new BMapType(env, mapType.tag, this, mapType.tsymbol, mapType.getFlags()); - BTableType newTableType = new BTableType(env, newMapType, tableType.tsymbol, - tableType.getFlags()); + BMapType newMapType = new BMapType(mapType.tag, this, mapType.tsymbol, mapType.flags); + BTableType newTableType = new BTableType(tableType.tag, newMapType, tableType.tsymbol, + tableType.flags); this.add(newTableType); continue; } @@ -405,7 +445,7 @@ private void computeStringRepresentation() { if (tsymbol != null && !tsymbol.getName().getValue().isEmpty()) { String typeName = tsymbol.getName().getValue(); String packageId = tsymbol.pkgID.toString(); - boolean isTypeParam = Symbols.isFlagOn(getFlags(), Flags.TYPE_PARAM); + boolean isTypeParam = Symbols.isFlagOn(flags, Flags.TYPE_PARAM); // improve readability of cyclic union types if (isCyclic && (pCloneable.matcher(typeName).matches() || (isTypeParam && pCloneableType.matcher(typeName).matches()))) { @@ -456,8 +496,8 @@ private void computeStringRepresentation() { String typeStr = numberOfNotNilTypes > 1 ? "(" + joiner + ")" : joiner.toString(); boolean hasNilType = uniqueTypes.size() > numberOfNotNilTypes; - cachedToString = (this.isNullable() && hasNilType && !hasNilableMember) ? (typeStr + Names.QUESTION_MARK.value) - : typeStr; + cachedToString = (nullable && hasNilType && !hasNilableMember) ? (typeStr + Names.QUESTION_MARK.value) : + typeStr; } private static boolean isNeverType(BType type) { @@ -475,27 +515,4 @@ private static boolean isNeverType(BType type) { } return false; } - - /** - * When the type is mutated we need to reset resolved semType. - */ - public void resetSemType() { - this.semType = null; - } - - @Override - public SemType semType() { - if (this.semType == null) { - this.semType = computeSemTypeFromMemberTypes(); - } - return this.semType; - } - - private SemType computeSemTypeFromMemberTypes() { - SemType t = PredefinedType.NEVER; - for (BType ty : this.memberTypes) { - t = SemTypes.union(t, ty.semType()); - } - return t; - } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BXMLSubType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BXMLSubType.java index c51c77304eec..eb62806d81ff 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BXMLSubType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BXMLSubType.java @@ -17,18 +17,11 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.Core; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypes; import org.ballerinalang.model.Name; import org.ballerinalang.model.types.SelectivelyImmutableReferenceType; import org.ballerinalang.model.types.TypeKind; +import org.wso2.ballerinalang.compiler.semantics.model.TypeVisitor; import org.wso2.ballerinalang.compiler.util.Names; -import org.wso2.ballerinalang.compiler.util.TypeTags; -import org.wso2.ballerinalang.util.Flags; - -import static org.wso2.ballerinalang.compiler.semantics.analyzer.Types.AND_READONLY_SUFFIX; /** * Represents Builtin Subtype of integer. @@ -36,53 +29,54 @@ * @since 1.2.0 */ public class BXMLSubType extends BType implements SelectivelyImmutableReferenceType { + public BXMLSubType(int tag, Name name) { - public static final BXMLSubType XML_ELEMENT = new BXMLSubType(TypeTags.XML_ELEMENT, Names.XML_ELEMENT, - SemTypes.XML_ELEMENT); - public static final BXMLSubType XML_PI = new BXMLSubType(TypeTags.XML_PI, Names.XML_PI, SemTypes.XML_PI); - public static final BXMLSubType XML_COMMENT = new BXMLSubType(TypeTags.XML_COMMENT, Names.XML_COMMENT, - SemTypes.XML_COMMENT); - public static final BXMLSubType XML_TEXT = new BXMLSubType(TypeTags.XML_TEXT, Names.XML_TEXT, Flags.READONLY, - SemTypes.XML_TEXT); - - private BXMLSubType(int tag, Name name, SemType semType) { - this(tag, name, 0, semType); + super(tag, null, name, 0); } - private BXMLSubType(int tag, Name name, long flags, SemType semType) { - super(tag, null, name, flags, semType); - } + public BXMLSubType(int tag, Name name, long flags) { - public static BXMLSubType newImmutableXMLSubType(BXMLSubType xmlSubType) { - return new BXMLSubType(xmlSubType.tag, - Names.fromString(xmlSubType.name.getValue().concat(AND_READONLY_SUFFIX)), - xmlSubType.getFlags() | Flags.READONLY, - Core.intersect(xmlSubType.semType, PredefinedType.VAL_READONLY)); + super(tag, null, name, flags); } @Override public boolean isNullable() { + return false; } @Override public R accept(BTypeVisitor visitor, T t) { + return visitor.visit(this, t); } @Override public TypeKind getKind() { + return TypeKind.XML; } + @Override + public void accept(TypeVisitor visitor) { + + visitor.visit(this); + } + @Override public String toString() { + return Names.XML.value + Names.ALIAS_SEPARATOR + name; } @Override public String getQualifiedTypeName() { + return Names.BALLERINA_ORG.value + Names.ORG_NAME_SEPARATOR.value + Names.LANG.value + Names.DOT.value + Names.XML.value + Names.ALIAS_SEPARATOR + name; } + + public boolean isAnydata() { + return true; + } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BXMLType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BXMLType.java index 602c52bb28d0..f86112006093 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BXMLType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BXMLType.java @@ -16,12 +16,7 @@ */ package org.wso2.ballerinalang.compiler.semantics.model.types; -import io.ballerina.types.Core; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypes; import org.ballerinalang.model.types.SelectivelyImmutableReferenceType; -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.Symbols; @@ -34,7 +29,7 @@ * * @since 0.961.0 */ -public class BXMLType extends BType implements SelectivelyImmutableReferenceType { +public class BXMLType extends BBuiltInRefType implements SelectivelyImmutableReferenceType { public BType constraint; public BXMLType mutableType; @@ -59,7 +54,7 @@ public String toString() { stringRep = Names.XML.value; } - return !Symbols.isFlagOn(getFlags(), Flags.READONLY) ? stringRep : stringRep.concat(" & readonly"); + return !Symbols.isFlagOn(flags, Flags.READONLY) ? stringRep : stringRep.concat(" & readonly"); } @Override @@ -67,42 +62,8 @@ public R accept(BTypeVisitor visitor, T t) { return visitor.visit(this, t); } - @Override - public TypeKind getKind() { - return TypeKind.XML; - } - @Override public void accept(TypeVisitor visitor) { visitor.visit(this); } - - @Override - public SemType semType() { - if (this.semType != null) { - return this.semType; - } - - SemType s; - if (constraint == null) { - s = PredefinedType.XML; - } else { - SemType contraintSemtype; - if (constraint instanceof BParameterizedType parameterizedType) { - contraintSemtype = parameterizedType.paramValueType.semType(); - } else { - contraintSemtype = constraint.semType(); - } - - if (contraintSemtype == null || !Core.isSubtypeSimple(contraintSemtype, PredefinedType.XML)) { - // we reach here for negative semantics - contraintSemtype = PredefinedType.NEVER; - } - s = SemTypes.xmlSequence(contraintSemtype); - } - - boolean readonly = Symbols.isFlagOn(this.getFlags(), Flags.READONLY); - this.semType = readonly ? SemTypes.intersect(PredefinedType.VAL_READONLY, s) : s; - return this.semType; - } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/SemNamedType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/SemNamedType.java deleted file mode 100644 index 7e7b7ed949e8..000000000000 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/SemNamedType.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.wso2.ballerinalang.compiler.semantics.model.types; - -import io.ballerina.types.SemType; - -import java.util.Optional; - -/** - * Represents a sem-type and its user-specified string representation. - * - * @param semType Sem-type representation of a type - * @param optName User-specified string representation for the type, if available - */ -public record SemNamedType(SemType semType, Optional optName) { -} diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangPackage.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangPackage.java index 36ce13aa0db5..2b53aabcaf12 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangPackage.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangPackage.java @@ -20,7 +20,6 @@ import io.ballerina.projects.internal.ModuleContextDataHolder; import io.ballerina.tools.diagnostics.Diagnostic; import io.ballerina.tools.diagnostics.DiagnosticSeverity; -import io.ballerina.types.Env; import org.ballerinalang.compiler.CompilerPhase; import org.ballerinalang.model.elements.Flag; import org.ballerinalang.model.elements.PackageID; @@ -93,9 +92,7 @@ public class BLangPackage extends BLangNode implements PackageNode { public ModuleContextDataHolder moduleContextDataHolder; - public final Env semtypeEnv; - - public BLangPackage(Env env) { + public BLangPackage() { this.compUnits = new ArrayList<>(); this.imports = new ArrayList<>(); this.xmlnsList = new ArrayList<>(); @@ -113,7 +110,6 @@ public BLangPackage(Env env) { this.testablePkgs = new ArrayList<>(); this.flagSet = EnumSet.noneOf(Flag.class); this.diagnostics = new TreeSet<>(new DiagnosticComparator()); - this.semtypeEnv = env; } @Override diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangTestablePackage.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangTestablePackage.java index 4a73e3143fe0..58196fac987d 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangTestablePackage.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangTestablePackage.java @@ -17,8 +17,6 @@ */ package org.wso2.ballerinalang.compiler.tree; -import io.ballerina.types.Env; - import java.util.HashMap; import java.util.Map; @@ -33,11 +31,6 @@ public class BLangTestablePackage extends BLangPackage { private final Map mockFunctionNamesMap = new HashMap<>(); private final Map isLegacyMockingMap = new HashMap<>(); - - public BLangTestablePackage(Env env) { - super(env); - } - public Map getMockFunctionNamesMap() { return mockFunctionNamesMap; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangTypeDefinition.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangTypeDefinition.java index ff3129519fad..d54361654d93 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangTypeDefinition.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangTypeDefinition.java @@ -18,7 +18,6 @@ package org.wso2.ballerinalang.compiler.tree; -import io.ballerina.types.SemType; import org.ballerinalang.model.elements.Flag; import org.ballerinalang.model.tree.AnnotationAttachmentNode; import org.ballerinalang.model.tree.IdentifierNode; @@ -58,10 +57,6 @@ public class BLangTypeDefinition extends BLangNode implements TypeDefinition { public int cycleDepth = -1; - // SemType Integration - public SemType semType; - public int semCycleDepth = -1; - public BLangTypeDefinition() { this.annAttachments = new ArrayList<>(); this.flagSet = EnumSet.noneOf(Flag.class); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangUnaryExpr.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangUnaryExpr.java index 4d182ae04c30..0b6dfa3c4bab 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangUnaryExpr.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangUnaryExpr.java @@ -41,6 +41,8 @@ public class BLangUnaryExpr extends BLangExpression implements UnaryExpressionNo // Semantic Data public BOperatorSymbol opSymbol; + public boolean isConstant; + @Override public BLangExpression getExpression() { return expr; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/types/BLangType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/types/BLangType.java index 50f3bdc78199..cd9eb532ddb9 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/types/BLangType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/types/BLangType.java @@ -17,7 +17,6 @@ */ package org.wso2.ballerinalang.compiler.tree.types; -import io.ballerina.types.Definition; import org.ballerinalang.model.elements.Flag; import org.ballerinalang.model.tree.types.TypeNode; import org.wso2.ballerinalang.compiler.tree.BLangNode; @@ -37,7 +36,6 @@ public abstract class BLangType extends BLangNode implements TypeNode { public boolean nullable; public boolean grouped; public Set flagSet = EnumSet.noneOf(Flag.class); - public Definition defn; @Override public boolean isNullable() { 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 fe11dda777dd..ea65959446a4 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 @@ -88,6 +88,8 @@ */ public final class ImmutableTypeCloner { + private static final String AND_READONLY_SUFFIX = " & readonly"; + private ImmutableTypeCloner() { } @@ -96,8 +98,8 @@ public static BType getEffectiveImmutableType(Location pos, Types types, SymbolTable symTable, BLangAnonymousModelHelper anonymousModelHelper, Names names) { return getImmutableIntersectionType(pos, types, type, env, env.enclPkg.packageID, env.scope.owner, - symTable, anonymousModelHelper, names, new HashSet<>(), - new HashSet<>()).effectiveType; + symTable, anonymousModelHelper, names, new HashSet<>(), + new HashSet<>()).effectiveType; } public static BType getEffectiveImmutableType(Location pos, Types types, @@ -105,8 +107,8 @@ public static BType getEffectiveImmutableType(Location pos, Types types, BSymbol owner, SymbolTable symTable, BLangAnonymousModelHelper anonymousModelHelper, Names names) { return getImmutableIntersectionType(pos, types, type, null, pkgId, owner, - symTable, anonymousModelHelper, names, new HashSet<>(), - new HashSet<>()).effectiveType; + symTable, anonymousModelHelper, names, new HashSet<>(), + new HashSet<>()).effectiveType; } public static BIntersectionType getImmutableIntersectionType(Location pos, Types types, @@ -167,7 +169,7 @@ public static BType getImmutableType(Location pos, Types types, BType type, Symb return symTable.semanticError; } - if (types.isInherentlyImmutableType(type) || Symbols.isFlagOn(type.getFlags(), Flags.READONLY)) { + if (types.isInherentlyImmutableType(type) || Symbols.isFlagOn(type.flags, Flags.READONLY)) { return type; } @@ -190,7 +192,7 @@ private static BIntersectionType getImmutableIntersectionType(Location pos, Set unresolvedTypes) { BType refType = Types.getReferredType(bType); SelectivelyImmutableReferenceType type = (SelectivelyImmutableReferenceType) refType; - if (refType.tag == TypeTags.INTERSECTION && Symbols.isFlagOn(refType.getFlags(), Flags.READONLY)) { + if (refType.tag == TypeTags.INTERSECTION && Symbols.isFlagOn(refType.flags, Flags.READONLY)) { return (BIntersectionType) refType; } @@ -217,7 +219,12 @@ private static BIntersectionType setImmutableType(Location pos, Types types, case TypeTags.XML_ELEMENT: case TypeTags.XML_PI: BXMLSubType origXmlSubType = (BXMLSubType) type; - BXMLSubType immutableXmlSubType = BXMLSubType.newImmutableXMLSubType(origXmlSubType); + + // TODO: 4/28/20 Check tsymbol + BXMLSubType immutableXmlSubType = + new BXMLSubType(origXmlSubType.tag, + Names.fromString(origXmlSubType.name.getValue().concat(AND_READONLY_SUFFIX)), + origXmlSubType.flags | Flags.READONLY); BIntersectionType immutableXmlSubTypeIntersectionType = createImmutableIntersectionType(pkgId, owner, originalType, immutableXmlSubType, symTable); @@ -249,7 +256,20 @@ private static BIntersectionType setImmutableType(Location pos, Types types, unresolvedTypes, (BTableType) type, originalType); case TypeTags.ANY: BAnyType origAnyType = (BAnyType) type; - BAnyType immutableAnyType = BAnyType.newImmutableBAnyType(); + + BTypeSymbol immutableAnyTSymbol = getReadonlyTSymbol(names, origAnyType.tsymbol, env, pkgId, owner); + + BAnyType immutableAnyType; + if (immutableAnyTSymbol != null) { + immutableAnyType = new BAnyType(origAnyType.tag, immutableAnyTSymbol, immutableAnyTSymbol.name, + origAnyType.flags | Flags.READONLY, origAnyType.isNullable()); + immutableAnyTSymbol.type = immutableAnyType; + } else { + immutableAnyType = new BAnyType(origAnyType.tag, null, + getImmutableTypeName(names, TypeKind.ANY.typeName()), + origAnyType.flags | Flags.READONLY, origAnyType.isNullable()); + } + BIntersectionType immutableAnyIntersectionType = createImmutableIntersectionType(pkgId, owner, originalType, immutableAnyType, @@ -274,14 +294,14 @@ private static BIntersectionType defineImmutableTableType(Location pos, Types ty Names names, Set unresolvedTypes, BTableType type, BType originalType) { - BTypeSymbol immutableTableTSymbol = getReadonlyTSymbol(type.tsymbol, env, pkgId, owner); + BTypeSymbol immutableTableTSymbol = getReadonlyTSymbol(names, type.tsymbol, env, pkgId, owner); Optional immutableType = Types.getImmutableType(symTable, pkgId, type); if (immutableType.isPresent()) { return immutableType.get(); } else { Types.addImmutableType(symTable, pkgId, type, createImmutableIntersectionType(pkgId, owner, - originalType, new BTableType(symTable.typeEnv(), null, immutableTableTSymbol, - type.getFlags() | Flags.READONLY), symTable)); + originalType, new BTableType(TypeTags.TABLE, null, immutableTableTSymbol, + type.flags | Flags.READONLY), symTable)); } BIntersectionType immutableTableType = Types.getImmutableType(symTable, pkgId, type).orElseThrow(); @@ -316,13 +336,13 @@ private static BIntersectionType defineImmutableXMLType(Location pos, Types type Names names, Set unresolvedTypes, BXMLType type, BType originalType) { - BTypeSymbol immutableXmlTSymbol = getReadonlyTSymbol(type.tsymbol, env, pkgId, owner); + BTypeSymbol immutableXmlTSymbol = getReadonlyTSymbol(names, type.tsymbol, env, pkgId, owner); Optional immutableType = Types.getImmutableType(symTable, pkgId, type); if (immutableType.isPresent()) { return immutableType.get(); } else { Types.addImmutableType(symTable, pkgId, type, createImmutableIntersectionType(pkgId, owner, - originalType, new BXMLType(null, immutableXmlTSymbol, type.getFlags() | Flags.READONLY), + originalType, new BXMLType(null, immutableXmlTSymbol, type.flags | Flags.READONLY), symTable)); } @@ -340,15 +360,14 @@ private static BIntersectionType defineImmutableArrayType(Location pos, Types ty Names names, Set unresolvedTypes, BArrayType type, BType originalType) { - BTypeSymbol immutableArrayTSymbol = getReadonlyTSymbol(type.tsymbol, env, pkgId, owner); + BTypeSymbol immutableArrayTSymbol = getReadonlyTSymbol(names, type.tsymbol, env, pkgId, owner); Optional immutableType = Types.getImmutableType(symTable, pkgId, type); if (immutableType.isPresent()) { return immutableType.get(); } else { Types.addImmutableType(symTable, pkgId, type, createImmutableIntersectionType(pkgId, owner, - originalType, - new BArrayType(symTable.typeEnv(), null, immutableArrayTSymbol, type.getSize(), type.state, - type.getFlags() | Flags.READONLY), symTable)); + originalType, new BArrayType(null, immutableArrayTSymbol, type.size, type.state, + type.flags | Flags.READONLY), symTable)); } BIntersectionType immutableArrayType = Types.getImmutableType(symTable, pkgId, type).orElseThrow(); @@ -365,14 +384,14 @@ private static BIntersectionType defineImmutableMapType(Location pos, Types type Names names, Set unresolvedTypes, BMapType type, BType originalType) { - BTypeSymbol immutableMapTSymbol = getReadonlyTSymbol(type.tsymbol, env, pkgId, owner); + BTypeSymbol immutableMapTSymbol = getReadonlyTSymbol(names, type.tsymbol, env, pkgId, owner); Optional immutableType = Types.getImmutableType(symTable, pkgId, type); if (immutableType.isPresent()) { return immutableType.get(); } else { Types.addImmutableType(symTable, pkgId, type, createImmutableIntersectionType(pkgId, owner, - originalType, new BMapType(symTable.typeEnv(), TypeTags.MAP, null, immutableMapTSymbol, - type.getFlags() | Flags.READONLY), symTable)); + originalType, new BMapType(TypeTags.MAP, null, immutableMapTSymbol, + type.flags | Flags.READONLY), symTable)); } BIntersectionType immutableMapType = Types.getImmutableType(symTable, pkgId, type).orElseThrow(); @@ -399,7 +418,7 @@ private static BIntersectionType defineImmutableTupleType(Location pos, Types ty return immutableType.get(); } else { Types.addImmutableType(symTable, pkgId, type, createImmutableIntersectionType(pkgId, owner, - originalType, new BTupleType(symTable.typeEnv(), origTupleTypeSymbol), symTable)); + originalType, new BTupleType(origTupleTypeSymbol), symTable)); } List immutableMemTypes = new ArrayList<>(origTupleMembers.size()); @@ -413,7 +432,7 @@ private static BIntersectionType defineImmutableTupleType(Location pos, Types ty Name origTupleTypeSymbolName = Names.EMPTY; if (!originalTypeName.isEmpty()) { origTupleTypeSymbolName = origTupleTypeSymbol.name.value.isEmpty() ? Names.EMPTY : - Types.getImmutableTypeName(getSymbolFQN(origTupleTypeSymbol)); + getImmutableTypeName(names, getSymbolFQN(origTupleTypeSymbol)); tupleEffectiveImmutableType.name = origTupleTypeSymbolName; } @@ -444,11 +463,11 @@ private static BIntersectionType defineImmutableTupleType(Location pos, Types ty BTypeSymbol immutableTupleTSymbol = getReadonlyTSymbol(origTupleTypeSymbol, env, pkgId, owner, origTupleTypeSymbolName); effectiveTypeFromType.tsymbol = immutableTupleTSymbol; - effectiveTypeFromType.addFlags(type.getFlags() | Flags.READONLY); + effectiveTypeFromType.flags |= (type.flags | Flags.READONLY); immutableTupleTSymbol.type = effectiveTypeFromType; } else { - effectiveTypeFromType.addFlags(type.getFlags() | Flags.READONLY); + effectiveTypeFromType.flags |= (type.flags | Flags.READONLY); } BType effectiveType = immutableTupleIntersectionType.effectiveType; @@ -463,7 +482,7 @@ private static BIntersectionType defineImmutableTupleType(Location pos, Types ty BLangTypeDefinition typeDefinition = TypeDefBuilderHelper.addTypeDefinition(effectiveType, effectiveType.tsymbol, tupleTypeNode, env); typeDefinition.pos = pos; - effectiveType.addFlags(Flags.EFFECTIVE_TYPE_DEF); + effectiveType.flags |= Flags.EFFECTIVE_TYPE_DEF; return immutableTupleIntersectionType; } @@ -564,11 +583,10 @@ private static BIntersectionType defineImmutableRecordType(Location pos, BRecord BTypeSymbol recordTypeSymbol = origRecordType.tsymbol; BRecordTypeSymbol recordSymbol = Symbols.createRecordSymbol(recordTypeSymbol.flags | Flags.READONLY, - Types.getImmutableTypeName(getSymbolFQN(recordTypeSymbol)), + getImmutableTypeName(names, getSymbolFQN(recordTypeSymbol)), pkgID, null, env.scope.owner, pos, VIRTUAL); - BInvokableType bInvokableType = - new BInvokableType(symTable.typeEnv(), List.of(), symTable.nilType, null); + 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, false, symTable.builtinPos, VIRTUAL); @@ -576,8 +594,7 @@ private static BIntersectionType defineImmutableRecordType(Location pos, BRecord recordSymbol.scope = new Scope(recordSymbol); - BRecordType immutableRecordType = new BRecordType(symTable.typeEnv(), recordSymbol, - origRecordType.getFlags() | Flags.READONLY); + BRecordType immutableRecordType = new BRecordType(recordSymbol, origRecordType.flags | Flags.READONLY); BIntersectionType immutableRecordIntersectionType = createImmutableIntersectionType(env, originalType, immutableRecordType, @@ -615,7 +632,7 @@ private static BIntersectionType defineImmutableObjectType(Location pos, flags &= ~Flags.CLASS; BObjectTypeSymbol objectSymbol = Symbols.createObjectSymbol(flags, - Types.getImmutableTypeName( + getImmutableTypeName(names, getSymbolFQN(origObjectTSymbol)), pkgID, null, env.scope.owner, pos, VIRTUAL); @@ -623,8 +640,7 @@ private static BIntersectionType defineImmutableObjectType(Location pos, defineObjectFunctions(objectSymbol, origObjectTSymbol, names, symTable); - BObjectType immutableObjectType = - new BObjectType(symTable.typeEnv(), objectSymbol, origObjectType.getFlags() | Flags.READONLY); + BObjectType immutableObjectType = new BObjectType(objectSymbol, origObjectType.flags | Flags.READONLY); immutableObjectType.typeIdSet = origObjectType.typeIdSet; BIntersectionType immutableObjectIntersectionType = createImmutableIntersectionType(env, originalType, @@ -668,8 +684,7 @@ public static void defineObjectFunctions(BObjectTypeSymbol immutableObjectSymbol Name funcName = Names.fromString(Symbols.getAttachedFuncSymbolName(immutableObjectSymbol.name.value, origFunc.funcName.value)); BInvokableSymbol immutableFuncSymbol = - ASTBuilderUtil.duplicateFunctionDeclarationSymbol(symTable.typeEnv(), origFunc.symbol, - immutableObjectSymbol, + ASTBuilderUtil.duplicateFunctionDeclarationSymbol(origFunc.symbol, immutableObjectSymbol, funcName, immutableObjectSymbol.pkgID, symTable.builtinPos, VIRTUAL); immutableFuncs.add(new BAttachedFunction(origFunc.funcName, immutableFuncSymbol, @@ -692,7 +707,7 @@ private static BIntersectionType defineImmutableUnionType(Location pos, Types ty if (immutableTypeOptional.isPresent()) { return immutableTypeOptional.get(); } else { - BUnionType immutableUnionType = BUnionType.create(symTable.typeEnv(), origUnionTypeSymbol); + BUnionType immutableUnionType = BUnionType.create(origUnionTypeSymbol); Types.addImmutableType(symTable, pkgId, type, createImmutableIntersectionType(pkgId, owner, originalType, immutableUnionType, symTable)); } @@ -747,23 +762,27 @@ private static BIntersectionType defineImmutableBuiltInUnionType(Location pos, T private static BAnydataType defineImmutableAnydataType(SymbolEnv env, PackageID pkgId, BSymbol owner, Names names, BAnydataType type) { - BTypeSymbol immutableAnydataTSymbol = getReadonlyTSymbol(type.tsymbol, env, pkgId, owner); + BTypeSymbol immutableAnydataTSymbol = getReadonlyTSymbol(names, type.tsymbol, env, pkgId, owner); if (immutableAnydataTSymbol != null) { - BAnydataType immutableAnydataType = BAnydataType.newImmutableBAnydataType(type, immutableAnydataTSymbol, - immutableAnydataTSymbol.name, + BAnydataType immutableAnydataType = + new BAnydataType(immutableAnydataTSymbol, + immutableAnydataTSymbol.name, type.flags | Flags.READONLY, type.isNullable()); immutableAnydataTSymbol.type = immutableAnydataType; return immutableAnydataType; } - return BAnydataType.newImmutableBAnydataType(type, null, - Types.getImmutableTypeName(TypeKind.ANYDATA.typeName()), type.isNullable()); + return new BAnydataType(null, + getImmutableTypeName(names, TypeKind.ANYDATA.typeName()), + type.flags | Flags.READONLY, type.isNullable()); } private static BJSONType defineImmutableJsonType(SymbolEnv env, PackageID pkgId, BSymbol owner, Names names, BJSONType type) { - BTypeSymbol immutableJsonTSymbol = getReadonlyTSymbol(type.tsymbol, env, pkgId, owner); - BJSONType immutableJsonType = BJSONType.newImmutableBJSONType(type, immutableJsonTSymbol, type.isNullable()); + BTypeSymbol immutableJsonTSymbol = getReadonlyTSymbol(names, type.tsymbol, env, pkgId, owner); + BJSONType immutableJsonType = new BJSONType(immutableJsonTSymbol, + type.isNullable(), + type.flags | Flags.READONLY); if (immutableJsonTSymbol != null) { immutableJsonTSymbol.type = immutableJsonType; } @@ -785,7 +804,7 @@ private static BIntersectionType handleImmutableUnionType(Location pos, Types ty String originalTypeName = origUnionTypeSymbol == null ? "" : origUnionTypeSymbol.name.getValue(); if (!originalTypeName.isEmpty()) { - unionEffectiveImmutableType.name = Types.getImmutableTypeName(getSymbolFQN(origUnionTypeSymbol)); + unionEffectiveImmutableType.name = getImmutableTypeName(names, getSymbolFQN(origUnionTypeSymbol)); } for (BType memberType : originalMemberList) { @@ -810,25 +829,25 @@ private static BIntersectionType handleImmutableUnionType(Location pos, Types ty BTypeSymbol immutableUnionTSymbol = getReadonlyTSymbol(origUnionTypeSymbol, env, pkgId, owner, origUnionTypeSymbol.name.value.isEmpty() ? Names.EMPTY : - Types.getImmutableTypeName(getSymbolFQN(origUnionTypeSymbol))); + getImmutableTypeName(names, getSymbolFQN(origUnionTypeSymbol))); immutableType.effectiveType.tsymbol = immutableUnionTSymbol; - immutableType.effectiveType.addFlags(type.getFlags() | Flags.READONLY); + immutableType.effectiveType.flags |= (type.flags | Flags.READONLY); immutableUnionTSymbol.type = immutableType.effectiveType; } else { - immutableType.effectiveType.addFlags(type.getFlags() | Flags.READONLY); + immutableType.effectiveType.flags |= (type.flags | Flags.READONLY); } return immutableType; } - private static BTypeSymbol getReadonlyTSymbol(BTypeSymbol originalTSymbol, SymbolEnv env, + private static BTypeSymbol getReadonlyTSymbol(Names names, BTypeSymbol originalTSymbol, SymbolEnv env, PackageID pkgId, BSymbol owner) { if (originalTSymbol == null) { return null; } - return getReadonlyTSymbol(originalTSymbol, env, pkgId, owner, getImmutableTypeName(originalTSymbol)); + return getReadonlyTSymbol(originalTSymbol, env, pkgId, owner, getImmutableTypeName(names, originalTSymbol)); } private static BTypeSymbol getReadonlyTSymbol(BTypeSymbol originalTSymbol, SymbolEnv env, PackageID pkgId, @@ -858,8 +877,16 @@ private static String getSymbolFQN(BTypeSymbol originalTSymbol) { getMajorVersion(pkgID.version.value) + ":" + originalTSymbol.name; } - private static Name getImmutableTypeName(BTypeSymbol originalTSymbol) { - return Types.getImmutableTypeName(originalTSymbol.name.getValue()); + private static Name getImmutableTypeName(Names names, BTypeSymbol originalTSymbol) { + return getImmutableTypeName(names, originalTSymbol.name.getValue()); + } + + private static Name getImmutableTypeName(Names names, String origName) { + if (origName.isEmpty()) { + return Names.EMPTY; + } + + return Names.fromString("(".concat(origName).concat(AND_READONLY_SUFFIX).concat(")")); } private static BIntersectionType createImmutableIntersectionType(SymbolEnv env, BType nonReadOnlyType, @@ -883,7 +910,7 @@ private static BIntersectionType createImmutableIntersectionType(PackageID pkgId }}; BIntersectionType intersectionType = new BIntersectionType(intersectionTypeSymbol, constituentTypes, - effectiveType, Flags.READONLY | effectiveType.getFlags()); + effectiveType, Flags.READONLY | effectiveType.flags); intersectionTypeSymbol.type = intersectionType; return intersectionType; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/Names.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/Names.java index fc540bdfa491..a57fdf0b7d68 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/Names.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/Names.java @@ -127,9 +127,7 @@ public class Names { public static final Name XML_COMMENT = new Name(STRING_XML_COMMENT); public static final Name XML_TEXT = new Name(STRING_XML_TEXT); public static final Name REGEXP_TYPE = new Name(STRING_REGEXP); - public static final Name TRUE = new Name("true"); - public static final Name FALSE = new Name("false"); - + // Names related to transactions. public static final Name TRANSACTION_PACKAGE = new Name("transactions"); public static final Name TRANSACTION_INFO_RECORD = new Name("Info"); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/TypeDefBuilderHelper.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/TypeDefBuilderHelper.java index 380455d75304..727bbc9e1cdb 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/TypeDefBuilderHelper.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/TypeDefBuilderHelper.java @@ -17,7 +17,6 @@ package org.wso2.ballerinalang.compiler.util; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.Env; import org.ballerinalang.model.TreeBuilder; import org.ballerinalang.model.elements.Flag; import org.ballerinalang.model.elements.MarkdownDocAttachment; @@ -143,12 +142,14 @@ public static BLangFunction createInitFunctionForStructureType(BSymbol symbol, Name suffix, SymbolTable symTable, BType type) { - return createInitFunctionForStructureType(symTable.typeEnv(), symbol, env, names, suffix, type, - symTable.nilType); + return createInitFunctionForStructureType(symbol, env, names, suffix, type, symTable.nilType); } - public static BLangFunction createInitFunctionForStructureType(Env typeEnv, BSymbol symbol, SymbolEnv env, - Names names, Name suffix, BType type, + public static BLangFunction createInitFunctionForStructureType(BSymbol symbol, + SymbolEnv env, + Names names, + Name suffix, + BType type, BType returnType) { String structTypeName = type.tsymbol.name.value; BLangFunction initFunction = ASTBuilderUtil.createInitFunctionWithNilReturn(null, structTypeName, suffix); @@ -164,7 +165,7 @@ public static BLangFunction createInitFunctionForStructureType(Env typeEnv, BSym initFunction.flagSet.add(Flag.ATTACHED); // Create the function type - initFunction.setBType(new BInvokableType(typeEnv, List.of(), returnType, null)); + initFunction.setBType(new BInvokableType(new ArrayList<>(), returnType, null)); // Create the function symbol Name funcSymbolName = Names.fromString(Symbols.getAttachedFuncSymbolName(structTypeName, suffix.value)); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/Unifier.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/Unifier.java index 1bb911853161..51225b103c49 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/Unifier.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/Unifier.java @@ -17,7 +17,6 @@ package org.wso2.ballerinalang.compiler.util; -import io.ballerina.types.Env; import org.ballerinalang.model.TreeBuilder; import org.ballerinalang.model.tree.NodeKind; import org.ballerinalang.model.types.TypeKind; @@ -32,6 +31,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BAnyType; import org.wso2.ballerinalang.compiler.semantics.model.types.BAnydataType; import org.wso2.ballerinalang.compiler.semantics.model.types.BArrayType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BBuiltInRefType; import org.wso2.ballerinalang.compiler.semantics.model.types.BErrorType; import org.wso2.ballerinalang.compiler.semantics.model.types.BFiniteType; import org.wso2.ballerinalang.compiler.semantics.model.types.BFutureType; @@ -89,16 +89,14 @@ public class Unifier implements BTypeVisitor { private SymbolEnv env; private Types types; private BLangDiagnosticLog dlog; - private Env typeEnv; - public BType build(Env typeEnv, BType originalType, BType expType, BLangInvocation invocation, Types types, + public BType build(BType originalType, BType expType, BLangInvocation invocation, Types types, SymbolTable symbolTable, BLangDiagnosticLog dlog) { this.isInvocation = invocation != null; if (this.isInvocation) { this.invocation = invocation; createParamMap(invocation); } - this.typeEnv = typeEnv; this.types = types; this.symbolTable = symbolTable; this.dlog = dlog; @@ -107,13 +105,12 @@ public BType build(Env typeEnv, BType originalType, BType expType, BLangInvocati return newType; } - public BType build(Env typeEnv, BType originalType) { - return build(typeEnv, originalType, null, null, null, null, null); + public BType build(BType originalType) { + return build(originalType, null, null, null, null, null); } - public void validate(Env typeEnv, BType returnType, BLangFunction function, SymbolTable symbolTable, SymbolEnv env, - Types types, BLangDiagnosticLog dlog) { - this.typeEnv = typeEnv; + public void validate(BType returnType, BLangFunction function, SymbolTable symbolTable, SymbolEnv env, Types types, + BLangDiagnosticLog dlog) { this.function = function; this.symbolTable = symbolTable; this.env = env; @@ -128,6 +125,11 @@ public BType visit(BType originalType, BType expType) { return originalType; } + @Override + public BType visit(BBuiltInRefType originalType, BType expType) { + return originalType; + } + @Override public BType visit(BAnyType originalType, BType expType) { return originalType; @@ -152,8 +154,8 @@ public BType visit(BMapType originalType, BType expType) { return symbolTable.semanticError; } - BMapType newMType = new BMapType(typeEnv, originalType.tag, newConstraint, null); - setFlags(newMType, originalType.getFlags()); + BMapType newMType = new BMapType(originalType.tag, newConstraint, null); + setFlags(newMType, originalType.flags); return newMType; } @@ -172,7 +174,7 @@ public BType visit(BXMLType originalType, BType expType) { } BXMLType newXMLType = new BXMLType(newConstraint, null); - setFlags(newXMLType, originalType.getFlags()); + setFlags(newXMLType, originalType.flags); return newXMLType; } @@ -195,9 +197,8 @@ public BType visit(BArrayType originalType, BType expType) { return symbolTable.semanticError; } - BArrayType newArrayType = new BArrayType(typeEnv, newElemType, null, originalType.getSize(), - originalType.state); - setFlags(newArrayType, originalType.getFlags()); + BArrayType newArrayType = new BArrayType(newElemType, null, originalType.size, originalType.state); + setFlags(newArrayType, originalType.flags); return newArrayType; } @@ -252,7 +253,7 @@ public BType visit(BTupleType originalType, BType expType) { BType member = tupleTypes.get(i); BType expMember = expTupleTypes.get(j); BType newMem = member.accept(this, expMember); - BVarSymbol varSymbol = new BVarSymbol(newMem.getFlags(), null, null, newMem, null, null, null); + BVarSymbol varSymbol = new BVarSymbol(newMem.flags, null, null, newMem, null, null, null); members.add(new BTupleMember(newMem, varSymbol)); if (isSemanticErrorInInvocation(newMem)) { @@ -283,9 +284,9 @@ public BType visit(BTupleType originalType, BType expType) { return expType != null ? expType : originalType; } - BTupleType type = new BTupleType(typeEnv, members); + BTupleType type = new BTupleType(null, members); type.restType = newRestType; - setFlags(type, originalType.getFlags()); + setFlags(type, originalType.flags); return type; } @@ -312,8 +313,8 @@ public BType visit(BStreamType originalType, BType expType) { return symbolTable.semanticError; } - BStreamType type = new BStreamType(typeEnv, originalType.tag, newConstraint, newError, null); - setFlags(type, originalType.getFlags()); + BStreamType type = new BStreamType(originalType.tag, newConstraint, newError, null); + setFlags(type, originalType.flags); return type; } @@ -339,19 +340,19 @@ public BType visit(BTableType originalType, BType expType) { return symbolTable.semanticError; } - BTableType newTableType = new BTableType(typeEnv, newConstraint, null); + BTableType newTableType = new BTableType(TypeTags.TABLE, newConstraint, null); newTableType.keyTypeConstraint = null; newTableType.fieldNameList = originalType.fieldNameList; newTableType.constraintPos = originalType.constraintPos; newTableType.isTypeInlineDefined = originalType.isTypeInlineDefined; newTableType.keyPos = originalType.keyPos; - setFlags(newTableType, originalType.getFlags()); + setFlags(newTableType, originalType.flags); return newTableType; } @Override public BType visit(BInvokableType originalType, BType expType) { - if (Symbols.isFlagOn(originalType.getFlags(), Flags.ANY_FUNCTION)) { + if (Symbols.isFlagOn(originalType.flags, Flags.ANY_FUNCTION)) { return originalType; } @@ -411,8 +412,8 @@ public BType visit(BInvokableType originalType, BType expType) { } } - BType type = new BInvokableType(typeEnv, paramTypes, newRestType, retType, null); - setFlags(type, originalType.getFlags()); + BType type = new BInvokableType(paramTypes, newRestType, retType, null); + setFlags(type, originalType.flags); return type; } @@ -449,7 +450,7 @@ public BType visit(BUnionType originalType, BType expType) { return symbolTable.semanticError; } - if (newMember == member && Symbols.isFlagOn(member.getFlags(), Flags.PARAMETERIZED)) { + if (newMember == member && Symbols.isFlagOn(member.flags, Flags.PARAMETERIZED)) { return expType; } } @@ -465,8 +466,8 @@ public BType visit(BUnionType originalType, BType expType) { return originalType; } - BUnionType type = BUnionType.create(originalType.env, null, newMemberTypes); - setFlags(type, originalType.getFlags()); + BUnionType type = BUnionType.create(null, newMemberTypes); + setFlags(type, originalType.flags); return type; } @@ -487,7 +488,7 @@ public BType visit(BIntersectionType originalType, BType expType) { BIntersectionType type = new BIntersectionType(null, (LinkedHashSet) originalType.getConstituentTypes(), newEffectiveType); - setFlags(type, originalType.getFlags()); + setFlags(type, originalType.flags); return originalType; } @@ -510,8 +511,9 @@ public BType visit(BFutureType originalType, BType expType) { return symbolTable.semanticError; } - BFutureType newFutureType = new BFutureType(typeEnv, newConstraint, null, originalType.workerDerivative); - setFlags(newFutureType, originalType.getFlags()); + BFutureType newFutureType = new BFutureType(originalType.tag, newConstraint, null, + originalType.workerDerivative); + setFlags(newFutureType, originalType.flags); return newFutureType; } @@ -535,8 +537,8 @@ public BType visit(BTypedescType originalType, BType expType) { return symbolTable.semanticError; } - BTypedescType newTypedescType = new BTypedescType(typeEnv, newConstraint, null); - setFlags(newTypedescType, originalType.getFlags()); + BTypedescType newTypedescType = new BTypedescType(newConstraint, null); + setFlags(newTypedescType, originalType.flags); return newTypedescType; } @@ -567,7 +569,7 @@ public BType visit(BParameterizedType originalType, BType expType) { // Log an error only if the user has not explicitly passed an argument. If the passed // argument is invalid, the type checker will log the error. dlog.error(invocation.pos, DiagnosticErrorCode.INCOMPATIBLE_TYPE_FOR_INFERRED_TYPEDESC_VALUE, - paramVarName, paramSymbolTypedescType, new BTypedescType(typeEnv, expType, null)); + paramVarName, paramSymbolTypedescType, new BTypedescType(expType, null)); return symbolTable.semanticError; } BType type = paramValueTypes.get(paramVarName); @@ -696,7 +698,7 @@ private BLangNamedArgsExpression createTypedescExprNamedArg(BType expType, Strin BLangTypedescExpr typedescExpr = (BLangTypedescExpr) TreeBuilder.createTypeAccessNode(); typedescExpr.pos = this.symbolTable.builtinPos; typedescExpr.resolvedType = expType; - typedescExpr.setBType(new BTypedescType(typeEnv, expType, null)); + typedescExpr.setBType(new BTypedescType(expType, null)); BLangNamedArgsExpression namedArgsExpression = (BLangNamedArgsExpression) TreeBuilder.createNamedArgNode(); BLangIdentifier identifierNode = (BLangIdentifier) TreeBuilder.createIdentifierNode(); @@ -827,7 +829,7 @@ private void populateParamMapFromTupleRestArg(List params, int curre } private void setFlags(BType type, long originalFlags) { - type.setFlags(originalFlags & (~Flags.PARAMETERIZED)); + type.flags = originalFlags & (~Flags.PARAMETERIZED); } private int getParamPosition(BVarSymbol sym) { @@ -958,7 +960,7 @@ private BType getMatchingTypeForInferrableType(BType originalType, BType expType BType referredOriginalType = Types.getImpliedType(originalType); if (referredOriginalType.tag == TypeTags.UNION) { for (BType memberType : ((BUnionType) referredOriginalType).getMemberTypes()) { - if (!Symbols.isFlagOn(memberType.getFlags(), Flags.PARAMETERIZED)) { + if (!Symbols.isFlagOn(memberType.flags, Flags.PARAMETERIZED)) { continue; } @@ -1049,7 +1051,7 @@ private boolean refersInferableParamName(List paramsWithInferredTypedesc } return refersInferableParamName(paramsWithInferredTypedescDefault, completionType, unresolvedTypes); case TypeTags.INVOKABLE: - if (Symbols.isFlagOn(type.getFlags(), Flags.ANY_FUNCTION)) { + if (Symbols.isFlagOn(type.flags, Flags.ANY_FUNCTION)) { return false; } BInvokableType invokableType = (BInvokableType) type; @@ -1134,7 +1136,7 @@ private List getParamsWithInferredTypedescDefault(List param // If the `expType` is `int|string|boolean` and the original type is `t|string` then the expected type for `t` // is `int|boolean`. private BType getExpectedTypeForInferredTypedescMember(BUnionType originalType, BType expType, BType member) { - if (expType == null || !this.isInvocation || !Symbols.isFlagOn(member.getFlags(), Flags.PARAMETERIZED)) { + if (expType == null || !this.isInvocation || !Symbols.isFlagOn(member.flags, Flags.PARAMETERIZED)) { return null; } @@ -1183,7 +1185,7 @@ private BType getExpectedTypeForInferredTypedescMember(BUnionType originalType, return expectedTypesSet.iterator().next(); } - return BUnionType.create(typeEnv, null, expectedTypesSet); + return BUnionType.create(null, expectedTypesSet); } private boolean isSameTypeOrError(BType newType, BType originalType) { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/programfile/ProgramFileConstants.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/programfile/ProgramFileConstants.java index da348731b9ec..e9ae324c0d33 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/programfile/ProgramFileConstants.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/programfile/ProgramFileConstants.java @@ -25,9 +25,9 @@ public final class ProgramFileConstants { public static final int MAGIC_NUMBER = 0xBA1DA4CE; public static final short VERSION_NUMBER = 50; - public static final int BIR_VERSION_NUMBER = 74; - public static final short MIN_SUPPORTED_VERSION = 74; - public static final short MAX_SUPPORTED_VERSION = 74; + public static final int BIR_VERSION_NUMBER = 73; + public static final short MIN_SUPPORTED_VERSION = 73; + public static final short MAX_SUPPORTED_VERSION = 73; // todo move this to a proper place public static final String[] SUPPORTED_PLATFORMS = {"java21", "java17", "java11"}; diff --git a/compiler/ballerina-lang/src/test/java/org/wso2/ballerinalang/compiler/diagnostic/BLangDiagnosticLogTest.java b/compiler/ballerina-lang/src/test/java/org/wso2/ballerinalang/compiler/diagnostic/BLangDiagnosticLogTest.java index e2159787bbb9..111755979b37 100644 --- a/compiler/ballerina-lang/src/test/java/org/wso2/ballerinalang/compiler/diagnostic/BLangDiagnosticLogTest.java +++ b/compiler/ballerina-lang/src/test/java/org/wso2/ballerinalang/compiler/diagnostic/BLangDiagnosticLogTest.java @@ -28,7 +28,6 @@ import io.ballerina.tools.diagnostics.DiagnosticInfo; import io.ballerina.tools.diagnostics.DiagnosticSeverity; import io.ballerina.tools.diagnostics.Location; -import io.ballerina.types.Env; import org.ballerinalang.compiler.CompilerOptionName; import org.ballerinalang.model.TreeBuilder; import org.ballerinalang.model.elements.PackageID; @@ -63,7 +62,7 @@ public void setup() { @Test public void testLogDiagnosticWithModuleDescriptor() { - BLangPackage pkgNode = (BLangPackage) TreeBuilder.createPackageNode(new Env()); + BLangPackage pkgNode = (BLangPackage) TreeBuilder.createPackageNode(); PackageID packageID = createPackageID("org.diagnostic.log", ".", "1.0.0"); PackageCache packageCache = PackageCache.getInstance(context); @@ -81,7 +80,7 @@ public void testLogDiagnosticWithModuleDescriptor() { @Test public void testLogDiagnosticWithPackageID() { - BLangPackage pkgNode = (BLangPackage) TreeBuilder.createPackageNode(new Env()); + BLangPackage pkgNode = (BLangPackage) TreeBuilder.createPackageNode(); PackageID packageID = createPackageID("org.diagnostic.log", ".", "1.0.0"); PackageCache packageCache = PackageCache.getInstance(context); diff --git a/docs/bir-spec/src/main/resources/kaitai/bir.ksy b/docs/bir-spec/src/main/resources/kaitai/bir.ksy index 4114e134e913..c4ac5bb12572 100644 --- a/docs/bir-spec/src/main/resources/kaitai/bir.ksy +++ b/docs/bir-spec/src/main/resources/kaitai/bir.ksy @@ -96,6 +96,8 @@ types: type: s4 - id: type_flag type: s8 + - id: type_special_flag + type: s4 - id: type_structure type: switch-on: type_tag @@ -120,238 +122,6 @@ types: instances: name_as_str: value: _root.constant_pool.constant_pool_entries[name_index].cp_info.as.value - sem_named_type: - seq: - - id: semtype - type: semtype_info - - id: optional_name - type: nullable_str_info - nullable_str_info: - seq: - - id: has_non_null_string - type: u1 - - id: str_cp_index - type: s4 - if: has_non_null_string == 1 - semtype_info: - seq: - - id: has_semtype - type: u1 - - id: semtype - type: semtype_internal - if: has_semtype == 1 - semtype_internal: - seq: - - id: is_uniform_type_bit_set - type: u1 - - id: uniform_type_bit_set - type: s4 - if: is_uniform_type_bit_set == 1 - - id: complex_semtype - type: semtype_complex - if: is_uniform_type_bit_set == 0 - semtype_complex: - seq: - - id: all_bit_set - type: s4 - - id: some_bit_set - type: s4 - - id: subtype_data_list_length - type: s1 - - id: proper_subtype_data - type: semtype_proper_subtype_data - repeat: expr - repeat-expr: subtype_data_list_length - semtype_proper_subtype_data: - seq: - - id: proper_subtype_data_kind - type: s1 - - id: bdd - type: semtype_bdd - if: proper_subtype_data_kind == 1 - - id: int_subtype - type: semtype_int_subtype - if: proper_subtype_data_kind == 2 - - id: boolean_subtype - type: semtype_boolean_subtype - if: proper_subtype_data_kind == 3 - - id: float_subtype - type: semtype_float_subtype - if: proper_subtype_data_kind == 4 - - id: decimal_subtype - type: semtype_decimal_subtype - if: proper_subtype_data_kind == 5 - - id: string_subtype - type: semtype_string_subtype - if: proper_subtype_data_kind == 6 - - id: xml_subtype - type: semtype_xml_subtype - if: proper_subtype_data_kind == 7 - semtype_bdd: - seq: - - id: is_bdd_node - type: u1 - - id: bdd_node - type: semtype_bdd_node - if: is_bdd_node == 1 - - id: bdd_all_or_nothing - type: u1 - if: is_bdd_node == 0 - semtype_bdd_node: - seq: - - id: is_rec_atom - type: u1 - - id: rec_atom_index - type: s4 - if: is_rec_atom == 1 - - id: target_kind - type: s4 - if: is_rec_atom == 1 and rec_atom_index > 1 - - id: type_atom - type: semtype_type_atom - if: is_rec_atom == 0 - - id: bdd_node_left - type: semtype_bdd - - id: bdd_node_middle - type: semtype_bdd - - id: bdd_node_right - type: semtype_bdd - semtype_type_atom: - seq: - - id: type_atom_index - type: s4 - - id: type_atom_kind - type: s1 - - id: mapping_atomic_type - type: semtype_mapping_atomic_type - if: type_atom_kind == 1 - - id: list_atomic_type - type: semtype_list_atomic_type - if: type_atom_kind == 2 - - id: function_atomic_type - type: semtype_function_atomic_type - if: type_atom_kind == 3 - - id: cell_atomic_type - type: semtype_cell_atomic_type - if: type_atom_kind == 4 - semtype_mapping_atomic_type: - seq: - - id: names_length - type: s4 - - id: names - type: s4 - repeat: expr - repeat-expr: names_length - - id: types_length - type: s4 - - id: types - type: semtype_info - repeat: expr - repeat-expr: types_length - - id: rest - type: semtype_info - semtype_list_atomic_type: - seq: - - id: initial_list_size - type: s4 - - id: initial - type: semtype_info - repeat: expr - repeat-expr: initial_list_size - - id: fixed_length - type: s4 - - id: rest - type: semtype_info - semtype_function_atomic_type: - seq: - - id: param_type - type: semtype_info - - id: ret_type - type: semtype_info - - id: qualifier_type - type: semtype_info - - id: is_generic - type: u1 - semtype_cell_atomic_type: - seq: - - id: ty - type: semtype_info - - id: mut - type: s1 - semtype_int_subtype: - seq: - - id: ranges_length - type: s4 - - id: x - type: semtype_range - repeat: expr - repeat-expr: ranges_length - semtype_range: - seq: - - id: min - type: s8 - - id: max - type: s8 - semtype_boolean_subtype: - seq: - - id: value - type: u1 - semtype_float_subtype: - seq: - - id: allowed - type: u1 - - id: values_length - type: s4 - - id: values - type: f8 - repeat: expr - repeat-expr: values_length - semtype_decimal_subtype: - seq: - - id: allowed - type: u1 - - id: values_length - type: s4 - - id: values - type: semtype_enumerable_decimal - repeat: expr - repeat-expr: values_length - semtype_enumerable_decimal: - seq: - - id: scale - type: s4 - - id: unscaled_value_bytes_length - type: s4 - - id: unscaled_value_bytes - size: unscaled_value_bytes_length - semtype_string_subtype: - seq: - - id: allowed - type: u1 - - id: values_length - type: s4 - - id: values - type: semtype_enumerable_string - repeat: expr - repeat-expr: values_length - - id: allowed1 - type: u1 - - id: values_length1 - type: s4 - - id: values1 - type: semtype_enumerable_string - repeat: expr - repeat-expr: values_length1 - semtype_enumerable_string: - seq: - - id: string_cp_index - type: s4 - semtype_xml_subtype: - seq: - - id: primitives - type: s4 - - id: sequence - type: semtype_bdd type_array: seq: - id: state @@ -400,10 +170,18 @@ types: type: s8 - id: value_space_size type: s4 - - id: value_space - type: sem_named_type + - id: finite_values + type: finite_value repeat: expr repeat-expr: value_space_size + finite_value: + seq: + - id : type_cp_index + type: s4 + - id: value_length + type: s4 + - id: value + size: value_length closure_symbol_body: seq: - id: name_cp_index diff --git a/docs/bir-spec/src/test/java/org/ballerinalang/birspec/BIRTestUtils.java b/docs/bir-spec/src/test/java/org/ballerinalang/birspec/BIRTestUtils.java index 23e97cefd4af..636262ee19af 100644 --- a/docs/bir-spec/src/test/java/org/ballerinalang/birspec/BIRTestUtils.java +++ b/docs/bir-spec/src/test/java/org/ballerinalang/birspec/BIRTestUtils.java @@ -649,7 +649,7 @@ private static void assertType(Bir.ConstantPoolEntry constantPoolEntry, BType ex Bir.TypeInfo typeInfo = ((Bir.ShapeCpInfo) constantPoolEntry.cpInfo()).shape(); Assert.assertEquals(typeInfo.typeTag().id(), expectedValue.tag); Assert.assertEquals(typeInfo.nameAsStr(), expectedValue.name.getValue()); - assertFlags(typeInfo.typeFlag(), expectedValue.getFlags()); + assertFlags(typeInfo.typeFlag(), expectedValue.flags); KaitaiStruct typeStructure = typeInfo.typeStructure(); if (typeStructure instanceof Bir.TypeObjectOrService objectOrService) { diff --git a/langlib/lang.__internal/src/main/java/org/ballerinalang/langlib/internal/SetNarrowType.java b/langlib/lang.__internal/src/main/java/org/ballerinalang/langlib/internal/SetNarrowType.java index 89c3b5342375..3518836a2fd0 100644 --- a/langlib/lang.__internal/src/main/java/org/ballerinalang/langlib/internal/SetNarrowType.java +++ b/langlib/lang.__internal/src/main/java/org/ballerinalang/langlib/internal/SetNarrowType.java @@ -29,7 +29,6 @@ import io.ballerina.runtime.api.values.BTypedesc; import java.util.HashMap; -import java.util.concurrent.atomic.AtomicLong; /** * Native implementation of lang.internal:setNarrowType(typedesc, (any|error)[]). @@ -38,19 +37,13 @@ */ public final class SetNarrowType { - private static final AtomicLong nextNarrowTypeId = new AtomicLong(0); - private SetNarrowType() { } - private static String getTypeName() { - return "narrowType" + nextNarrowTypeId.getAndIncrement(); - } - public static BMap setNarrowType(BTypedesc td, BMap value) { RecordType recordType = (RecordType) TypeUtils.getImpliedType(value.getType()); RecordType newRecordType = - TypeCreator.createRecordType(getTypeName(), recordType.getPackage(), recordType.getTypeFlags(), + TypeCreator.createRecordType("narrowType", recordType.getPackage(), recordType.getTypeFlags(), recordType.isSealed(), recordType.getTypeFlags()); newRecordType.setFields(new HashMap<>() {{ put("value", TypeCreator.createField(td.getDescribingType(), "value", diff --git a/langlib/lang.error/src/main/java/org/ballerinalang/langlib/error/StackTrace.java b/langlib/lang.error/src/main/java/org/ballerinalang/langlib/error/StackTrace.java index d0b49ffca282..33212bd6edd9 100644 --- a/langlib/lang.error/src/main/java/org/ballerinalang/langlib/error/StackTrace.java +++ b/langlib/lang.error/src/main/java/org/ballerinalang/langlib/error/StackTrace.java @@ -25,7 +25,6 @@ import io.ballerina.runtime.api.types.MethodType; import io.ballerina.runtime.api.types.ObjectType; import io.ballerina.runtime.api.types.PredefinedTypes; -import io.ballerina.runtime.api.types.RecordType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.utils.TypeUtils; @@ -48,8 +47,6 @@ import static io.ballerina.runtime.api.constants.RuntimeConstants.DOT; import static io.ballerina.runtime.api.constants.RuntimeConstants.EMPTY; import static io.ballerina.runtime.api.constants.RuntimeConstants.FILE_NAME_PERIOD_SEPARATOR; -import static io.ballerina.runtime.api.flags.SymbolFlags.OPTIONAL; -import static io.ballerina.runtime.api.flags.SymbolFlags.PUBLIC; import static io.ballerina.runtime.api.values.BError.CALL_STACK_ELEMENT; /** @@ -62,34 +59,21 @@ public final class StackTrace { private StackTrace() { } - private static final ObjectType CALLSTACK_TYPE = createCallStackType(); - public static BObject stackTrace(BError value) { - CallStack callStack = new CallStack(CALLSTACK_TYPE); - callStack.callStack = getCallStackArray(value.getStackTrace()); - callStack.callStack.freezeDirect(); - return callStack; - } - - private static ObjectType createCallStackType() { - Module module = new Module("ballerina", "lang.error", null); - RecordType callStackElementType = - TypeCreator.createRecordType("CallStackElement", module, 0, Map.of( - "callableName", TypeCreator.createField(PredefinedTypes.TYPE_STRING, "callableName", 0), - "moduleName", TypeCreator.createField(PredefinedTypes.TYPE_STRING, "moduleName", OPTIONAL), - "fileName", TypeCreator.createField(PredefinedTypes.TYPE_STRING, "fileName", 0), - "lineNumber", TypeCreator.createField(PredefinedTypes.TYPE_INT, "lineNumber", 0) - ), PredefinedTypes.TYPE_NEVER, false, 0); - ObjectType callStackObjType = TypeCreator - .createObjectType("CallStack", module, 0); + .createObjectType("CallStack", new Module("ballerina", "lang.error", null), 0); callStackObjType.setMethods(new MethodType[]{}); callStackObjType .setFields(Collections.singletonMap("callStack", - TypeCreator.createField(TypeCreator.createArrayType(callStackElementType), "callStack", - PUBLIC))); - return callStackObjType; + TypeCreator.createField(TypeCreator.createArrayType( + PredefinedTypes.TYPE_ANY), + null, 0))); + + CallStack callStack = new CallStack(callStackObjType); + callStack.callStack = getCallStackArray(value.getStackTrace()); + callStack.callStack.freezeDirect(); + return callStack; } private static BArray getCallStackArray(StackTraceElement[] stackTrace) { diff --git a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibMapTest.java b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibMapTest.java index 80db405f6fff..8258de8eca9c 100644 --- a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibMapTest.java +++ b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibMapTest.java @@ -20,12 +20,12 @@ import io.ballerina.runtime.api.creators.ValueCreator; import io.ballerina.runtime.api.types.ArrayType; -import io.ballerina.runtime.api.types.MapType; import io.ballerina.runtime.api.types.TypeTags; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.values.BArray; import io.ballerina.runtime.api.values.BMap; import io.ballerina.runtime.api.values.BString; +import io.ballerina.runtime.internal.types.BMapType; import org.ballerinalang.test.BCompileUtil; import org.ballerinalang.test.BRunUtil; import org.ballerinalang.test.CompileResult; @@ -86,7 +86,7 @@ public void testEntries() { assertEquals(getType(returns).getTag(), TypeTags.MAP_TAG); BMap map = (BMap) returns; - assertEquals(((MapType) map.getType()).getConstrainedType().getTag(), TypeTags.TUPLE_TAG); + assertEquals(((BMapType) map.getType()).getConstrainedType().getTag(), TypeTags.TUPLE_TAG); assertEquals(map.size(), 3); assertEquals(map.get(StringUtils.fromString("lk")).toString(), "[\"lk\",\"Sri Lanka\"]"); assertEquals(map.get(StringUtils.fromString("us")).toString(), "[\"us\",\"USA\"]"); @@ -148,7 +148,7 @@ public void testMap() { assertEquals(getType(returns).getTag(), TypeTags.MAP_TAG); BMap map = (BMap) returns; - assertEquals(((MapType) map.getType()).getConstrainedType().getTag(), TypeTags.FLOAT_TAG); + assertEquals(((BMapType) map.getType()).getConstrainedType().getTag(), TypeTags.FLOAT_TAG); assertEquals(map.size(), 3); assertEquals(map.get(StringUtils.fromString("1")), 5.5d); assertEquals(map.get(StringUtils.fromString("2")), 11.0d); @@ -167,7 +167,7 @@ public void testFilter() { assertEquals(getType(returns).getTag(), TypeTags.MAP_TAG); BMap map = (BMap) returns; - assertEquals(((MapType) map.getType()).getConstrainedType().getTag(), TypeTags.DECIMAL_TAG); + assertEquals(((BMapType) map.getType()).getConstrainedType().getTag(), TypeTags.DECIMAL_TAG); assertEquals(map.size(), 2); assertEquals(map.get(StringUtils.fromString("1")), ValueCreator.createDecimalValue("12.34")); assertEquals(map.get(StringUtils.fromString("4")), ValueCreator.createDecimalValue("21.2")); diff --git a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibRecordTest.java b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibRecordTest.java index 020049525a2c..72933bf4069d 100644 --- a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibRecordTest.java +++ b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibRecordTest.java @@ -18,7 +18,6 @@ package org.ballerinalang.langlib.test; -import io.ballerina.runtime.api.types.MapType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; import io.ballerina.runtime.api.utils.StringUtils; @@ -26,6 +25,7 @@ import io.ballerina.runtime.api.values.BMap; import io.ballerina.runtime.api.values.BString; import io.ballerina.runtime.internal.types.BArrayType; +import io.ballerina.runtime.internal.types.BMapType; import org.ballerinalang.test.BCompileUtil; import org.ballerinalang.test.BRunUtil; import org.ballerinalang.test.CompileResult; @@ -88,7 +88,7 @@ public void testEntries() { assertEquals(getType(returns).getTag(), TypeTags.MAP_TAG); BMap map = (BMap) returns; - assertEquals(((MapType) map.getType()).getConstrainedType().getTag(), TypeTags.TUPLE_TAG); + assertEquals(((BMapType) map.getType()).getConstrainedType().getTag(), TypeTags.TUPLE_TAG); assertEquals(map.size(), 2); assertEquals(map.get(StringUtils.fromString("name")).toString(), "[\"name\",\"John Doe\"]"); assertEquals(map.get(StringUtils.fromString("age")).toString(), "[\"age\",25]"); @@ -143,7 +143,7 @@ public void testMap() { assertEquals(getType(returns).getTag(), TypeTags.MAP_TAG); BMap map = (BMap) returns; - assertEquals(((MapType) map.getType()).getConstrainedType().getTag(), TypeTags.INT_TAG); + assertEquals(((BMapType) map.getType()).getConstrainedType().getTag(), TypeTags.INT_TAG); assertEquals(map.size(), 2); assertEquals(map.get(StringUtils.fromString("name")), 8L); assertEquals(map.get(StringUtils.fromString("age")), 25L); @@ -161,7 +161,7 @@ public void testFilter() { assertEquals(getType(returns).getTag(), TypeTags.MAP_TAG); BMap map = (BMap) returns; - assertEquals(((MapType) map.getType()).getConstrainedType().getTag(), TypeTags.INT_TAG); + assertEquals(((BMapType) map.getType()).getConstrainedType().getTag(), TypeTags.INT_TAG); assertEquals(map.size(), 2); assertEquals(map.get(StringUtils.fromString("physics")), 75L); assertEquals(map.get(StringUtils.fromString("ict")), 85L); diff --git a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibTableTest.java b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibTableTest.java index d7658103ba5b..89a71714b5d5 100644 --- a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibTableTest.java +++ b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibTableTest.java @@ -214,6 +214,9 @@ public void testImplementationrNegativeCases() { validateError(negativeResult, index++, "missing ellipsis token", 181, 38); validateError(negativeResult, index++, "missing open brace token", 181, 38); validateError(negativeResult, index++, "missing close brace token", 181, 39); + validateError(negativeResult, index++, "incompatible types: expected " + + "'table key', " + + "found 'table key(age)'", 182, 9); validateError(negativeResult, index++, "incompatible types: expected '[]', found 'int'", 182, 20); validateError(negativeResult, index++, "table with constraint of type map cannot have key specifier " + "or key type constraint", 188, 30); diff --git a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/TypeParamTest.java b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/TypeParamTest.java index 8b81da85bd3a..a7dcd6accd70 100644 --- a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/TypeParamTest.java +++ b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/TypeParamTest.java @@ -72,6 +72,9 @@ public void testTypeParamNegative() { BAssertUtil.validateError(result, err++, "incompatible types: expected '(int|string)', found 'float'", 131, 24); BAssertUtil.validateError(result, err++, "incompatible types: expected '[int,(int|float)][]', found '[int," + "(int|float|string)][]'", 137, 34); + BAssertUtil.validateError(result, err++, "incompatible types: expected 'function " + + "(ballerina/lang.table:0.0.0:MapType) returns (ballerina/lang.table:0.0.0:MapType1)', " + + "found 'function (other) returns (DataRow)'", 150, 31); BAssertUtil.validateError(result, err++, "unknown type 'dRecord'", 150, 40); BAssertUtil.validateError(result, err++, "missing identifier", 150, 47); BAssertUtil.validateError(result, err++, "unknown type 'x'", 158, 35); diff --git a/langlib/langlib-test/src/test/resources/test-src/valuelib_test.bal b/langlib/langlib-test/src/test/resources/test-src/valuelib_test.bal index c45a8c9515f2..d5b54572d3f2 100644 --- a/langlib/langlib-test/src/test/resources/test-src/valuelib_test.bal +++ b/langlib/langlib-test/src/test/resources/test-src/valuelib_test.bal @@ -883,7 +883,7 @@ function testCloneWithTypeDecimalToIntNegative() { var message = err.detail()["message"]; string messageString = message is error ? message.toString() : message.toString(); assert(err.message(), "{ballerina/lang.value}ConversionError"); - assert(messageString, "'decimal' value '9223372036854775807.5' cannot be converted to 'int'"); + assert(messageString, "'decimal' value cannot be converted to 'int'"); decimal[] a1 = [9223372036854775807.5, -9223372036854775807.6]; int[]|error a2e = a1.cloneWithType(IntArray); @@ -892,7 +892,7 @@ function testCloneWithTypeDecimalToIntNegative() { message = err.detail()["message"]; messageString = message is error ? message.toString() : message.toString(); assert(err.message(), "{ballerina/lang.value}ConversionError"); - assert(messageString, "'decimal' value '9223372036854775807.5' cannot be converted to 'int'"); + assert(messageString, "'decimal' value cannot be converted to 'int'"); } type IntSubtypeArray1 int:Signed32[]; @@ -1007,7 +1007,8 @@ function testCloneWithTypeIntArrayToUnionArray() { error err = u; var message = err.detail()["message"]; string messageString = message is error ? message.toString() : message.toString(); - string errMsg = "'int' value cannot be converted to '(byte|lang.int:Signed16)'"; + string errMsg = "'int[]' value cannot be converted to '(byte|lang.int:Signed16)[]': " + + "\n\t\tarray element '[2]' should be of type '(byte|lang.int:Signed16)', found '65000'"; assert(err.message(), "{ballerina/lang.value}ConversionError"); assert(messageString, errMsg); @@ -1738,7 +1739,9 @@ function testCloneWithTypeWithFiniteTypeArrayFromIntArrayNegative() { error err = a; var message = err.detail()["message"]; string messageString = message is error ? message.toString() : message.toString(); - string errMsg = "'int' value cannot be converted to 'IntTwoOrThree'"; + string errMsg = "'int[]' value cannot be converted to 'IntTwoOrThree[]': " + + "\n\t\tarray element '[0]' should be of type 'IntTwoOrThree', found '1'" + + "\n\t\tarray element '[3]' should be of type 'IntTwoOrThree', found '4'"; assert(messageString, errMsg); (IntTwoOrThree|IntThreeOrFour)[]|error c = x.cloneWithType(); @@ -1746,7 +1749,8 @@ function testCloneWithTypeWithFiniteTypeArrayFromIntArrayNegative() { err = c; message = err.detail()["message"]; messageString = message is error ? message.toString() : message.toString(); - errMsg = "'int' value cannot be converted to '(IntTwoOrThree|IntThreeOrFour)'"; + errMsg = "'int[]' value cannot be converted to '(IntTwoOrThree|IntThreeOrFour)[]': " + + "\n\t\tarray element '[0]' should be of type '(IntTwoOrThree|IntThreeOrFour)', found '1'"; assert(messageString, errMsg); int[] y = [3, 4]; @@ -4709,8 +4713,8 @@ function testEnsureTypeJsonToNestedRecordsWithErrors() { Factory|error val = trap clonedJsonVal.ensureType(Factory); error err = val; - string errorMsgPrefix = "incompatible types: 'map<(json & readonly)> & readonly' cannot be cast to 'Factory'"; - string errorMsg = errorMsgPrefix; + string errorMsgPrefix = "incompatible types: 'map<(json & readonly)> & readonly' cannot be cast to 'Factory': "; + string errorMsg = errorMsgPrefix + errorMsgContent; assert(checkpanic err.detail()["message"], errorMsg); assert(err.message(), "{ballerina}TypeCastError"); } diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/change-var-type/config/changeVarType5.json b/language-server/modules/langserver-core/src/test/resources/codeaction/change-var-type/config/changeVarType5.json index 39668a65d61d..03d1ad056bb0 100644 --- a/language-server/modules/langserver-core/src/test/resources/codeaction/change-var-type/config/changeVarType5.json +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/change-var-type/config/changeVarType5.json @@ -6,7 +6,7 @@ "source": "changeVarType2.bal", "expected": [ { - "title": "Change variable 'clientResponse' type to 'X|module1:ClientError'", + "title": "Change variable 'clientResponse' type to 'module1:Response|anydata'", "kind": "quickfix", "edits": [ { @@ -20,7 +20,7 @@ "character": 5 } }, - "newText": "X|module1:ClientError" + "newText": "module1:Response|anydata" } ] } diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/change-var-type/source/changeVarType2.bal b/language-server/modules/langserver-core/src/test/resources/codeaction/change-var-type/source/changeVarType2.bal index c4c2bc874f88..8ded0cd20a49 100644 --- a/language-server/modules/langserver-core/src/test/resources/codeaction/change-var-type/source/changeVarType2.bal +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/change-var-type/source/changeVarType2.bal @@ -2,7 +2,5 @@ import ballerina/module1; public function main() returns error? { module1:Client clientEP = check new("http://example.com"); - X clientResponse = clientEP->get("/"); + x clientResponse = clientEP->get("/"); } - -type X anydata; diff --git a/language-server/modules/langserver-core/src/test/resources/completion/action_node_context/config/client_remote_action_config1.json b/language-server/modules/langserver-core/src/test/resources/completion/action_node_context/config/client_remote_action_config1.json index c73e11972bbf..5cbef70cce12 100644 --- a/language-server/modules/langserver-core/src/test/resources/completion/action_node_context/config/client_remote_action_config1.json +++ b/language-server/modules/langserver-core/src/test/resources/completion/action_node_context/config/client_remote_action_config1.json @@ -461,10 +461,10 @@ { "label": "message = ...", "kind": "Snippet", - "detail": "message = ()", + "detail": "message = \"\"", "sortText": "AR", "filterText": "message", - "insertText": "message = ${1:()}", + "insertText": "message = ${1:\"\"}", "insertTextFormat": "Snippet" }, { diff --git a/language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/check_expression_ctx_config9.json b/language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/check_expression_ctx_config9.json index 534dc2fb67c0..26fd93151e15 100644 --- a/language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/check_expression_ctx_config9.json +++ b/language-server/modules/langserver-core/src/test/resources/completion/expression_context/config/check_expression_ctx_config9.json @@ -104,11 +104,11 @@ { "label": "next()", "kind": "Function", - "detail": "record {|string value;|}|stream:CompletionType", + "detail": "record {|string value; string...;|}|stream:CompletionType", "documentation": { "right": { "kind": "markdown", - "value": "**Package:** _ballerina/lang.stream:0.0.0_ \n \nReturns the next element in the stream wrapped in a record or () if the stream ends.\n\n```ballerina\nstream scores = [45, 60, 75, 30, 90].toStream();\nscores.next() ⇒ {\"value\":45}\n```\n \n \n \n**Return** `record {|string value;|}|stream:CompletionType` \n- If the stream has elements, return the element wrapped in a record with single field called `value`, \notherwise returns () \n \n" + "value": "**Package:** _ballerina/lang.stream:0.0.0_ \n \nReturns the next element in the stream wrapped in a record or () if the stream ends.\n\n```ballerina\nstream scores = [45, 60, 75, 30, 90].toStream();\nscores.next() ⇒ {\"value\":45}\n```\n \n \n \n**Return** `record {|string value; string...;|}|stream:CompletionType` \n- If the stream has elements, return the element wrapped in a record with single field called `value`, \notherwise returns () \n \n" } }, "sortText": "BD", @@ -119,11 +119,11 @@ { "label": "iterator()", "kind": "Function", - "detail": "object {public isolated function next() returns record {|string value;|}|stream:CompletionType;}", + "detail": "object {public isolated function next() returns record {|string value; string...;|}|stream:CompletionType;}", "documentation": { "right": { "kind": "markdown", - "value": "**Package:** _ballerina/lang.stream:0.0.0_ \n \nReturns an iterator over a stream.\n\n```ballerina\nstream scores = [45, 60, 75, 30, 90].toStream();\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = scores.iterator();\niterator.next() ⇒ {\"value\":45}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|string value;|}|stream:CompletionType;}` \n- a new iterator object that will iterate over the members of parameter `stm`. \n \n" + "value": "**Package:** _ballerina/lang.stream:0.0.0_ \n \nReturns an iterator over a stream.\n\n```ballerina\nstream scores = [45, 60, 75, 30, 90].toStream();\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = scores.iterator();\niterator.next() ⇒ {\"value\":45}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|string value; string...;|}|stream:CompletionType;}` \n- a new iterator object that will iterate over the members of parameter `stm`. \n \n" } }, "sortText": "CD", diff --git a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/field_access_ctx_config28.json b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/field_access_ctx_config28.json index cb47c62a119d..2f6a4dd238f6 100644 --- a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/field_access_ctx_config28.json +++ b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/field_access_ctx_config28.json @@ -440,11 +440,11 @@ { "label": "iterator()", "kind": "Function", - "detail": "object {public isolated function next() returns record {|NodeCredential value;|}?;}", + "detail": "object {public isolated function next() returns record {|NodeCredential value; NodeCredential...;|}?;}", "documentation": { "right": { "kind": "markdown", - "value": "**Package:** _ballerina/lang.array:0.0.0_ \n \nReturns an iterator over an array.\n\n```ballerina\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = [2, 4, 6, 8].iterator();\niterator.next() ⇒ {\"value\":2}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|NodeCredential value;|}?;}` \n- a new iterator object that will iterate over the members of parameter `arr` \n \n" + "value": "**Package:** _ballerina/lang.array:0.0.0_ \n \nReturns an iterator over an array.\n\n```ballerina\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = [2, 4, 6, 8].iterator();\niterator.next() ⇒ {\"value\":2}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|NodeCredential value; NodeCredential...;|}?;}` \n- a new iterator object that will iterate over the members of parameter `arr` \n \n" } }, "sortText": "CD", diff --git a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/field_access_ctx_config34.json b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/field_access_ctx_config34.json index 84151704e5ed..5d1e41158f3a 100644 --- a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/field_access_ctx_config34.json +++ b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/field_access_ctx_config34.json @@ -388,11 +388,11 @@ { "label": "iterator()", "kind": "Function", - "detail": "object {public isolated function next() returns record {|int value;|}?;}", + "detail": "object {public isolated function next() returns record {|int value; int...;|}?;}", "documentation": { "right": { "kind": "markdown", - "value": "**Package:** _ballerina/lang.array:0.0.0_ \n \nReturns an iterator over an array.\n\n```ballerina\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = [2, 4, 6, 8].iterator();\niterator.next() ⇒ {\"value\":2}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|int value;|}?;}` \n- a new iterator object that will iterate over the members of parameter `arr` \n \n" + "value": "**Package:** _ballerina/lang.array:0.0.0_ \n \nReturns an iterator over an array.\n\n```ballerina\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = [2, 4, 6, 8].iterator();\niterator.next() ⇒ {\"value\":2}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|int value; int...;|}?;}` \n- a new iterator object that will iterate over the members of parameter `arr` \n \n" } }, "sortText": "CD", diff --git a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/field_access_on_method_call_expression_config1.json b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/field_access_on_method_call_expression_config1.json index 537787e6a6bf..e76bcbf7cd4b 100644 --- a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/field_access_on_method_call_expression_config1.json +++ b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/field_access_on_method_call_expression_config1.json @@ -92,11 +92,11 @@ { "label": "iterator()", "kind": "Function", - "detail": "object {public isolated function next() returns record {|string value;|}?;}", + "detail": "object {public isolated function next() returns record {|string value; string...;|}?;}", "documentation": { "right": { "kind": "markdown", - "value": "**Package:** _ballerina/lang.array:0.0.0_ \n \nReturns an iterator over an array.\n\n```ballerina\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = [2, 4, 6, 8].iterator();\niterator.next() ⇒ {\"value\":2}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|string value;|}?;}` \n- a new iterator object that will iterate over the members of parameter `arr` \n \n" + "value": "**Package:** _ballerina/lang.array:0.0.0_ \n \nReturns an iterator over an array.\n\n```ballerina\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = [2, 4, 6, 8].iterator();\niterator.next() ⇒ {\"value\":2}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|string value; string...;|}?;}` \n- a new iterator object that will iterate over the members of parameter `arr` \n \n" } }, "sortText": "CD", diff --git a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/field_access_on_method_call_expression_config2.json b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/field_access_on_method_call_expression_config2.json index 0487bf79a0ad..a38463e10a92 100644 --- a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/field_access_on_method_call_expression_config2.json +++ b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/field_access_on_method_call_expression_config2.json @@ -92,11 +92,11 @@ { "label": "iterator()", "kind": "Function", - "detail": "object {public isolated function next() returns record {|string value;|}?;}", + "detail": "object {public isolated function next() returns record {|string value; string...;|}?;}", "documentation": { "right": { "kind": "markdown", - "value": "**Package:** _ballerina/lang.array:0.0.0_ \n \nReturns an iterator over an array.\n\n```ballerina\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = [2, 4, 6, 8].iterator();\niterator.next() ⇒ {\"value\":2}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|string value;|}?;}` \n- a new iterator object that will iterate over the members of parameter `arr` \n \n" + "value": "**Package:** _ballerina/lang.array:0.0.0_ \n \nReturns an iterator over an array.\n\n```ballerina\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = [2, 4, 6, 8].iterator();\niterator.next() ⇒ {\"value\":2}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|string value; string...;|}?;}` \n- a new iterator object that will iterate over the members of parameter `arr` \n \n" } }, "sortText": "CD", diff --git a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config10.json b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config10.json index 0a1279f71935..de3b672ee103 100644 --- a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config10.json +++ b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config10.json @@ -440,11 +440,11 @@ { "label": "iterator()", "kind": "Function", - "detail": "object {public isolated function next() returns record {|int[] value;|}?;}", + "detail": "object {public isolated function next() returns record {|int[] value; int[]...;|}?;}", "documentation": { "right": { "kind": "markdown", - "value": "**Package:** _ballerina/lang.array:0.0.0_ \n \nReturns an iterator over an array.\n\n```ballerina\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = [2, 4, 6, 8].iterator();\niterator.next() ⇒ {\"value\":2}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|int[] value;|}?;}` \n- a new iterator object that will iterate over the members of parameter `arr` \n \n" + "value": "**Package:** _ballerina/lang.array:0.0.0_ \n \nReturns an iterator over an array.\n\n```ballerina\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = [2, 4, 6, 8].iterator();\niterator.next() ⇒ {\"value\":2}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|int[] value; int[]...;|}?;}` \n- a new iterator object that will iterate over the members of parameter `arr` \n \n" } }, "sortText": "CD", diff --git a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config14.json b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config14.json index 53b204912b79..cbee75c2542a 100644 --- a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config14.json +++ b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config14.json @@ -440,11 +440,11 @@ { "label": "iterator()", "kind": "Function", - "detail": "object {public isolated function next() returns record {|[string, int] value;|}?;}", + "detail": "object {public isolated function next() returns record {|[string, int] value; [string, int]...;|}?;}", "documentation": { "right": { "kind": "markdown", - "value": "**Package:** _ballerina/lang.array:0.0.0_ \n \nReturns an iterator over an array.\n\n```ballerina\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = [2, 4, 6, 8].iterator();\niterator.next() ⇒ {\"value\":2}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|[string, int] value;|}?;}` \n- a new iterator object that will iterate over the members of parameter `arr` \n \n" + "value": "**Package:** _ballerina/lang.array:0.0.0_ \n \nReturns an iterator over an array.\n\n```ballerina\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = [2, 4, 6, 8].iterator();\niterator.next() ⇒ {\"value\":2}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|[string, int] value; [string, int]...;|}?;}` \n- a new iterator object that will iterate over the members of parameter `arr` \n \n" } }, "sortText": "CD", diff --git a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config17.json b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config17.json index 6e605eb203ee..f3d76f9d08ae 100644 --- a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config17.json +++ b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config17.json @@ -319,11 +319,11 @@ { "label": "iterator()", "kind": "Function", - "detail": "object {public isolated function next() returns record {|MyType value;|}?;}", + "detail": "object {public isolated function next() returns record {|MyType value; MyType...;|}?;}", "documentation": { "right": { "kind": "markdown", - "value": "**Package:** _ballerina/lang.map:0.0.0_ \n \nReturns an iterator over a map.\n\nThe iterator will iterate over the members of the map not the keys.\nThe function `entries` can be used to iterate over the keys and members together.\nThe function `keys` can be used to iterator over just the keys.\n\n```ballerina\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = {\"Carl\": 85, \"Bob\": 50, \"Max\": 60}.iterator();\niterator.next() ⇒ {\"value\":85}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|MyType value;|}?;}` \n- a new iterator object that will iterate over the members of parameter `m` \n \n" + "value": "**Package:** _ballerina/lang.map:0.0.0_ \n \nReturns an iterator over a map.\n\nThe iterator will iterate over the members of the map not the keys.\nThe function `entries` can be used to iterate over the keys and members together.\nThe function `keys` can be used to iterator over just the keys.\n\n```ballerina\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = {\"Carl\": 85, \"Bob\": 50, \"Max\": 60}.iterator();\niterator.next() ⇒ {\"value\":85}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|MyType value; MyType...;|}?;}` \n- a new iterator object that will iterate over the members of parameter `m` \n \n" } }, "sortText": "CD", diff --git a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config19.json b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config19.json index eeea3bb1ed93..72749ef9da30 100644 --- a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config19.json +++ b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config19.json @@ -130,11 +130,11 @@ { "label": "next()", "kind": "Function", - "detail": "record {|int value;|}|stream:CompletionType", + "detail": "record {|int value; int...;|}|stream:CompletionType", "documentation": { "right": { "kind": "markdown", - "value": "**Package:** _ballerina/lang.stream:0.0.0_ \n \nReturns the next element in the stream wrapped in a record or () if the stream ends.\n\n```ballerina\nstream scores = [45, 60, 75, 30, 90].toStream();\nscores.next() ⇒ {\"value\":45}\n```\n \n \n \n**Return** `record {|int value;|}|stream:CompletionType` \n- If the stream has elements, return the element wrapped in a record with single field called `value`, \notherwise returns () \n \n" + "value": "**Package:** _ballerina/lang.stream:0.0.0_ \n \nReturns the next element in the stream wrapped in a record or () if the stream ends.\n\n```ballerina\nstream scores = [45, 60, 75, 30, 90].toStream();\nscores.next() ⇒ {\"value\":45}\n```\n \n \n \n**Return** `record {|int value; int...;|}|stream:CompletionType` \n- If the stream has elements, return the element wrapped in a record with single field called `value`, \notherwise returns () \n \n" } }, "sortText": "CD", @@ -145,11 +145,11 @@ { "label": "iterator()", "kind": "Function", - "detail": "object {public isolated function next() returns record {|int value;|}|stream:CompletionType;}", + "detail": "object {public isolated function next() returns record {|int value; int...;|}|stream:CompletionType;}", "documentation": { "right": { "kind": "markdown", - "value": "**Package:** _ballerina/lang.stream:0.0.0_ \n \nReturns an iterator over a stream.\n\n```ballerina\nstream scores = [45, 60, 75, 30, 90].toStream();\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = scores.iterator();\niterator.next() ⇒ {\"value\":45}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|int value;|}|stream:CompletionType;}` \n- a new iterator object that will iterate over the members of parameter `stm`. \n \n" + "value": "**Package:** _ballerina/lang.stream:0.0.0_ \n \nReturns an iterator over a stream.\n\n```ballerina\nstream scores = [45, 60, 75, 30, 90].toStream();\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = scores.iterator();\niterator.next() ⇒ {\"value\":45}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|int value; int...;|}|stream:CompletionType;}` \n- a new iterator object that will iterate over the members of parameter `stm`. \n \n" } }, "sortText": "CD", diff --git a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config21.json b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config21.json index 578741b838de..8ae6b56a6b6d 100644 --- a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config21.json +++ b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config21.json @@ -440,11 +440,11 @@ { "label": "iterator()", "kind": "Function", - "detail": "object {public isolated function next() returns record {|int value;|}?;}", + "detail": "object {public isolated function next() returns record {|int value; int...;|}?;}", "documentation": { "right": { "kind": "markdown", - "value": "**Package:** _ballerina/lang.array:0.0.0_ \n \nReturns an iterator over an array.\n\n```ballerina\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = [2, 4, 6, 8].iterator();\niterator.next() ⇒ {\"value\":2}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|int value;|}?;}` \n- a new iterator object that will iterate over the members of parameter `arr` \n \n" + "value": "**Package:** _ballerina/lang.array:0.0.0_ \n \nReturns an iterator over an array.\n\n```ballerina\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = [2, 4, 6, 8].iterator();\niterator.next() ⇒ {\"value\":2}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|int value; int...;|}?;}` \n- a new iterator object that will iterate over the members of parameter `arr` \n \n" } }, "sortText": "CD", diff --git a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config22.json b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config22.json index d8a184ba6f03..42e5b4b6f1c9 100644 --- a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config22.json +++ b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config22.json @@ -402,11 +402,11 @@ { "label": "iterator()", "kind": "Function", - "detail": "object {public isolated function next() returns record {|Report value;|}?;}", + "detail": "object {public isolated function next() returns record {|Report value; Report...;|}?;}", "documentation": { "right": { "kind": "markdown", - "value": "**Package:** _ballerina/lang.array:0.0.0_ \n \nReturns an iterator over an array.\n\n```ballerina\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = [2, 4, 6, 8].iterator();\niterator.next() ⇒ {\"value\":2}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|Report value;|}?;}` \n- a new iterator object that will iterate over the members of parameter `arr` \n \n" + "value": "**Package:** _ballerina/lang.array:0.0.0_ \n \nReturns an iterator over an array.\n\n```ballerina\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = [2, 4, 6, 8].iterator();\niterator.next() ⇒ {\"value\":2}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|Report value; Report...;|}?;}` \n- a new iterator object that will iterate over the members of parameter `arr` \n \n" } }, "sortText": "CD", diff --git a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config25.json b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config25.json index e9f47f7bccf4..e2ee21237d3b 100644 --- a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config25.json +++ b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config25.json @@ -104,11 +104,11 @@ { "label": "next()", "kind": "Function", - "detail": "record {|int value;|}|stream:CompletionType", + "detail": "record {|int value; int...;|}|stream:CompletionType", "documentation": { "right": { "kind": "markdown", - "value": "**Package:** _ballerina/lang.stream:0.0.0_ \n \nReturns the next element in the stream wrapped in a record or () if the stream ends.\n\n```ballerina\nstream scores = [45, 60, 75, 30, 90].toStream();\nscores.next() ⇒ {\"value\":45}\n```\n \n \n \n**Return** `record {|int value;|}|stream:CompletionType` \n- If the stream has elements, return the element wrapped in a record with single field called `value`, \notherwise returns () \n \n" + "value": "**Package:** _ballerina/lang.stream:0.0.0_ \n \nReturns the next element in the stream wrapped in a record or () if the stream ends.\n\n```ballerina\nstream scores = [45, 60, 75, 30, 90].toStream();\nscores.next() ⇒ {\"value\":45}\n```\n \n \n \n**Return** `record {|int value; int...;|}|stream:CompletionType` \n- If the stream has elements, return the element wrapped in a record with single field called `value`, \notherwise returns () \n \n" } }, "sortText": "CD", @@ -119,11 +119,11 @@ { "label": "iterator()", "kind": "Function", - "detail": "object {public isolated function next() returns record {|int value;|}|stream:CompletionType;}", + "detail": "object {public isolated function next() returns record {|int value; int...;|}|stream:CompletionType;}", "documentation": { "right": { "kind": "markdown", - "value": "**Package:** _ballerina/lang.stream:0.0.0_ \n \nReturns an iterator over a stream.\n\n```ballerina\nstream scores = [45, 60, 75, 30, 90].toStream();\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = scores.iterator();\niterator.next() ⇒ {\"value\":45}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|int value;|}|stream:CompletionType;}` \n- a new iterator object that will iterate over the members of parameter `stm`. \n \n" + "value": "**Package:** _ballerina/lang.stream:0.0.0_ \n \nReturns an iterator over a stream.\n\n```ballerina\nstream scores = [45, 60, 75, 30, 90].toStream();\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = scores.iterator();\niterator.next() ⇒ {\"value\":45}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|int value; int...;|}|stream:CompletionType;}` \n- a new iterator object that will iterate over the members of parameter `stm`. \n \n" } }, "sortText": "CD", diff --git a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config9.json b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config9.json index a9143384f6ef..ce58c3e79a5b 100644 --- a/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config9.json +++ b/language-server/modules/langserver-core/src/test/resources/completion/field_access_expression_context/config/foreach_stmt_ctx_config9.json @@ -440,11 +440,11 @@ { "label": "iterator()", "kind": "Function", - "detail": "object {public isolated function next() returns record {|int value;|}?;}", + "detail": "object {public isolated function next() returns record {|int value; int...;|}?;}", "documentation": { "right": { "kind": "markdown", - "value": "**Package:** _ballerina/lang.array:0.0.0_ \n \nReturns an iterator over an array.\n\n```ballerina\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = [2, 4, 6, 8].iterator();\niterator.next() ⇒ {\"value\":2}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|int value;|}?;}` \n- a new iterator object that will iterate over the members of parameter `arr` \n \n" + "value": "**Package:** _ballerina/lang.array:0.0.0_ \n \nReturns an iterator over an array.\n\n```ballerina\nobject {\n public isolated function next() returns record {|int value;|}?;\n} iterator = [2, 4, 6, 8].iterator();\niterator.next() ⇒ {\"value\":2}\n```\n \n \n \n**Return** `object {public isolated function next() returns record {|int value; int...;|}?;}` \n- a new iterator object that will iterate over the members of parameter `arr` \n \n" } }, "sortText": "CD", diff --git a/language-server/modules/langserver-core/src/test/resources/completion/module_const_context/config/config7.json b/language-server/modules/langserver-core/src/test/resources/completion/module_const_context/config/config7.json index 85ac8710eae0..acabac212753 100644 --- a/language-server/modules/langserver-core/src/test/resources/completion/module_const_context/config/config7.json +++ b/language-server/modules/langserver-core/src/test/resources/completion/module_const_context/config/config7.json @@ -199,7 +199,7 @@ "value": "" } }, - "sortText": "AB", + "sortText": "F", "insertText": "varName", "insertTextFormat": "Snippet" }, diff --git a/misc/debug-adapter/modules/debug-adapter-runtime/src/main/java/org/ballerinalang/debugadapter/runtime/VariableUtils.java b/misc/debug-adapter/modules/debug-adapter-runtime/src/main/java/org/ballerinalang/debugadapter/runtime/VariableUtils.java index 870006970d2a..cd15f0d33bf5 100644 --- a/misc/debug-adapter/modules/debug-adapter-runtime/src/main/java/org/ballerinalang/debugadapter/runtime/VariableUtils.java +++ b/misc/debug-adapter/modules/debug-adapter-runtime/src/main/java/org/ballerinalang/debugadapter/runtime/VariableUtils.java @@ -18,7 +18,7 @@ package org.ballerinalang.debugadapter.runtime; -import io.ballerina.runtime.api.types.MapType; +import io.ballerina.runtime.internal.types.BMapType; import io.ballerina.runtime.internal.values.MapValueImpl; /** @@ -46,7 +46,7 @@ public static String getBMapType(Object mapObject) { return String.format(MAP_TYPE_TEMPLATE, UNKNOWN); } - if (!(mapValue.getType() instanceof MapType type)) { + if (!(mapValue.getType() instanceof BMapType type)) { return String.format(MAP_TYPE_TEMPLATE, UNKNOWN); } diff --git a/misc/ls-extensions/modules/bal-shell-service/src/test/java/io/ballerina/shell/service/test/getresult/QueryExpressionsTests.java b/misc/ls-extensions/modules/bal-shell-service/src/test/java/io/ballerina/shell/service/test/getresult/QueryExpressionsTests.java index 2bc9e648a35d..8a8530dfdc1a 100644 --- a/misc/ls-extensions/modules/bal-shell-service/src/test/java/io/ballerina/shell/service/test/getresult/QueryExpressionsTests.java +++ b/misc/ls-extensions/modules/bal-shell-service/src/test/java/io/ballerina/shell/service/test/getresult/QueryExpressionsTests.java @@ -38,8 +38,7 @@ public void testQueryExpressionsWithTables() throws ExecutionException, IOExcept runGetResultTest("query.tables.json"); } - // We no longer has fixed names for internal narrowed types so we can't hardcode them - @Test(description = "Test for querying with streams", enabled = false) + @Test(description = "Test for querying with streams") public void testQueryExpressionsWithStreams() throws ExecutionException, IOException, InterruptedException { runGetResultTest("query.streams.json"); } diff --git a/misc/ls-extensions/modules/bal-shell-service/src/test/resources/testcases/getResult/functional.programming.json b/misc/ls-extensions/modules/bal-shell-service/src/test/resources/testcases/getResult/functional.programming.json index ba9053506774..b09f41f282c9 100644 --- a/misc/ls-extensions/modules/bal-shell-service/src/test/resources/testcases/getResult/functional.programming.json +++ b/misc/ls-extensions/modules/bal-shell-service/src/test/resources/testcases/getResult/functional.programming.json @@ -39,9 +39,9 @@ "source": "f", "result": { "shellValue": { - "value": "function isolated function (int) returns (boolean)", + "value": "function IntFilter", "mimeType":"plain/text", - "type":"isolated function (int) returns (boolean)" + "type":"IntFilter" }, "errors":[], "diagnostics":[], diff --git a/semtypes/build.gradle b/semtypes/build.gradle index 22f85a25bf86..b9b3488eafd8 100644 --- a/semtypes/build.gradle +++ b/semtypes/build.gradle @@ -7,9 +7,6 @@ dependencies { } test { - // Add additional system property to distinguish tests requiring all basic types - systemProperty "ballerina.semtype.all.types.test", "true" - useTestNG() { suites 'src/test/resources/testng.xml' } diff --git a/semtypes/spotbugs-exclude.xml b/semtypes/spotbugs-exclude.xml index 599e9236ea20..97c14919f38e 100644 --- a/semtypes/spotbugs-exclude.xml +++ b/semtypes/spotbugs-exclude.xml @@ -21,83 +21,32 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - + + - - + + + + + + + + + + + - - - - - - - - - - - - - + + + - - - - - diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/SubTypeData.java b/semtypes/src/main/java/io/ballerina/semtype/Atom.java similarity index 67% rename from bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/SubTypeData.java rename to semtypes/src/main/java/io/ballerina/semtype/Atom.java index a418583d10af..1e9461723580 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/SubTypeData.java +++ b/semtypes/src/main/java/io/ballerina/semtype/Atom.java @@ -1,7 +1,7 @@ /* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * - * WSO2 LLC. licenses this file to you under the Apache License, + * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at @@ -15,14 +15,12 @@ * specific language governing permissions and limitations * under the License. */ - -package io.ballerina.runtime.internal.types.semtype; +package io.ballerina.semtype; /** - * Marker interface for SubTypeData. + * Represent the BDD atom. * - * @since 2201.11.0 + * @since 2.0.0 */ -public interface SubTypeData { - +public interface Atom { } diff --git a/semtypes/src/main/java/io/ballerina/types/AtomicType.java b/semtypes/src/main/java/io/ballerina/semtype/AtomicType.java similarity index 68% rename from semtypes/src/main/java/io/ballerina/types/AtomicType.java rename to semtypes/src/main/java/io/ballerina/semtype/AtomicType.java index 7de1e82a3867..3eb7f7377e11 100644 --- a/semtypes/src/main/java/io/ballerina/types/AtomicType.java +++ b/semtypes/src/main/java/io/ballerina/semtype/AtomicType.java @@ -1,7 +1,7 @@ /* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * - * WSO2 LLC. licenses this file to you under the Apache License, + * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at @@ -11,18 +11,16 @@ * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the + * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ -package io.ballerina.types; +package io.ballerina.semtype; /** * Represent AtomicType. * - * @since 2201.8.0 + * @since 2.0.0 */ public interface AtomicType { - - Atom.Kind atomKind(); } diff --git a/semtypes/src/main/java/io/ballerina/types/Bdd.java b/semtypes/src/main/java/io/ballerina/semtype/Bdd.java similarity index 69% rename from semtypes/src/main/java/io/ballerina/types/Bdd.java rename to semtypes/src/main/java/io/ballerina/semtype/Bdd.java index a51aa98545b7..351df65a953b 100644 --- a/semtypes/src/main/java/io/ballerina/types/Bdd.java +++ b/semtypes/src/main/java/io/ballerina/semtype/Bdd.java @@ -1,7 +1,7 @@ /* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * - * WSO2 LLC. licenses this file to you under the Apache License, + * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at @@ -11,16 +11,16 @@ * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the + * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ -package io.ballerina.types; +package io.ballerina.semtype; /** * Represent BDD node. * - * @since 2201.8.0 + * @since 2.0.0 */ public interface Bdd extends ProperSubtypeData { } diff --git a/semtypes/src/main/java/io/ballerina/semtype/BddMemo.java b/semtypes/src/main/java/io/ballerina/semtype/BddMemo.java new file mode 100644 index 000000000000..993f1670a76b --- /dev/null +++ b/semtypes/src/main/java/io/ballerina/semtype/BddMemo.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.semtype; + +/** + * Represent BddMomo type used for memoization. + * + * @since 2.0.0 + */ +public class BddMemo { + Bdd bddNode; + MemoStatus isEmpty; + + enum MemoStatus { + NOT_SET, TRUE, FALSE + } +} diff --git a/semtypes/src/main/java/io/ballerina/types/CommonBasicTypeOps.java b/semtypes/src/main/java/io/ballerina/semtype/CommonUniformTypeOps.java similarity index 72% rename from semtypes/src/main/java/io/ballerina/types/CommonBasicTypeOps.java rename to semtypes/src/main/java/io/ballerina/semtype/CommonUniformTypeOps.java index 2739e376f5eb..bc7cd3067b89 100644 --- a/semtypes/src/main/java/io/ballerina/types/CommonBasicTypeOps.java +++ b/semtypes/src/main/java/io/ballerina/semtype/CommonUniformTypeOps.java @@ -1,7 +1,7 @@ /* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * - * WSO2 LLC. licenses this file to you under the Apache License, + * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at @@ -11,18 +11,18 @@ * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the + * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ -package io.ballerina.types; +package io.ballerina.semtype; /** * Operations common to most of the subtypes. * - * @since 2201.8.0 + * @since 2.0.0 */ -public interface CommonBasicTypeOps { +public interface CommonUniformTypeOps { SubtypeData union(SubtypeData t1, SubtypeData t2); SubtypeData intersect(SubtypeData t1, SubtypeData t2); SubtypeData diff(SubtypeData t1, SubtypeData t2); diff --git a/semtypes/src/main/java/io/ballerina/semtype/ComplexSemType.java b/semtypes/src/main/java/io/ballerina/semtype/ComplexSemType.java new file mode 100644 index 000000000000..09b191eb7c35 --- /dev/null +++ b/semtypes/src/main/java/io/ballerina/semtype/ComplexSemType.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.semtype; + +import java.util.ArrayList; + +/** + * ComplexSemType node. + * + * @since 2.0.0 + */ +public class ComplexSemType implements SemType { + // For a uniform type with code c, + // all & (1 << c) is non-zero iff this type contains all of the uniform type + // some & (1 << c) is non-zero iff this type contains some but not all of the uniform type + public final UniformTypeBitSet all; + public final UniformTypeBitSet some; + // There is one member of subtypes for each bit set in some. + // Ordered in increasing order of UniformTypeCode + public final SubtypeData[] subtypeDataList; + + public ComplexSemType(UniformTypeBitSet all, UniformTypeBitSet some, SubtypeData[] subtypeDataList) { + this.all = all; + this.some = some; + this.subtypeDataList = subtypeDataList; + } + + public static ComplexSemType createComplexSemType(int allBitset, UniformSubtype... subtypeList) { + int some = 0; + ArrayList dataList = new ArrayList<>(); + for (UniformSubtype uniformSubtype : subtypeList) { + dataList.add(uniformSubtype.subtypeData); + long c = uniformSubtype.uniformTypeCode; + some |= 1L << c; + } + return new ComplexSemType( + new UniformTypeBitSet(allBitset), new UniformTypeBitSet(some), dataList.toArray(new SubtypeData[]{})); + } +} diff --git a/semtypes/src/main/java/io/ballerina/types/Definition.java b/semtypes/src/main/java/io/ballerina/semtype/Definition.java similarity index 70% rename from semtypes/src/main/java/io/ballerina/types/Definition.java rename to semtypes/src/main/java/io/ballerina/semtype/Definition.java index 6b0a359083fa..da0d79a9bf6a 100644 --- a/semtypes/src/main/java/io/ballerina/types/Definition.java +++ b/semtypes/src/main/java/io/ballerina/semtype/Definition.java @@ -1,7 +1,7 @@ /* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * - * WSO2 LLC. licenses this file to you under the Apache License, + * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at @@ -11,16 +11,16 @@ * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the + * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ -package io.ballerina.types; +package io.ballerina.semtype; /** * Super type for type-descs. * - * @since 2201.8.0 + * @since 2.0.0 */ public interface Definition { SemType getSemType(Env env); diff --git a/semtypes/src/main/java/io/ballerina/semtype/Env.java b/semtypes/src/main/java/io/ballerina/semtype/Env.java new file mode 100644 index 000000000000..ee00c5044853 --- /dev/null +++ b/semtypes/src/main/java/io/ballerina/semtype/Env.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.semtype; + +import java.util.ArrayList; +import java.util.HashMap; + +/** + * Env node. + * + * @since 2.0.0 + */ +public class Env { + private final HashMap atomTable; + private final ArrayList recListAtoms; + private final ArrayList recMappingAtoms; + private final ArrayList recFunctionAtoms; + + public Env() { + this.atomTable = new HashMap<>(); + // Set up index 0 for use by bddFixReadOnly + this.recListAtoms = new ArrayList<>(); + this.recListAtoms.add(ListAtomicType.LIST_SUBTYPE_RO); + + this.recMappingAtoms = new ArrayList<>(); + // todo: add MAPPING_SUBTYPE_RO + this.recFunctionAtoms = new ArrayList<>(); + } + + +} diff --git a/semtypes/src/main/java/io/ballerina/semtype/FunctionAtomicType.java b/semtypes/src/main/java/io/ballerina/semtype/FunctionAtomicType.java new file mode 100644 index 000000000000..8ca845b74f22 --- /dev/null +++ b/semtypes/src/main/java/io/ballerina/semtype/FunctionAtomicType.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.semtype; + +/** + * FunctionAtomicType node. + * + * @since 2.0.0 + */ +public class FunctionAtomicType { + SemType paramType; + SemType retType; +} diff --git a/semtypes/src/main/java/io/ballerina/types/IsEmptyOp.java b/semtypes/src/main/java/io/ballerina/semtype/IsEmptyOp.java similarity index 65% rename from semtypes/src/main/java/io/ballerina/types/IsEmptyOp.java rename to semtypes/src/main/java/io/ballerina/semtype/IsEmptyOp.java index 7697284af7b9..ce410b0d222f 100644 --- a/semtypes/src/main/java/io/ballerina/types/IsEmptyOp.java +++ b/semtypes/src/main/java/io/ballerina/semtype/IsEmptyOp.java @@ -1,7 +1,7 @@ /* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * - * WSO2 LLC. licenses this file to you under the Apache License, + * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at @@ -11,17 +11,17 @@ * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the + * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ -package io.ballerina.types; +package io.ballerina.semtype; /** * Interface representing {@code isEmpty} operation. * - * @since 2201.8.0 + * @since 2.0.0 */ public interface IsEmptyOp { - boolean isEmpty(Context cx, SubtypeData t); + boolean isEmpty(TypeCheckContext tc, SubtypeData t); } diff --git a/semtypes/src/main/java/io/ballerina/semtype/ListAtomicType.java b/semtypes/src/main/java/io/ballerina/semtype/ListAtomicType.java new file mode 100644 index 000000000000..6dedbb509453 --- /dev/null +++ b/semtypes/src/main/java/io/ballerina/semtype/ListAtomicType.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.semtype; + +import java.util.ArrayList; + +/** + * ListAtomicType node. + * + * @since 2.0.0 + */ +public class ListAtomicType implements AtomicType { + final ArrayList members; + final SemType rest; + + public static final ListAtomicType LIST_SUBTYPE_RO = new ListAtomicType(new ArrayList<>(), PredefinedType.READONLY); + + public ListAtomicType(ArrayList members, SemType rest) { + this.members = members; + this.rest = rest; + } +} diff --git a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/TypeTestContext.java b/semtypes/src/main/java/io/ballerina/semtype/MappingAtomicType.java similarity index 64% rename from tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/TypeTestContext.java rename to semtypes/src/main/java/io/ballerina/semtype/MappingAtomicType.java index 86402244cc03..a455f45c165d 100644 --- a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/TypeTestContext.java +++ b/semtypes/src/main/java/io/ballerina/semtype/MappingAtomicType.java @@ -1,7 +1,7 @@ /* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * - * WSO2 LLC. licenses this file to you under the Apache License, + * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at @@ -15,14 +15,12 @@ * specific language governing permissions and limitations * under the License. */ +package io.ballerina.semtype; -package io.ballerina.semtype.port.test; - -public interface TypeTestContext { - - TypeTestEnv getEnv(); - - Object getInnerEnv(); - - Object getInnerContext(); +/** + * MappingAtomicType node. + * + * @since 2.0.0 + */ +public class MappingAtomicType implements AtomicType { } diff --git a/semtypes/src/main/java/io/ballerina/semtype/PredefinedType.java b/semtypes/src/main/java/io/ballerina/semtype/PredefinedType.java new file mode 100644 index 000000000000..fcad89624357 --- /dev/null +++ b/semtypes/src/main/java/io/ballerina/semtype/PredefinedType.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.semtype; + +import io.ballerina.semtype.subtypedata.IntSubtype; + +/** + * Contain predefined types used for constructing other types. + * + * @since 2.0.0 + */ +public final class PredefinedType { + + public static final UniformTypeBitSet NEVER = uniformTypeUnion(0); + public static final UniformTypeBitSet NIL = uniformType(UniformTypeCode.UT_NIL); + public static final UniformTypeBitSet BOOLEAN = uniformType(UniformTypeCode.UT_BOOLEAN); + public static final UniformTypeBitSet INT = uniformType(UniformTypeCode.UT_INT); + public static final UniformTypeBitSet FLOAT = uniformType(UniformTypeCode.UT_FLOAT); + public static final UniformTypeBitSet DECIMAL = uniformType(UniformTypeCode.UT_DECIMAL); + public static final UniformTypeBitSet STRING = uniformType(UniformTypeCode.UT_STRING); + public static final UniformTypeBitSet ERROR = uniformType(UniformTypeCode.UT_ERROR); + public static final UniformTypeBitSet LIST_RW = uniformType(UniformTypeCode.UT_LIST_RW); + public static final UniformTypeBitSet LIST = + uniformTypeUnion((1 << UniformTypeCode.UT_LIST_RO) | (1 << UniformTypeCode.UT_LIST_RW)); + public static final UniformTypeBitSet MAPPING_RW = uniformType(UniformTypeCode.UT_MAPPING_RW); + public static final UniformTypeBitSet MAPPING = + uniformTypeUnion((1 << UniformTypeCode.UT_MAPPING_RO) | (1 << UniformTypeCode.UT_MAPPING_RW)); + + // matches all functions + public static final UniformTypeBitSet FUNCTION = uniformType(UniformTypeCode.UT_FUNCTION); + public static final UniformTypeBitSet TYPEDESC = uniformType(UniformTypeCode.UT_TYPEDESC); + public static final UniformTypeBitSet HANDLE = uniformType(UniformTypeCode.UT_HANDLE); + + public static final UniformTypeBitSet XML = + uniformTypeUnion((1 << UniformTypeCode.UT_XML_RO) | (1 << UniformTypeCode.UT_XML_RW)); + public static final UniformTypeBitSet STREAM = uniformType(UniformTypeCode.UT_STREAM); + public static final UniformTypeBitSet FUTURE = uniformType(UniformTypeCode.UT_FUTURE); + + // this is SubtypeData|error + public static final UniformTypeBitSet TOP = uniformTypeUnion(UniformTypeCode.UT_MASK); + public static final UniformTypeBitSet ANY = + uniformTypeUnion(UniformTypeCode.UT_MASK & ~(1 << UniformTypeCode.UT_ERROR)); + public static final UniformTypeBitSet READONLY = uniformTypeUnion(UniformTypeCode.UT_READONLY); + public static final UniformTypeBitSet SIMPLE_OR_STRING = + uniformTypeUnion((1 << UniformTypeCode.UT_NIL) + | (1 << UniformTypeCode.UT_BOOLEAN) + | (1 << UniformTypeCode.UT_INT) + | (1 << UniformTypeCode.UT_FLOAT) + | (1 << UniformTypeCode.UT_DECIMAL) + | (1 << UniformTypeCode.UT_STRING)); + public static final SemType BYTE = IntSubtype.intWidthUnsigned(8); + + private PredefinedType() { + } + + private static UniformTypeBitSet uniformTypeUnion(int bitset) { + return new UniformTypeBitSet(bitset); + } + + private static UniformTypeBitSet uniformType(int code) { + return new UniformTypeBitSet(1 << code); + } + + public static SemType uniformSubtype(int code, ProperSubtypeData data) { + return ComplexSemType.createComplexSemType(0, new UniformSubtype(code, data)); + } +} diff --git a/semtypes/src/main/java/io/ballerina/types/ProperSubtypeData.java b/semtypes/src/main/java/io/ballerina/semtype/ProperSubtypeData.java similarity index 69% rename from semtypes/src/main/java/io/ballerina/types/ProperSubtypeData.java rename to semtypes/src/main/java/io/ballerina/semtype/ProperSubtypeData.java index 5ee0e48548db..151c1bd1d133 100644 --- a/semtypes/src/main/java/io/ballerina/types/ProperSubtypeData.java +++ b/semtypes/src/main/java/io/ballerina/semtype/ProperSubtypeData.java @@ -1,7 +1,7 @@ /* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * - * WSO2 LLC. licenses this file to you under the Apache License, + * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at @@ -11,16 +11,16 @@ * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the + * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ -package io.ballerina.types; +package io.ballerina.semtype; /** * ProperSubtypeData node. * - * @since 2201.8.0 + * @since 2.0.0 */ public interface ProperSubtypeData extends SubtypeData { } diff --git a/semtypes/src/main/java/io/ballerina/types/README.md b/semtypes/src/main/java/io/ballerina/semtype/README.md similarity index 100% rename from semtypes/src/main/java/io/ballerina/types/README.md rename to semtypes/src/main/java/io/ballerina/semtype/README.md diff --git a/semtypes/src/main/java/io/ballerina/semtype/RecAtom.java b/semtypes/src/main/java/io/ballerina/semtype/RecAtom.java new file mode 100644 index 000000000000..eaea5a9a50e5 --- /dev/null +++ b/semtypes/src/main/java/io/ballerina/semtype/RecAtom.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.semtype; + +/** + * Represent a recursive type atom. + * + * @since 2.0.0 + */ +public class RecAtom implements Atom { + int index; + + public RecAtom(int index) { + this.index = index; + } + + public static RecAtom createRecAtom(int index) { + return new RecAtom(index); + } +} diff --git a/semtypes/src/main/java/io/ballerina/types/SemType.java b/semtypes/src/main/java/io/ballerina/semtype/SemType.java similarity index 68% rename from semtypes/src/main/java/io/ballerina/types/SemType.java rename to semtypes/src/main/java/io/ballerina/semtype/SemType.java index 3b07310dc61e..98bcc7292b55 100644 --- a/semtypes/src/main/java/io/ballerina/types/SemType.java +++ b/semtypes/src/main/java/io/ballerina/semtype/SemType.java @@ -1,7 +1,7 @@ /* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * - * WSO2 LLC. licenses this file to you under the Apache License, + * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at @@ -11,18 +11,16 @@ * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the + * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ -package io.ballerina.types; +package io.ballerina.semtype; /** * SemType node. * - * @since 2201.8.0 + * @since 2.0.0 */ public interface SemType { - - int all(); } diff --git a/semtypes/src/main/java/io/ballerina/semtype/SemTypeMock.java b/semtypes/src/main/java/io/ballerina/semtype/SemTypeMock.java new file mode 100644 index 000000000000..f908b14ee024 --- /dev/null +++ b/semtypes/src/main/java/io/ballerina/semtype/SemTypeMock.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.semtype; + +/** + * SemType Interface. + */ +public interface SemTypeMock { + +} + +/** + * Complex SemType implementation. + */ +class ComplexSemTypeMock implements SemTypeMock { + UniformTypeBitSet all; + UniformTypeBitSet some; + +} + +/** + * UniformTypeBitSet SemType implementation. + */ +class UniformTypeBitSetMock implements SemTypeMock { + int value; + + public UniformTypeBitSetMock(int value) { + this.value = value; + } + + public int getValue() { + return value; + } +} diff --git a/semtypes/src/main/java/io/ballerina/types/SubtypeData.java b/semtypes/src/main/java/io/ballerina/semtype/SubtypeData.java similarity index 69% rename from semtypes/src/main/java/io/ballerina/types/SubtypeData.java rename to semtypes/src/main/java/io/ballerina/semtype/SubtypeData.java index 51d8a9810103..8b6834734a85 100644 --- a/semtypes/src/main/java/io/ballerina/types/SubtypeData.java +++ b/semtypes/src/main/java/io/ballerina/semtype/SubtypeData.java @@ -1,7 +1,7 @@ /* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * - * WSO2 LLC. licenses this file to you under the Apache License, + * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at @@ -11,16 +11,16 @@ * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the + * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ -package io.ballerina.types; +package io.ballerina.semtype; /** * Represent SubtypeData type. * - * @since 2201.8.0 + * @since 2.0.0 */ public interface SubtypeData { } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/MappingProj.java b/semtypes/src/main/java/io/ballerina/semtype/TypeAtom.java similarity index 51% rename from bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/MappingProj.java rename to semtypes/src/main/java/io/ballerina/semtype/TypeAtom.java index cd3c113054d3..1a629bdf616d 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/MappingProj.java +++ b/semtypes/src/main/java/io/ballerina/semtype/TypeAtom.java @@ -1,7 +1,7 @@ /* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * - * WSO2 LLC. licenses this file to you under the Apache License, + * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at @@ -14,25 +14,24 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. - * */ - -package io.ballerina.runtime.api.types.semtype; - -import io.ballerina.runtime.internal.types.semtype.BMappingProj; +package io.ballerina.semtype; /** - * Utility class for mapping type projection. + * Represent a TypeAtom. * - * @since 2201.11.0 + * @since 2.0.0 */ -public final class MappingProj { +public class TypeAtom implements Atom { + long index; + AtomicType atomicType; - private MappingProj() { + public TypeAtom(long index, AtomicType atomicType) { + this.index = index; + this.atomicType = atomicType; } - public static SemType mappingMemberTypeInnerVal(Context cx, SemType t, SemType k) { - return BMappingProj.mappingMemberTypeInnerVal(cx, t, k); + public static TypeAtom createTypeAtom(long index, AtomicType atomicType) { + return new TypeAtom(index, atomicType); } - } diff --git a/semtypes/src/main/java/io/ballerina/semtype/TypeCheckContext.java b/semtypes/src/main/java/io/ballerina/semtype/TypeCheckContext.java new file mode 100644 index 000000000000..ec5acf707f68 --- /dev/null +++ b/semtypes/src/main/java/io/ballerina/semtype/TypeCheckContext.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.semtype; + +/** + * TypeCheckContext node. + * + * @since 2.0.0 + */ +public class TypeCheckContext { + private final Env env; + // todo: Normal hash tables should do here + // BddMemoTable listMemo = table []; + // BddMemoTable mappingMemo = table []; + // BddMemoTable functionMemo = table []; + + public TypeCheckContext(Env env) { + this.env = env; + } + + +// function listAtomType(Atom atom) returns ListAtomicType { +// if atom is RecAtom { +// return self.env.getRecListAtomType(atom); +// } +// else { +// return atom.atomicType; +// } +// } +// +// function mappingAtomType(Atom atom) returns MappingAtomicType { +// if atom is RecAtom { +// return self.env.getRecMappingAtomType(atom); +// } +// else { +// return atom.atomicType; +// } +// } +// +// function functionAtomType(Atom atom) returns FunctionAtomicType { +// return self.env.getRecFunctionAtomType(atom); +// } +} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/ListProj.java b/semtypes/src/main/java/io/ballerina/semtype/UniformSubtype.java similarity index 53% rename from bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/ListProj.java rename to semtypes/src/main/java/io/ballerina/semtype/UniformSubtype.java index e1d579e9b266..bcd02fa91e34 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/ListProj.java +++ b/semtypes/src/main/java/io/ballerina/semtype/UniformSubtype.java @@ -1,7 +1,7 @@ /* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * - * WSO2 LLC. licenses this file to you under the Apache License, + * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at @@ -15,23 +15,19 @@ * specific language governing permissions and limitations * under the License. */ - -package io.ballerina.runtime.api.types.semtype; - -import io.ballerina.runtime.internal.types.semtype.BListProj; +package io.ballerina.semtype; /** - * Utility class for list type projection. + * UniformSubtype node. * - * @since 2201.11.0 + * @since 2.0.0 */ -public final class ListProj { +public class UniformSubtype { + public final int uniformTypeCode; + public final SubtypeData subtypeData; - private ListProj() { + public UniformSubtype(int uniformTypeCode, SubtypeData subtypeData) { + this.uniformTypeCode = uniformTypeCode; + this.subtypeData = subtypeData; } - - public static SemType listProjInnerVal(Context cx, SemType t, SemType k) { - return BListProj.listProjInnerVal(cx, t, k); - } - } diff --git a/semtypes/src/main/java/io/ballerina/semtype/UniformTypeBitSet.java b/semtypes/src/main/java/io/ballerina/semtype/UniformTypeBitSet.java new file mode 100644 index 000000000000..dc3621d7d0d3 --- /dev/null +++ b/semtypes/src/main/java/io/ballerina/semtype/UniformTypeBitSet.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.semtype; + +/** + * UniformTypeBitSet node. + * + * @since 2.0.0 + */ +public class UniformTypeBitSet implements SemType { + int bitset; + + public UniformTypeBitSet(int bitset) { + this.bitset = bitset; + } +} diff --git a/semtypes/src/main/java/io/ballerina/semtype/UniformTypeCode.java b/semtypes/src/main/java/io/ballerina/semtype/UniformTypeCode.java new file mode 100644 index 000000000000..2b3adf472510 --- /dev/null +++ b/semtypes/src/main/java/io/ballerina/semtype/UniformTypeCode.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.semtype; + +/** + * Represent bit field that indicate which uniform type a semType belongs to. + * Regular types are divided longo mutable part and immutable part and these parts are called an uniform type. + * 5th bit indicate mutability; 0 immutable, 1 mutable. + * + * @since 2.0.0 + */ +public final class UniformTypeCode { + + // Inherently immutable + public static final int UT_NIL = 0x00; + public static final int UT_BOOLEAN = 0x01; + + // Selectively immutable; immutable half + public static final int UT_LIST_RO = 0x02; + public static final int UT_MAPPING_RO = 0x03; + public static final int UT_TABLE_RO = 0x04; + public static final int UT_XML_RO = 0x05; + public static final int UT_OBJECT_RO = 0x06; + + // Rest of inherently immutable + public static final int UT_INT = 0x07; + public static final int UT_FLOAT = 0x08; + public static final int UT_DECIMAL = 0x09; + public static final int UT_STRING = 0x0A; + public static final int UT_ERROR = 0x0B; + public static final int UT_FUNCTION = 0x0C; + public static final int UT_TYPEDESC = 0x0D; + public static final int UT_HANDLE = 0x0E; + + // Inherently mutable + public static final int UT_FUTURE = 0x10; + public static final int UT_STREAM = 0x11; + + // Selectively immutable; mutable half + public static final int UT_LIST_RW = 0x12; + public static final int UT_MAPPING_RW = 0x13; + public static final int UT_TABLE_RW = 0x14; + public static final int UT_XML_RW = 0x15; + public static final int UT_OBJECT_RW = 0x16; + + // Helper bit fields (does not represent uniform type tag) + static final int UT_COUNT = UT_OBJECT_RW + 1; + static final int UT_MASK = (1 << UT_COUNT) - 1; + + static final int UT_COUNT_RO = 0x10; + static final int UT_READONLY = (1 << UT_COUNT_RO) - 1; + + static final int UT_RW_MASK = UT_MASK ^ ~UT_READONLY; + + private UniformTypeCode() { + } +} diff --git a/semtypes/src/main/java/io/ballerina/semtype/UniformTypeOps.java b/semtypes/src/main/java/io/ballerina/semtype/UniformTypeOps.java new file mode 100644 index 000000000000..2fb53b153b62 --- /dev/null +++ b/semtypes/src/main/java/io/ballerina/semtype/UniformTypeOps.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.semtype; + +/** + * Interface representing type operations on uniform types. + * + * @since 2.0.0 + */ +public interface UniformTypeOps extends IsEmptyOp, CommonUniformTypeOps { +} diff --git a/semtypes/src/main/java/io/ballerina/semtype/definition/FunctionDefinition.java b/semtypes/src/main/java/io/ballerina/semtype/definition/FunctionDefinition.java new file mode 100644 index 000000000000..34028895f964 --- /dev/null +++ b/semtypes/src/main/java/io/ballerina/semtype/definition/FunctionDefinition.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.semtype.definition; + +import io.ballerina.semtype.Definition; +import io.ballerina.semtype.Env; +import io.ballerina.semtype.SemType; + +/** + * Represent function type desc. + * + * @since 2.0.0 + */ +public class FunctionDefinition implements Definition { + @Override + public SemType getSemType(Env env) { + throw new AssertionError(); + } +} diff --git a/semtypes/src/main/java/io/ballerina/semtype/definition/ListDefinition.java b/semtypes/src/main/java/io/ballerina/semtype/definition/ListDefinition.java new file mode 100644 index 000000000000..3a277c03c12b --- /dev/null +++ b/semtypes/src/main/java/io/ballerina/semtype/definition/ListDefinition.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.semtype.definition; + +import io.ballerina.semtype.Definition; +import io.ballerina.semtype.Env; +import io.ballerina.semtype.SemType; + +/** + * Represent list/tuple type desc. + * + * @since 2.0.0 + */ +public class ListDefinition implements Definition { + @Override + public SemType getSemType(Env env) { + throw new AssertionError(); + } +} diff --git a/semtypes/src/main/java/io/ballerina/semtype/definition/MappingDefinition.java b/semtypes/src/main/java/io/ballerina/semtype/definition/MappingDefinition.java new file mode 100644 index 000000000000..d9651e97a3b8 --- /dev/null +++ b/semtypes/src/main/java/io/ballerina/semtype/definition/MappingDefinition.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.semtype.definition; + +import io.ballerina.semtype.Definition; +import io.ballerina.semtype.Env; +import io.ballerina.semtype.SemType; + +/** + * Represent mapping type desc. + * + * @since 2.0.0 + */ +public class MappingDefinition implements Definition { + @Override + public SemType getSemType(Env env) { + throw new AssertionError(); + } +} diff --git a/semtypes/src/main/java/io/ballerina/types/subtypedata/AllOrNothingSubtype.java b/semtypes/src/main/java/io/ballerina/semtype/subtypedata/AllOrNothingSubtype.java similarity index 68% rename from semtypes/src/main/java/io/ballerina/types/subtypedata/AllOrNothingSubtype.java rename to semtypes/src/main/java/io/ballerina/semtype/subtypedata/AllOrNothingSubtype.java index 40099994dddc..b14487953317 100644 --- a/semtypes/src/main/java/io/ballerina/types/subtypedata/AllOrNothingSubtype.java +++ b/semtypes/src/main/java/io/ballerina/semtype/subtypedata/AllOrNothingSubtype.java @@ -1,7 +1,7 @@ /* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * - * WSO2 LLC. licenses this file to you under the Apache License, + * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at @@ -11,36 +11,33 @@ * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the + * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ -package io.ballerina.types.subtypedata; +package io.ballerina.semtype.subtypedata; -import io.ballerina.types.SubtypeData; +import io.ballerina.semtype.SubtypeData; /** * A subtype representing either all subtypes or nothing. * This is the Java representation of the `boolean` found in `SubtypeData` type in Ballerina impl. * - * @since 2201.8.0 + * @since 2.0.0 */ public class AllOrNothingSubtype implements SubtypeData { private final boolean isAll; - private static final AllOrNothingSubtype all = new AllOrNothingSubtype(true); - private static final AllOrNothingSubtype nothing = new AllOrNothingSubtype(false); - private AllOrNothingSubtype(boolean isAll) { this.isAll = isAll; } public static AllOrNothingSubtype createAll() { - return all; + return new AllOrNothingSubtype(true); } public static AllOrNothingSubtype createNothing() { - return nothing; + return new AllOrNothingSubtype(false); } public boolean isAllSubtype() { diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BddPredicate.java b/semtypes/src/main/java/io/ballerina/semtype/subtypedata/BddNode.java similarity index 58% rename from bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BddPredicate.java rename to semtypes/src/main/java/io/ballerina/semtype/subtypedata/BddNode.java index 4a6e47f3c870..9c657c468581 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BddPredicate.java +++ b/semtypes/src/main/java/io/ballerina/semtype/subtypedata/BddNode.java @@ -1,7 +1,7 @@ /* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * - * WSO2 LLC. licenses this file to you under the Apache License, + * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at @@ -14,18 +14,20 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. - * */ +package io.ballerina.semtype.subtypedata; -package io.ballerina.runtime.api.types.semtype; +import io.ballerina.semtype.Atom; +import io.ballerina.semtype.Bdd; /** - * Represents a predicate that can be applied to a BDD conjunction. + * Bdd node. * - * @since 2201.11.0 + * @since 2.0.0 */ -@FunctionalInterface -public interface BddPredicate { - - boolean apply(Context cx, Conjunction posList, Conjunction negList); +public class BddNode implements Bdd { + Atom atom; + BddNode left; + BddNode middle; + BddNode right; } diff --git a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/TypeTestEnv.java b/semtypes/src/main/java/io/ballerina/semtype/subtypedata/BooleanSubtype.java similarity index 60% rename from tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/TypeTestEnv.java rename to semtypes/src/main/java/io/ballerina/semtype/subtypedata/BooleanSubtype.java index 3a1afd44326f..d4b9ede5829e 100644 --- a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/TypeTestEnv.java +++ b/semtypes/src/main/java/io/ballerina/semtype/subtypedata/BooleanSubtype.java @@ -1,7 +1,7 @@ /* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * - * WSO2 LLC. licenses this file to you under the Apache License, + * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at @@ -15,16 +15,15 @@ * specific language governing permissions and limitations * under the License. */ +package io.ballerina.semtype.subtypedata; -package io.ballerina.semtype.port.test; +import io.ballerina.semtype.ProperSubtypeData; -import java.util.Map; - -public interface TypeTestEnv { - - Map getTypeNameSemTypeMap(); - - void addTypeDef(String value, SemType semtype); +/** + * Represent BooleanSubtype. + * + * @since 2.0.0 + */ +public class BooleanSubtype implements ProperSubtypeData { - Object getInnerEnv(); } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/DelegatedSubType.java b/semtypes/src/main/java/io/ballerina/semtype/subtypedata/FloatSubtype.java similarity index 59% rename from bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/DelegatedSubType.java rename to semtypes/src/main/java/io/ballerina/semtype/subtypedata/FloatSubtype.java index 6f798ca4d07c..8f28d7bc9025 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/DelegatedSubType.java +++ b/semtypes/src/main/java/io/ballerina/semtype/subtypedata/FloatSubtype.java @@ -1,7 +1,7 @@ /* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * - * WSO2 LLC. licenses this file to you under the Apache License, + * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at @@ -15,17 +15,15 @@ * specific language governing permissions and limitations * under the License. */ +package io.ballerina.semtype.subtypedata; -package io.ballerina.runtime.internal.types.semtype; - -import io.ballerina.runtime.api.types.semtype.SubType; +import io.ballerina.semtype.ProperSubtypeData; /** - * Represents the subtype implemented by BDDs. + * Represent FloatSubtype. * - * @since 2201.11.0 + * @since 2.0.0 */ -public interface DelegatedSubType extends SubTypeData { +public class FloatSubtype implements ProperSubtypeData { - SubType inner(); } diff --git a/semtypes/src/main/java/io/ballerina/types/subtypedata/IntSubtype.java b/semtypes/src/main/java/io/ballerina/semtype/subtypedata/IntSubtype.java similarity index 63% rename from semtypes/src/main/java/io/ballerina/types/subtypedata/IntSubtype.java rename to semtypes/src/main/java/io/ballerina/semtype/subtypedata/IntSubtype.java index e977b77cdfd5..475640212fca 100644 --- a/semtypes/src/main/java/io/ballerina/types/subtypedata/IntSubtype.java +++ b/semtypes/src/main/java/io/ballerina/semtype/subtypedata/IntSubtype.java @@ -1,7 +1,7 @@ /* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * - * WSO2 LLC. licenses this file to you under the Apache License, + * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at @@ -11,30 +11,29 @@ * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the + * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ -package io.ballerina.types.subtypedata; +package io.ballerina.semtype.subtypedata; -import io.ballerina.types.BasicTypeCode; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.ProperSubtypeData; -import io.ballerina.types.SemType; -import io.ballerina.types.SubtypeData; +import io.ballerina.semtype.PredefinedType; +import io.ballerina.semtype.ProperSubtypeData; +import io.ballerina.semtype.SemType; +import io.ballerina.semtype.SubtypeData; +import io.ballerina.semtype.UniformTypeCode; import java.util.Arrays; import java.util.Optional; -import java.util.StringJoiner; /** * Represent IntSubtype. * - * @since 2201.8.0 + * @since 2.0.0 */ public class IntSubtype implements ProperSubtypeData { - public final Range[] ranges; + private final Range[] ranges; public IntSubtype(Range[] ranges) { this.ranges = Arrays.copyOf(ranges, ranges.length); @@ -49,7 +48,7 @@ public static IntSubtype createSingleRangeSubtype(long min, long max) { } public static SemType intConst(long value) { - return PredefinedType.basicSubtype(BasicTypeCode.BT_INT, createSingleRangeSubtype(value, value)); + return PredefinedType.uniformSubtype(UniformTypeCode.UT_INT, createSingleRangeSubtype(value, value)); } static void validIntWidth(boolean signed, long bits) { @@ -85,17 +84,17 @@ public static SemType intWidthSigned(long bits) { return PredefinedType.INT; } IntSubtype t = createSingleRangeSubtype(-(1L << (bits - 1L)), (1L << (bits - 1L)) - 1L); - return PredefinedType.basicSubtype(BasicTypeCode.BT_INT, t); + return PredefinedType.uniformSubtype(UniformTypeCode.UT_INT, t); } public static SemType intWidthUnsigned(int bits) { validIntWidth(false, bits); IntSubtype t = createSingleRangeSubtype(0L, (1L << bits) - 1L); - return PredefinedType.basicSubtype(BasicTypeCode.BT_INT, t); + return PredefinedType.uniformSubtype(UniformTypeCode.UT_INT, t); } // Widen to UnsignedN - public static SubtypeData intSubtypeWidenUnsigned(SubtypeData d) { + public SubtypeData intSubtypeWidenUnsigned(SubtypeData d) { if (d instanceof AllOrNothingSubtype) { return d; } @@ -106,10 +105,10 @@ public static SubtypeData intSubtypeWidenUnsigned(SubtypeData d) { } Range r = v.ranges[v.ranges.length - 1]; - long i = 8L; - while (i <= 32L) { + int i = 8; + while (i <= 32) { if (r.max < (1L << i)) { - IntSubtype w = createSingleRangeSubtype(0L, (1L << i) - 1); + IntSubtype w = createSingleRangeSubtype(0L, i); return w; } i = i * 2; @@ -117,7 +116,7 @@ public static SubtypeData intSubtypeWidenUnsigned(SubtypeData d) { return AllOrNothingSubtype.createAll(); } - public static Optional intSubtypeSingleValue(SubtypeData d) { + public Optional intSubtypeSingleValue(SubtypeData d) { if (d instanceof AllOrNothingSubtype) { return Optional.empty(); } @@ -134,32 +133,16 @@ public static Optional intSubtypeSingleValue(SubtypeData d) { return Optional.of(min); } - public static boolean intSubtypeContains(SubtypeData d, long n) { - if (d instanceof AllOrNothingSubtype allOrNothingSubtype) { - return allOrNothingSubtype.isAllSubtype(); - } - IntSubtype v = (IntSubtype) d; - for (Range r : v.ranges) { - if (r.min <= n && n <= r.max) { - return true; - } - } - return false; - } - - @Override - public String toString() { - StringJoiner j = new StringJoiner(", ", "Int:Range[", "]"); - for (Range r : ranges) { - j.add(minusIndi(r.min) + "-" + minusIndi(r.max)); - } - return j.toString(); - } + /** + * Int Range node. + */ + static class Range { + final long min; + final long max; - private String minusIndi(long i) { - if (i < 0) { - return "(" + i + ")"; + public Range(long min, long max) { + this.min = min; + this.max = max; } - return String.valueOf(i); } } diff --git a/semtypes/src/main/java/io/ballerina/semtype/subtypedata/StringSubtype.java b/semtypes/src/main/java/io/ballerina/semtype/subtypedata/StringSubtype.java new file mode 100644 index 000000000000..e2d25feb5261 --- /dev/null +++ b/semtypes/src/main/java/io/ballerina/semtype/subtypedata/StringSubtype.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.semtype.subtypedata; + +import io.ballerina.semtype.ProperSubtypeData; + +/** + * Represent StringSubtype. + * + * @since 2.0.0 + */ +public class StringSubtype implements ProperSubtypeData { + +} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/CommonOps.java b/semtypes/src/main/java/io/ballerina/semtype/typeops/CommonOps.java similarity index 57% rename from semtypes/src/main/java/io/ballerina/types/typeops/CommonOps.java rename to semtypes/src/main/java/io/ballerina/semtype/typeops/CommonOps.java index 30254d0a12ab..328686d429ef 100644 --- a/semtypes/src/main/java/io/ballerina/types/typeops/CommonOps.java +++ b/semtypes/src/main/java/io/ballerina/semtype/typeops/CommonOps.java @@ -1,7 +1,7 @@ /* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * - * WSO2 LLC. licenses this file to you under the Apache License, + * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at @@ -11,39 +11,38 @@ * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the + * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ -package io.ballerina.types.typeops; +package io.ballerina.semtype.typeops; -import io.ballerina.types.Bdd; -import io.ballerina.types.CommonBasicTypeOps; -import io.ballerina.types.SubtypeData; +import io.ballerina.semtype.CommonUniformTypeOps; +import io.ballerina.semtype.SubtypeData; /** * Common methods operate on SubtypeData. * - * @since 2201.8.0 + * @since 2.0.0 */ -public abstract class CommonOps implements CommonBasicTypeOps { +public abstract class CommonOps implements CommonUniformTypeOps { @Override public SubtypeData union(SubtypeData t1, SubtypeData t2) { - return BddCommonOps.bddUnion((Bdd) t1, (Bdd) t2); + throw new AssertionError(); } @Override public SubtypeData intersect(SubtypeData t1, SubtypeData t2) { - return BddCommonOps.bddIntersect((Bdd) t1, (Bdd) t2); + throw new AssertionError(); } @Override public SubtypeData diff(SubtypeData t1, SubtypeData t2) { - return BddCommonOps.bddDiff((Bdd) t1, (Bdd) t2); + throw new AssertionError(); } @Override public SubtypeData complement(SubtypeData t) { - return BddCommonOps.bddComplement((Bdd) t); + throw new AssertionError(); } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Conjunction.java b/semtypes/src/main/java/io/ballerina/semtype/typeops/FunctionOps.java similarity index 50% rename from bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Conjunction.java rename to semtypes/src/main/java/io/ballerina/semtype/typeops/FunctionOps.java index 2faf2c559857..507e271c1ed9 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Conjunction.java +++ b/semtypes/src/main/java/io/ballerina/semtype/typeops/FunctionOps.java @@ -1,7 +1,7 @@ /* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * - * WSO2 LLC. licenses this file to you under the Apache License, + * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at @@ -14,22 +14,21 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. - * */ +package io.ballerina.semtype.typeops; -package io.ballerina.runtime.api.types.semtype; +import io.ballerina.semtype.SubtypeData; +import io.ballerina.semtype.TypeCheckContext; +import io.ballerina.semtype.UniformTypeOps; /** - * Represents the Conjunction in the BDD. + * Function specific methods operate on SubtypeData. * - * @param atom Atom of this node - * @param next Next node in the conjunction, will be {@code null} if this is the - * last node - * @since 2201.11.0 + * @since 2.0.0 */ -public record Conjunction(Atom atom, Conjunction next) { - - public static Conjunction and(Atom atom, Conjunction next) { - return new Conjunction(atom, next); +public class FunctionOps extends CommonOps implements UniformTypeOps { + @Override + public boolean isEmpty(TypeCheckContext tc, SubtypeData t) { + throw new AssertionError(); } } diff --git a/semtypes/src/main/java/io/ballerina/semtype/typeops/ListTypeRWOps.java b/semtypes/src/main/java/io/ballerina/semtype/typeops/ListTypeRWOps.java new file mode 100644 index 000000000000..d6734164f8d4 --- /dev/null +++ b/semtypes/src/main/java/io/ballerina/semtype/typeops/ListTypeRWOps.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.semtype.typeops; + +import io.ballerina.semtype.SubtypeData; +import io.ballerina.semtype.TypeCheckContext; +import io.ballerina.semtype.UniformTypeOps; + +/** + * List read/write specific methods operate on SubtypeData. + * + * @since 2.0.0 + */ +public class ListTypeRWOps extends CommonOps implements UniformTypeOps { + @Override + public boolean isEmpty(TypeCheckContext tc, SubtypeData t) { + throw new AssertionError(); + } +} diff --git a/semtypes/src/main/java/io/ballerina/semtype/typeops/ListTypeRoOps.java b/semtypes/src/main/java/io/ballerina/semtype/typeops/ListTypeRoOps.java new file mode 100644 index 000000000000..9ee27e5105e9 --- /dev/null +++ b/semtypes/src/main/java/io/ballerina/semtype/typeops/ListTypeRoOps.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.semtype.typeops; + +import io.ballerina.semtype.SubtypeData; +import io.ballerina.semtype.TypeCheckContext; +import io.ballerina.semtype.UniformTypeOps; + +/** + * List readonly specific methods operate on SubtypeData. + * + * @since 2.0.0 + */ +public class ListTypeRoOps extends CommonOps implements UniformTypeOps { + @Override + public boolean isEmpty(TypeCheckContext tc, SubtypeData t) { + throw new AssertionError(); + } +} diff --git a/semtypes/src/main/java/io/ballerina/semtype/typeops/MappingCommonOps.java b/semtypes/src/main/java/io/ballerina/semtype/typeops/MappingCommonOps.java new file mode 100644 index 000000000000..055ccb15133f --- /dev/null +++ b/semtypes/src/main/java/io/ballerina/semtype/typeops/MappingCommonOps.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.semtype.typeops; + +import io.ballerina.semtype.UniformTypeOps; + +// todo: use this to place common things between Ro and RW, if there are non; delete this. +/** + * Common mapping related methods operate on SubtypeData. + * + * @since 2.0.0 + */ +public abstract class MappingCommonOps extends CommonOps implements UniformTypeOps { + +} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BddIsEmptyPredicate.java b/semtypes/src/main/java/io/ballerina/semtype/typeops/MappingRWOps.java similarity index 51% rename from bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BddIsEmptyPredicate.java rename to semtypes/src/main/java/io/ballerina/semtype/typeops/MappingRWOps.java index d08297a81b06..0a6a69f9c51f 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/BddIsEmptyPredicate.java +++ b/semtypes/src/main/java/io/ballerina/semtype/typeops/MappingRWOps.java @@ -1,7 +1,7 @@ /* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * - * WSO2 LLC. licenses this file to you under the Apache License, + * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at @@ -15,23 +15,19 @@ * specific language governing permissions and limitations * under the License. */ +package io.ballerina.semtype.typeops; -package io.ballerina.runtime.api.types.semtype; +import io.ballerina.semtype.SubtypeData; +import io.ballerina.semtype.TypeCheckContext; /** - * Predicate to check if a BDD is empty. + * Mapping read/write specific methods operate on SubtypeData. * - * @since 2201.11.0 + * @since 2.0.0 */ -@FunctionalInterface -public interface BddIsEmptyPredicate { - - /** - * Check if the given BDD is empty. - * - * @param cx Type check context - * @param bdd BDD to check - * @return true if the BDD is empty, false otherwise - */ - boolean apply(Context cx, Bdd bdd); +public class MappingRWOps extends MappingCommonOps { + @Override + public boolean isEmpty(TypeCheckContext tc, SubtypeData t) { + throw new AssertionError(); + } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/ShapeSupplier.java b/semtypes/src/main/java/io/ballerina/semtype/typeops/MappingRoOps.java similarity index 52% rename from bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/ShapeSupplier.java rename to semtypes/src/main/java/io/ballerina/semtype/typeops/MappingRoOps.java index 999986483930..88b3ed961a9f 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/ShapeSupplier.java +++ b/semtypes/src/main/java/io/ballerina/semtype/typeops/MappingRoOps.java @@ -1,7 +1,7 @@ /* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * - * WSO2 LLC. licenses this file to you under the Apache License, + * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at @@ -14,23 +14,20 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. - * */ +package io.ballerina.semtype.typeops; -package io.ballerina.runtime.internal.types; - -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.SemType; - -import java.util.Optional; +import io.ballerina.semtype.SubtypeData; +import io.ballerina.semtype.TypeCheckContext; /** - * Function that can be used to get the shape of a value. + * Mapping readonly specific methods operate on SubtypeData. * - * @since 2201.11.0 + * @since 2.0.0 */ -@FunctionalInterface -public interface ShapeSupplier { - - Optional get(Context cx, Object object); +public class MappingRoOps extends MappingCommonOps { + @Override + public boolean isEmpty(TypeCheckContext tc, SubtypeData t) { + throw new AssertionError(); + } } diff --git a/semtypes/src/main/java/io/ballerina/types/Atom.java b/semtypes/src/main/java/io/ballerina/types/Atom.java deleted file mode 100644 index b1e053887d11..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/Atom.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -/** - * Represent the BDD atom. - * - * @since 2201.8.0 - */ -public interface Atom { - - /** - * Get the unique index of the atom. - */ - int index(); - - /** - * Get the kind of the atom. - */ - Kind kind(); - - /** - * This method returns a unique identifier for an Atom. - * The identifier is a combination of the atom's index and kind. - * - * @return AtomIdentifier - a record containing the index and kind of the atom. - */ - default AtomIdentifier getIdentifier() { - return new AtomIdentifier(index(), kind()); - } - - record AtomIdentifier(int index, Kind kind) { - } - - enum Kind { - LIST_ATOM, - FUNCTION_ATOM, - MAPPING_ATOM, - CELL_ATOM, - XML_ATOM, - DISTINCT_ATOM - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/BasicSubtype.java b/semtypes/src/main/java/io/ballerina/types/BasicSubtype.java deleted file mode 100644 index 3fd190893077..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/BasicSubtype.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -/** - * BasicSubtype node. - * - * @since 2201.8.0 - */ -public class BasicSubtype { - public final BasicTypeCode basicTypeCode; - public final ProperSubtypeData subtypeData; - - private BasicSubtype(BasicTypeCode basicTypeCode, ProperSubtypeData properSubtypeData) { - this.basicTypeCode = basicTypeCode; - this.subtypeData = properSubtypeData; - } - - public static BasicSubtype from(BasicTypeCode typeCode, ProperSubtypeData data) { - return new BasicSubtype(typeCode, data); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/BasicTypeBitSet.java b/semtypes/src/main/java/io/ballerina/types/BasicTypeBitSet.java deleted file mode 100644 index 3d14765053c0..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/BasicTypeBitSet.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -/** - * BasicTypeBitSet node. - * - * @since 2201.8.0 - */ -public final class BasicTypeBitSet implements SemType { - - public final int bitset; - - private BasicTypeBitSet(int bitset) { - this.bitset = bitset; - } - - public static BasicTypeBitSet from(int bitset) { - if (bitset == 0) { - return BitSetCache.ZERO; - } - if (Integer.bitCount(bitset) == 1) { - return BitSetCache.CACHE[Integer.numberOfTrailingZeros(bitset)]; - } - return new BasicTypeBitSet(bitset); - } - - public static BasicTypeBitSet union(BasicTypeBitSet t1, BasicTypeBitSet t2) { - return BasicTypeBitSet.from(t1.bitset | t2.bitset); - } - - @Override - public String toString() { - return PredefinedType.toString(this.bitset); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o instanceof BasicTypeBitSet b) { - return b.bitset == this.bitset; - } - return false; - } - - @Override - public int hashCode() { - return bitset; - } - - @Override - public int all() { - return bitset; - } - - private static final class BitSetCache { - - private static final int SIZE = 0x14; - private static final BasicTypeBitSet[] CACHE = new BasicTypeBitSet[SIZE]; - private static final BasicTypeBitSet ZERO = new BasicTypeBitSet(0); - - static { - for (int i = 0; i < SIZE; i++) { - CACHE[i] = new BasicTypeBitSet(1 << i); - } - } - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/BasicTypeCode.java b/semtypes/src/main/java/io/ballerina/types/BasicTypeCode.java deleted file mode 100644 index d614491fd6c8..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/BasicTypeCode.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.Map; - -/** - * Represent bit field that indicate which basic type a semType belongs to. - * - * @since 2201.10.0 - */ -public class BasicTypeCode { - // Inherently immutable - public static final BasicTypeCode BT_NIL = from(0x00); - public static final BasicTypeCode BT_BOOLEAN = from(0x01); - public static final BasicTypeCode BT_INT = from(0x02); - public static final BasicTypeCode BT_FLOAT = from(0x03); - public static final BasicTypeCode BT_DECIMAL = from(0x04); - public static final BasicTypeCode BT_STRING = from(0x05); - public static final BasicTypeCode BT_ERROR = from(0x06); - public static final BasicTypeCode BT_TYPEDESC = from(0x07); - public static final BasicTypeCode BT_HANDLE = from(0x08); - public static final BasicTypeCode BT_FUNCTION = from(0x09); - public static final BasicTypeCode BT_REGEXP = from(0x0A); - - // Inherently mutable - public static final BasicTypeCode BT_FUTURE = from(0x0B); - public static final BasicTypeCode BT_STREAM = from(0x0C); - - // Selectively immutable - public static final BasicTypeCode BT_LIST = from(0x0D); - public static final BasicTypeCode BT_MAPPING = from(0x0E); - public static final BasicTypeCode BT_TABLE = from(0x0F); - public static final BasicTypeCode BT_XML = from(0x10); - public static final BasicTypeCode BT_OBJECT = from(0x11); - - // Non-val - public static final BasicTypeCode BT_CELL = from(0x12); - public static final BasicTypeCode BT_UNDEF = from(0x13); - - // Helper bit fields (does not represent basic type tag) - static final int VT_COUNT = BT_OBJECT.code + 1; - static final int VT_MASK = (1 << VT_COUNT) - 1; - - static final int VT_COUNT_INHERENTLY_IMMUTABLE = BT_FUTURE.code; - public static final int VT_INHERENTLY_IMMUTABLE = (1 << VT_COUNT_INHERENTLY_IMMUTABLE) - 1; - - public final int code; - - // There is an integer for each basic type. - private BasicTypeCode(int code) { - this.code = code; - } - - public static BasicTypeCode from(int code) { - // todo: Add validation - return new BasicTypeCode(code); - } - - // Only used for .toString() method to aid debugging. - private static Map fieldNames = new HashMap<>(); - static { - for (Field field : BasicTypeCode.class.getDeclaredFields()) { - if (field.getType() == BasicTypeCode.class) { - try { - BasicTypeCode o = (BasicTypeCode) field.get(null); - fieldNames.put(o.code, field.getName()); - } catch (IllegalAccessException e) { - throw new IllegalStateException(); - } - } - } - } - - @Override - public String toString() { - return fieldNames.get(this.code); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/BasicTypeOps.java b/semtypes/src/main/java/io/ballerina/types/BasicTypeOps.java deleted file mode 100644 index 71dcaf7b01fe..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/BasicTypeOps.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -/** - * Interface representing type operations on basic types. - * - * @since 2201.8.0 - */ -public interface BasicTypeOps extends IsEmptyOp, CommonBasicTypeOps { -} diff --git a/semtypes/src/main/java/io/ballerina/types/BddMemo.java b/semtypes/src/main/java/io/ballerina/types/BddMemo.java deleted file mode 100644 index c9b82a59ac3b..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/BddMemo.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -/** - * Represent BddMomo type used for memoization. - * - * @since 2201.8.0 - */ -public class BddMemo { - - protected MemoStatus isEmpty; - - public BddMemo() { - this.isEmpty = MemoStatus.NULL; - } - - public void setIsEmpty(boolean isEmpty) { - this.isEmpty = isEmpty ? MemoStatus.TRUE : MemoStatus.FALSE; - } - - public boolean isEmpty() { - return this.isEmpty == MemoStatus.TRUE; - } - /** - * Represent if BddMemo is null or not. - * - * @since 3.0.0 - */ - public enum MemoStatus { - LOOP, TRUE, FALSE, CYCLIC, PROVISIONAL, NULL; - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/BddPath.java b/semtypes/src/main/java/io/ballerina/types/BddPath.java deleted file mode 100644 index 4eceb36065f0..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/BddPath.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import io.ballerina.types.subtypedata.BddAllOrNothing; -import io.ballerina.types.subtypedata.BddNode; -import io.ballerina.types.typeops.BddCommonOps; - -import java.util.ArrayList; -import java.util.List; - -/** - * Represents path from root to leaf (ending with true). - * bdd gets the Bdd for this path - * - * @since 2201.8.0 - */ -public class BddPath { - Bdd bdd; - List pos; - List neg; - - private BddPath(BddPath bddPath) { - this.bdd = bddPath.bdd; - this.pos = new ArrayList<>(bddPath.pos); // pos: path.pos.clone() - this.neg = new ArrayList<>(bddPath.neg); // pos: path.pos.clone() - } - - public BddPath() { - this.bdd = BddAllOrNothing.bddAll(); - this.pos = new ArrayList<>(); - this.neg = new ArrayList<>(); - } - - public static void bddPaths(Bdd b, List paths, BddPath accum) { - if (b instanceof BddAllOrNothing allOrNothing) { - if (allOrNothing.isAll()) { - paths.add(accum); - } - } else { - BddPath left = bddPathClone(accum); - BddPath right = bddPathClone(accum); - BddNode bn = (BddNode) b; - left.pos.add(bn.atom()); - left.bdd = BddCommonOps.bddIntersect(left.bdd, BddCommonOps.bddAtom(bn.atom())); - bddPaths(bn.left(), paths, left); - bddPaths(bn.middle(), paths, accum); - right.neg.add(bn.atom()); - right.bdd = BddCommonOps.bddDiff(right.bdd, BddCommonOps.bddAtom(bn.atom())); - bddPaths(bn.right(), paths, right); - } - } - - private static BddPath bddPathClone(BddPath path) { - return new BddPath(path); - } - - public static BddPath from() { - return new BddPath(); - } - -} diff --git a/semtypes/src/main/java/io/ballerina/types/CellAtomicType.java b/semtypes/src/main/java/io/ballerina/types/CellAtomicType.java deleted file mode 100644 index a17744fa2625..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/CellAtomicType.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -/** - * CellAtomicType node. - * - * @param ty Type "wrapped" by this cell - * @param mut Mutability of the cell - * @since 2201.10.0 - */ -public record CellAtomicType(SemType ty, CellMutability mut) implements AtomicType { - - public CellAtomicType { - assert ty != null; - } - - public static CellAtomicType from(SemType ty, CellMutability mut) { - assert ty != null; - // TODO: return final fields where applicable - return new CellAtomicType(ty, mut); - } - - @Override - public Atom.Kind atomKind() { - return Atom.Kind.CELL_ATOM; - } - - public enum CellMutability { - CELL_MUT_NONE, - CELL_MUT_LIMITED, - CELL_MUT_UNLIMITED - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/CellSemType.java b/semtypes/src/main/java/io/ballerina/types/CellSemType.java deleted file mode 100644 index d799bfcd193f..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/CellSemType.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -/** - * This is to represent a SemType belonging to cell basic type. - * - * @since 2201.10.0 - */ -public class CellSemType implements ComplexSemType { - - // Holding on to the single value instead of the array with a single value is more memory efficient. However, if - // this start to cause problems in the future, we can change this to an array. - private final ProperSubtypeData subtypeData; - - private CellSemType(ProperSubtypeData[] subtypeDataList) { - assert subtypeDataList.length == 1; - this.subtypeData = subtypeDataList[0]; - } - - public static CellSemType from(ProperSubtypeData[] subtypeDataList) { - return new CellSemType(subtypeDataList); - } - - @Override - public String toString() { - return "CellSemType{" + subtypeDataList()[0] + '}'; - } - - @Override - public int all() { - return 0; - } - - @Override - public int some() { - return PredefinedType.CELL.bitset; - } - - @Override - public ProperSubtypeData[] subtypeDataList() { - return new ProperSubtypeData[]{subtypeData}; - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/CombinedRange.java b/semtypes/src/main/java/io/ballerina/types/CombinedRange.java deleted file mode 100644 index f097004b2220..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/CombinedRange.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import io.ballerina.types.subtypedata.Range; - -/** - * Represents a combined range. - * - * @param range range - * @param i1 i1 - * @param i2 i2 - * @since 2201.11.0 - */ -public record CombinedRange(Range range, Long i1, Long i2) { - - public static CombinedRange from(Range range, Long i1, Long i2) { - return new CombinedRange(range, i1, i2); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/Common.java b/semtypes/src/main/java/io/ballerina/types/Common.java deleted file mode 100644 index 0a253308c48e..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/Common.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import io.ballerina.types.subtypedata.AllOrNothingSubtype; -import io.ballerina.types.subtypedata.BddAllOrNothing; -import io.ballerina.types.subtypedata.BddNode; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.BiFunction; - -import static io.ballerina.types.Conjunction.and; -import static io.ballerina.types.typeops.BddCommonOps.bddComplement; -import static io.ballerina.types.typeops.BddCommonOps.bddDiff; -import static io.ballerina.types.typeops.BddCommonOps.bddIntersect; -import static io.ballerina.types.typeops.BddCommonOps.bddUnion; - -/** - * Code common to implementation of multiple basic types. - * - * @since 2201.8.0 - */ -public class Common { - - // [from nballerina] A Bdd represents a disjunction of conjunctions of atoms, where each atom is either positive or - // negative (negated). Each path from the root to a leaf that is true represents one of the conjunctions - // We walk the tree, accumulating the positive and negative conjunctions for a path as we go. - // When we get to a leaf that is true, we apply the predicate to the accumulated conjunctions. - - public static boolean bddEvery(Context cx, - Bdd b, - Conjunction pos, - Conjunction neg, - BddPredicate predicate) { - if (b instanceof BddAllOrNothing allOrNothing) { - return !allOrNothing.isAll() || predicate.apply(cx, pos, neg); - } else { - BddNode bn = (BddNode) b; - return bddEvery(cx, bn.left(), and(bn.atom(), pos), neg, predicate) - && bddEvery(cx, bn.middle(), pos, neg, predicate) - && bddEvery(cx, bn.right(), pos, and(bn.atom(), neg), predicate); - } - } - - public static boolean bddEveryPositive(Context cx, Bdd b, Conjunction pos, Conjunction neg, - BddPredicate predicate) { - if (b instanceof BddAllOrNothing allOrNothing) { - return !allOrNothing.isAll() || predicate.apply(cx, pos, neg); - } else { - BddNode bn = (BddNode) b; - return bddEveryPositive(cx, bn.left(), andIfPositive(bn.atom(), pos), neg, predicate) - && bddEveryPositive(cx, bn.middle(), pos, neg, predicate) - && bddEveryPositive(cx, bn.right(), pos, andIfPositive(bn.atom(), neg), predicate); - } - } - - public static Conjunction andIfPositive(Atom atom, Conjunction next) { - if (atom instanceof RecAtom recAtom && recAtom.index < 0) { - return next; - } - return and(atom, next); - } - - public static boolean bddPosMaybeEmpty(Bdd b) { - if (b instanceof BddAllOrNothing allOrNothing) { - return allOrNothing.isAll(); - } else { - BddNode bddNode = (BddNode) b; - return bddPosMaybeEmpty(bddNode.middle()) || bddPosMaybeEmpty(bddNode.right()); - } - } - - public static SubtypeData bddSubtypeUnion(SubtypeData t1, SubtypeData t2) { - return bddUnion((Bdd) t1, (Bdd) t2); - } - - public static SubtypeData bddSubtypeIntersect(SubtypeData t1, SubtypeData t2) { - return bddIntersect((Bdd) t1, (Bdd) t2); - } - - public static SubtypeData bddSubtypeDiff(SubtypeData t1, SubtypeData t2) { - return bddDiff((Bdd) t1, (Bdd) t2); - } - - public static SubtypeData bddSubtypeComplement(SubtypeData t) { - return bddComplement((Bdd) t); - } - - public static SemType[] shallowCopyTypes(SemType[] v) { - return Arrays.copyOf(v, v.length); - } - - public static CellSemType[] shallowCopyCellTypes(CellSemType[] v) { - return shallowCopyCellTypes(v, v.length); - } - - public static CellSemType[] shallowCopyCellTypes(CellSemType[] v, int newLength) { - return Arrays.copyOf(v, newLength); - } - - public static List shallowCopyTypes(List v) { - return new ArrayList<>(v); - } - - public static String[] shallowCopyStrings(String[] v, int newLength) { - return Arrays.copyOf(v, newLength); - } - - public static boolean notIsEmpty(Context cx, SubtypeData d) { - return false; - } - - // Returns whether s1.codePoints < s2.codePoints - public static boolean codePointCompare(String s1, String s2) { - if (s1.equals(s2)) { - return false; - } - int len1 = s1.length(); - int len2 = s2.length(); - if (len1 < len2 && s2.substring(0, len1).equals(s1)) { - return true; - } - int cpCount1 = s1.codePointCount(0, len1); - int cpCount2 = s2.codePointCount(0, len2); - for (int cp = 0; cp < cpCount1 && cp < cpCount2;) { - int codepoint1 = s1.codePointAt(cp); - int codepoint2 = s2.codePointAt(cp); - if (codepoint1 == codepoint2) { - cp++; - continue; - } - return codepoint1 < codepoint2; - } - return false; - } - - - public static boolean isNothingSubtype(SubtypeData data) { - return data instanceof AllOrNothingSubtype allOrNothingSubtype && allOrNothingSubtype.isNothingSubtype(); - } - - /** - * Function interface used for method references. - * - * @since 3.0.0 - */ - public interface BddPredicate { - boolean apply(Context cx, Conjunction posList, Conjunction negList); - } - - public interface BddIsEmptyPredicate extends BiFunction { - - } - - public static boolean memoSubtypeIsEmpty(Context cx, Map memoTable, - BddIsEmptyPredicate isEmptyPredicate, Bdd b) { - BddMemo mm = memoTable.get(b); - BddMemo m; - if (mm != null) { - BddMemo.MemoStatus res = mm.isEmpty; - switch (res) { - case CYCLIC: - // Since we define types inductively we consider these to be empty - return true; - case TRUE, FALSE: - // We know whether b is empty or not for certain - return res == BddMemo.MemoStatus.TRUE; - case NULL: - // this is same as not having memo so fall through - m = mm; - break; - case LOOP, PROVISIONAL: - // We've got a loop. - mm.isEmpty = BddMemo.MemoStatus.LOOP; - return true; - default: - throw new AssertionError("Unexpected memo status: " + res); - } - } else { - m = new BddMemo(); - memoTable.put(b, m); - } - m.isEmpty = BddMemo.MemoStatus.PROVISIONAL; - int initStackDepth = cx.memoStack.size(); - cx.memoStack.add(m); - boolean isEmpty = isEmptyPredicate.apply(cx, b); - boolean isLoop = m.isEmpty == BddMemo.MemoStatus.LOOP; - if (!isEmpty || initStackDepth == 0) { - for (int i = initStackDepth + 1; i < cx.memoStack.size(); i++) { - BddMemo.MemoStatus memoStatus = cx.memoStack.get(i).isEmpty; - if (Objects.requireNonNull(memoStatus) == BddMemo.MemoStatus.PROVISIONAL || - memoStatus == BddMemo.MemoStatus.LOOP || memoStatus == BddMemo.MemoStatus.CYCLIC) { - cx.memoStack.get(i).isEmpty = isEmpty ? BddMemo.MemoStatus.TRUE : BddMemo.MemoStatus.NULL; - } - } - while (cx.memoStack.size() > initStackDepth) { - cx.memoStack.subList(initStackDepth, cx.memoStack.size()).clear(); - } - // The only way that we have found that this can be empty is by going through a loop. - // This means that the shapes in the type would all be infinite. - // But we define types inductively, which means we only consider finite shapes. - if (isLoop && isEmpty) { - m.isEmpty = BddMemo.MemoStatus.CYCLIC; - } else { - m.isEmpty = isEmpty ? BddMemo.MemoStatus.TRUE : BddMemo.MemoStatus.FALSE; - } - } - return isEmpty; - } - - public static boolean isAllSubtype(SubtypeData d) { - if (d instanceof AllOrNothingSubtype allOrNothingSubtype) { - return allOrNothingSubtype.isAllSubtype(); - } - return false; - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/ComplexSemType.java b/semtypes/src/main/java/io/ballerina/types/ComplexSemType.java deleted file mode 100644 index 9a72477dad31..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/ComplexSemType.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import static io.ballerina.types.BasicTypeCode.BT_CELL; - -/** - * ComplexSemType node. - * - * @since 2201.8.0 - */ -public interface ComplexSemType extends SemType { - - static ComplexSemType createComplexSemType(int allBitset, BasicSubtype... subtypeList) { - return createComplexSemType(allBitset, Arrays.asList(subtypeList)); - } - - static ComplexSemType createComplexSemType(int allBitset, int someBitset, ProperSubtypeData[] subtypeData) { - if (allBitset == 0 && someBitset == (1 << BT_CELL.code)) { - return CellSemType.from(subtypeData); - } - return new ComplexSemTypeImpl(allBitset, someBitset, subtypeData); - } - - static ComplexSemType createComplexSemType(int allBitset, List subtypeList) { - int some = 0; - ArrayList dataList = new ArrayList<>(); - for (BasicSubtype basicSubtype : subtypeList) { - dataList.add(basicSubtype.subtypeData); - int c = basicSubtype.basicTypeCode.code; - some |= 1 << c; - } - return createComplexSemType(allBitset, some, dataList.toArray(ProperSubtypeData[]::new)); - } - - int all(); - - int some(); - - ProperSubtypeData[] subtypeDataList(); -} diff --git a/semtypes/src/main/java/io/ballerina/types/ComplexSemTypeImpl.java b/semtypes/src/main/java/io/ballerina/types/ComplexSemTypeImpl.java deleted file mode 100644 index d280d98a7081..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/ComplexSemTypeImpl.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import java.util.Arrays; -import java.util.Objects; - -/** - * @param all all & (1 << c) is non-zero iff this type contains all the basic type with code c - * @param some some & (1 << c) is non-zero iff this type contains some but not all the basic type with code c - * @param subtypeDataList There is one member of subtypes for each bit set in some. Ordered in increasing order of - * BasicTypeCode - */ -record ComplexSemTypeImpl(int all, int some, ProperSubtypeData[] subtypeDataList) implements ComplexSemType { - - @Override - public String toString() { - return "ComplexSemType{all=" + all + PredefinedType.toString(all) + ", some=" + some() + - PredefinedType.toString(some) + ", subtypeDataList=" + Arrays.toString(subtypeDataList()) + '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof ComplexSemType other)) { - return false; - } - return Objects.equals(all(), other.all()) && - Objects.equals(some(), other.some()) && - Arrays.equals(subtypeDataList(), other.subtypeDataList()); - } - - @Override - public int hashCode() { - return Objects.hash(all(), some(), Arrays.hashCode(subtypeDataList())); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/Conjunction.java b/semtypes/src/main/java/io/ballerina/types/Conjunction.java deleted file mode 100644 index 84b524c1e7ef..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/Conjunction.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -/** - * Represents the Conjunction record type. - * - * @since 2201.8.0 - */ -public class Conjunction { - public Atom atom; - public Conjunction next; - - private Conjunction(Atom atom, Conjunction next) { - this.atom = atom; - this.next = next; - } - - public static Conjunction and(Atom atom, Conjunction next) { - return new Conjunction(atom, next); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/Context.java b/semtypes/src/main/java/io/ballerina/types/Context.java deleted file mode 100644 index d0da307ccf5c..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/Context.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * TypeCheckContext node. - * - * @since 2201.8.0 - */ -public final class Context { - - public final Env env; - public final Map functionMemo = new HashMap<>(); - public final Map listMemo = new HashMap<>(); - public final Map mappingMemo = new HashMap<>(); - public final Map comparableMemo = new HashMap<>(); - - // Contains all BddMemo entries with isEmpty == PROVISIONAL - final List memoStack = new ArrayList<>(); - - private static volatile Context instance; - - SemType anydataMemo; - SemType jsonMemo; - SemType cloneableMemo; - SemType isolatedObjectMemo; - SemType serviceObjectMemo; - - private Context(Env env) { - this.env = env; - } - - public static Context from(Env env) { - if (instance == null) { - synchronized (Context.class) { - if (instance == null) { - instance = new Context(env); - } - } - } - if (instance.env == env) { - return instance; - } else { - instance = new Context(env); - } - return instance; - } - - public ListAtomicType listAtomType(Atom atom) { - if (atom instanceof RecAtom recAtom) { - return this.env.getRecListAtomType(recAtom); - } else { - return (ListAtomicType) ((TypeAtom) atom).atomicType(); - } - } - - public MappingAtomicType mappingAtomType(Atom atom) { - if (atom instanceof RecAtom recAtom) { - return this.env.getRecMappingAtomType(recAtom); - } else { - return (MappingAtomicType) ((TypeAtom) atom).atomicType(); - } - } - - public FunctionAtomicType functionAtomType(Atom atom) { - if (atom instanceof RecAtom recAtom) { - return this.env.getRecFunctionAtomType(recAtom); - } else { - return (FunctionAtomicType) ((TypeAtom) atom).atomicType(); - } - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/Core.java b/semtypes/src/main/java/io/ballerina/types/Core.java deleted file mode 100644 index 82ab6e91c296..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/Core.java +++ /dev/null @@ -1,1001 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import io.ballerina.types.definition.ListDefinition; -import io.ballerina.types.definition.MappingDefinition; -import io.ballerina.types.definition.ObjectDefinition; -import io.ballerina.types.definition.ObjectQualifiers; -import io.ballerina.types.subtypedata.AllOrNothingSubtype; -import io.ballerina.types.subtypedata.BddAllOrNothing; -import io.ballerina.types.subtypedata.BddNode; -import io.ballerina.types.subtypedata.BddNodeImpl; -import io.ballerina.types.subtypedata.BddNodeSimple; -import io.ballerina.types.subtypedata.BooleanSubtype; -import io.ballerina.types.subtypedata.DecimalSubtype; -import io.ballerina.types.subtypedata.FloatSubtype; -import io.ballerina.types.subtypedata.IntSubtype; -import io.ballerina.types.subtypedata.Range; -import io.ballerina.types.subtypedata.StringSubtype; -import io.ballerina.types.subtypedata.TableSubtype; -import io.ballerina.types.typeops.SubtypePair; -import io.ballerina.types.typeops.SubtypePairs; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Optional; - -import static io.ballerina.types.BasicTypeCode.BT_BOOLEAN; -import static io.ballerina.types.BasicTypeCode.BT_CELL; -import static io.ballerina.types.BasicTypeCode.BT_DECIMAL; -import static io.ballerina.types.BasicTypeCode.BT_FLOAT; -import static io.ballerina.types.BasicTypeCode.BT_INT; -import static io.ballerina.types.BasicTypeCode.BT_LIST; -import static io.ballerina.types.BasicTypeCode.BT_MAPPING; -import static io.ballerina.types.BasicTypeCode.BT_NIL; -import static io.ballerina.types.BasicTypeCode.BT_STRING; -import static io.ballerina.types.BasicTypeCode.VT_MASK; -import static io.ballerina.types.CellAtomicType.CellMutability.CELL_MUT_NONE; -import static io.ballerina.types.Common.isNothingSubtype; -import static io.ballerina.types.PredefinedType.CELL_ATOMIC_VAL; -import static io.ballerina.types.PredefinedType.INNER; -import static io.ballerina.types.PredefinedType.LIST; -import static io.ballerina.types.PredefinedType.LIST_ATOMIC_INNER; -import static io.ballerina.types.PredefinedType.MAPPING; -import static io.ballerina.types.PredefinedType.MAPPING_ATOMIC_INNER; -import static io.ballerina.types.PredefinedType.NEVER; -import static io.ballerina.types.PredefinedType.REGEXP; -import static io.ballerina.types.PredefinedType.SIMPLE_OR_STRING; -import static io.ballerina.types.PredefinedType.UNDEF; -import static io.ballerina.types.PredefinedType.VAL; -import static io.ballerina.types.PredefinedType.VAL_READONLY; -import static io.ballerina.types.PredefinedType.XML; -import static io.ballerina.types.subtypedata.CellSubtype.cellContaining; -import static io.ballerina.types.typeops.CellOps.intersectCellAtomicType; -import static io.ballerina.types.typeops.ListOps.bddListMemberTypeInnerVal; -import static io.ballerina.types.typeops.MappingOps.bddMappingMemberTypeInner; -import static java.lang.Long.MAX_VALUE; -import static java.lang.Long.MIN_VALUE; - -/** - * Contain functions defined in `core.bal` file. - * - * @since 2201.8.0 - */ -public final class Core { - - public static CellAtomicType cellAtomType(Atom atom) { - return (CellAtomicType) ((TypeAtom) atom).atomicType(); - } - - public static SemType diff(SemType t1, SemType t2) { - int all1, all2, some1, some2; - if (t1 instanceof BasicTypeBitSet b1) { - if (t2 instanceof BasicTypeBitSet b2) { - return BasicTypeBitSet.from(b1.bitset & ~b2.bitset); - } else { - if (b1.bitset == 0) { - return t1; - } - ComplexSemType c2 = (ComplexSemType) t2; - all2 = c2.all(); - some2 = c2.some(); - } - all1 = b1.bitset; - some1 = 0; - } else { - ComplexSemType c1 = (ComplexSemType) t1; - all1 = c1.all(); - some1 = c1.some(); - if (t2 instanceof BasicTypeBitSet b2) { - if (b2.bitset == BasicTypeCode.VT_MASK) { - return BasicTypeBitSet.from(0); - } - all2 = b2.bitset; - some2 = 0; - } else { - ComplexSemType c2 = (ComplexSemType) t2; - all2 = c2.all(); - some2 = c2.some(); - } - } - BasicTypeBitSet all = BasicTypeBitSet.from(all1 & ~(all2 | some2)); - - int someBitset = (all1 | some1) & ~all2; - someBitset = someBitset & ~all.bitset; - BasicTypeBitSet some = BasicTypeBitSet.from(someBitset); - - if (some.bitset == 0) { - return PredefinedType.basicTypeUnion(all.bitset); - } - List subtypes = new ArrayList<>(); - - for (SubtypePair pair : new SubtypePairs(t1, t2, some)) { - BasicTypeCode code = pair.basicTypeCode; - SubtypeData data1 = pair.subtypeData1; - SubtypeData data2 = pair.subtypeData2; - SubtypeData data; - if (data1 == null) { - data = OpsTable.OPS[code.code].complement(data2); - } else if (data2 == null) { - data = data1; - } else { - data = OpsTable.OPS[code.code].diff(data1, data2); - } - if (!(data instanceof AllOrNothingSubtype allOrNothingSubtype)) { - subtypes.add(BasicSubtype.from(code, (ProperSubtypeData) data)); - } else if (allOrNothingSubtype.isAllSubtype()) { - int c = code.code; - all = BasicTypeBitSet.from(all.bitset | (1 << c)); - } - // No need to consider `data == false` case. The `some` variable above is not used to create the SemType - } - if (subtypes.isEmpty()) { - return all; - } - return ComplexSemType.createComplexSemType(all.bitset, subtypes); - } - - public static List unpackComplexSemType(ComplexSemType t) { - int some = t.some(); - List subtypeList = new ArrayList<>(); - for (ProperSubtypeData data : t.subtypeDataList()) { - BasicTypeCode code = BasicTypeCode.from(Integer.numberOfTrailingZeros(some)); - subtypeList.add(BasicSubtype.from(code, data)); - int c = code.code; - some ^= (1 << c); - } - return subtypeList; - } - - public static SubtypeData getComplexSubtypeData(ComplexSemType t, BasicTypeCode code) { - int c = code.code; - c = 1 << c; - if ((t.all() & c) != 0) { - return AllOrNothingSubtype.createAll(); - } - if ((t.some() & c) == 0) { - return AllOrNothingSubtype.createNothing(); - } - int loBits = t.some() & (c - 1); - return t.subtypeDataList()[loBits == 0 ? 0 : Integer.bitCount(loBits)]; - } - - public static SemType union(SemType t1, SemType t2) { - assert t1 != null && t2 != null; - int all1, all2, some1, some2; - - if (t1 instanceof BasicTypeBitSet b1) { - if (t2 instanceof BasicTypeBitSet b2) { - return BasicTypeBitSet.from(b1.bitset | b2.bitset); - } else { - ComplexSemType complexT2 = (ComplexSemType) t2; - all2 = complexT2.all(); - some2 = complexT2.some(); - } - all1 = b1.bitset; - some1 = 0; - } else { - ComplexSemType complexT1 = (ComplexSemType) t1; - all1 = complexT1.all(); - some1 = complexT1.some(); - if (t2 instanceof BasicTypeBitSet b2) { - all2 = b2.bitset; - some2 = 0; - } else { - ComplexSemType complexT2 = (ComplexSemType) t2; - all2 = complexT2.all(); - some2 = complexT2.some(); - } - } - - BasicTypeBitSet all = BasicTypeBitSet.from(all1 | all2); - BasicTypeBitSet some = BasicTypeBitSet.from((some1 | some2) & ~all.bitset); - if (some.bitset == 0) { - return PredefinedType.basicTypeUnion(all.bitset); - } - - List subtypes = new ArrayList<>(); - - for (SubtypePair pair : new SubtypePairs(t1, t2, some)) { - BasicTypeCode code = pair.basicTypeCode; - SubtypeData data1 = pair.subtypeData1; - SubtypeData data2 = pair.subtypeData2; - - SubtypeData data; - if (data1 == null) { - data = data2; // // [from original impl] if they are both null, something's gone wrong - } else if (data2 == null) { - data = data1; - } else { - data = OpsTable.OPS[code.code].union(data1, data2); - } - - if (data instanceof AllOrNothingSubtype allOrNothingSubtype && allOrNothingSubtype.isAllSubtype()) { - int c = code.code; - all = BasicTypeBitSet.from(all.bitset | 1 << c); - } else { - // data cannot be false since data1 and data2 are not both false - subtypes.add(BasicSubtype.from(code, (ProperSubtypeData) data)); - } - } - - if (subtypes.isEmpty()) { - return all; - } - return ComplexSemType.createComplexSemType(all.bitset, subtypes); - } - - public static SemType intersect(SemType t1, SemType t2) { - int all1, all2, some1, some2; - - if (t1 instanceof BasicTypeBitSet b1) { - if (t2 instanceof BasicTypeBitSet b2) { - return BasicTypeBitSet.from(b1.bitset & b2.bitset); - } else { - if (b1.bitset == 0) { - return t1; - } - if (b1.bitset == VT_MASK) { - return t2; - } - ComplexSemType complexT2 = (ComplexSemType) t2; - all2 = complexT2.all(); - some2 = complexT2.some(); - } - all1 = b1.bitset; - some1 = 0; - } else { - ComplexSemType complexT1 = (ComplexSemType) t1; - all1 = complexT1.all(); - some1 = complexT1.some(); - if (t2 instanceof BasicTypeBitSet b2) { - if (b2.bitset == 0) { - return t2; - } - if (b2.bitset == VT_MASK) { - return t1; - } - all2 = b2.bitset; - some2 = 0; - } else { - ComplexSemType complexT2 = (ComplexSemType) t2; - all2 = complexT2.all(); - some2 = complexT2.some(); - } - } - - BasicTypeBitSet all = BasicTypeBitSet.from(all1 & all2); - BasicTypeBitSet some = BasicTypeBitSet.from((some1 | all1) & (some2 | all2)); - some = BasicTypeBitSet.from(some.bitset & ~all.bitset); - if (some.bitset == 0) { - return PredefinedType.basicTypeUnion(all.bitset); - } - - List subtypes = new ArrayList<>(); - - for (SubtypePair pair : new SubtypePairs(t1, t2, some)) { - BasicTypeCode code = pair.basicTypeCode; - SubtypeData data1 = pair.subtypeData1; - SubtypeData data2 = pair.subtypeData2; - - SubtypeData data; - if (data1 == null) { - data = data2; - } else if (data2 == null) { - data = data1; - } else { - data = OpsTable.OPS[code.code].intersect(data1, data2); - } - if (!(data instanceof AllOrNothingSubtype allOrNothingSubtype) || allOrNothingSubtype.isAllSubtype()) { - subtypes.add(BasicSubtype.from(code, (ProperSubtypeData) data)); - } - } - if (subtypes.isEmpty()) { - return all; - } - return ComplexSemType.createComplexSemType(all.bitset, subtypes); - } - - public static CellSemType intersectMemberSemTypes(Env env, CellSemType t1, CellSemType t2) { - CellAtomicType c1 = cellAtomicType(t1); - CellAtomicType c2 = cellAtomicType(t2); - assert c1 != null && c2 != null; - CellAtomicType atomicType = intersectCellAtomicType(c1, c2); - return cellContaining(env, atomicType.ty(), UNDEF.equals(atomicType.ty()) ? CELL_MUT_NONE : atomicType.mut()); - } - - public static SemType complement(SemType t) { - return diff(VAL, t); - } - - public static boolean isNever(SemType t) { - return (t instanceof BasicTypeBitSet b) && b.bitset == 0; - } - - public static boolean isEmpty(Context cx, SemType t) { - assert t != null && cx != null; - if (t instanceof BasicTypeBitSet b) { - return b.bitset == 0; - } else { - ComplexSemType ct = (ComplexSemType) t; - if (ct.all() != 0) { - // includes all of, one or more basic types - return false; - } - for (var st : unpackComplexSemType(ct)) { - if (!OpsTable.OPS[st.basicTypeCode.code].isEmpty(cx, st.subtypeData)) { - return false; - } - } - return true; - } - } - - public static boolean isSubtype(Context cx, SemType t1, SemType t2) { - return isEmpty(cx, diff(t1, t2)); - } - - public static boolean isSubtypeSimple(SemType t1, BasicTypeBitSet t2) { - int bits; - if (t1 instanceof BasicTypeBitSet b1) { - bits = b1.bitset; - } else { - ComplexSemType complexT1 = (ComplexSemType) t1; - bits = complexT1.all() | complexT1.some(); - } - return (bits & ~t2.bitset) == 0; - } - - public static boolean isSameType(Context context, SemType t1, SemType t2) { - return isSubtype(context, t1, t2) && isSubtype(context, t2, t1); - } - - public static BasicTypeBitSet widenToBasicTypes(SemType t) { - if (t instanceof BasicTypeBitSet b) { - return b; - } else { - ComplexSemType complexSemType = (ComplexSemType) t; - return BasicTypeBitSet.from(complexSemType.all() | complexSemType.some()); - } - } - - // If t is a non-empty subtype of a built-in unsigned int subtype (Unsigned8/16/32), - // then return the smallest such subtype. Otherwise, return t. - public static SemType wideUnsigned(SemType t) { - if (t instanceof BasicTypeBitSet) { - return t; - } else { - if (!isSubtypeSimple(t, PredefinedType.INT)) { - return t; - } - SubtypeData data = IntSubtype.intSubtypeWidenUnsigned(subtypeData(t, BT_INT)); - if (data instanceof AllOrNothingSubtype) { - return PredefinedType.INT; - } else { - return PredefinedType.basicSubtype(BT_INT, (ProperSubtypeData) data); - } - } - } - - public static SubtypeData booleanSubtype(SemType t) { - return subtypeData(t, BT_BOOLEAN); - } - - // Describes the subtype of int included in the type: true/false mean all or none of string - public static SubtypeData intSubtype(SemType t) { - return subtypeData(t, BT_INT); - } - - public static SubtypeData floatSubtype(SemType t) { - return subtypeData(t, BT_FLOAT); - } - - public static SubtypeData decimalSubtype(SemType t) { - return subtypeData(t, BT_DECIMAL); - } - - // Describes the subtype of string included in the type: true/false mean all or none of string - public static SubtypeData stringSubtype(SemType t) { - return subtypeData(t, BT_STRING); - } - - // This computes the spec operation called "member type of K in T", - // for the case when T is a subtype of list, and K is either `int` or a singleton int. - // This is what Castagna calls projection. - // We will extend this to allow `key` to be a SemType, which will turn into an IntSubtype. - // If `t` is not a list, NEVER is returned - public static SemType listMemberTypeInnerVal(Context cx, SemType t, SemType k) { - if (t instanceof BasicTypeBitSet b) { - return (b.bitset & LIST.bitset) != 0 ? VAL : NEVER; - } else { - SubtypeData keyData = intSubtype(k); - if (isNothingSubtype(keyData)) { - return NEVER; - } - return bddListMemberTypeInnerVal(cx, (Bdd) getComplexSubtypeData((ComplexSemType) t, BT_LIST), keyData, - VAL); - } - } - - static final ListMemberTypes LIST_MEMBER_TYPES_ALL = ListMemberTypes.from( - List.of(Range.from(0, MAX_VALUE)), - List.of(VAL) - ); - - static final ListMemberTypes LIST_MEMBER_TYPES_NONE = ListMemberTypes.from(List.of(), List.of()); - - public static ListMemberTypes listAllMemberTypesInner(Context cx, SemType t) { - if (t instanceof BasicTypeBitSet b) { - return (b.bitset & LIST.bitset) != 0 ? LIST_MEMBER_TYPES_ALL : LIST_MEMBER_TYPES_NONE; - } - - ComplexSemType ct = (ComplexSemType) t; - List ranges = new ArrayList<>(); - List types = new ArrayList<>(); - - - Range[] allRanges = bddListAllRanges(cx, (Bdd) getComplexSubtypeData(ct, BT_LIST), new Range[]{}); - for (Range r : allRanges) { - SemType m = listMemberTypeInnerVal(cx, t, IntSubtype.intConst(r.min)); - if (!NEVER.equals(m)) { - ranges.add(r); - types.add(m); - } - } - return ListMemberTypes.from(ranges, types); - } - - static Range[] bddListAllRanges(Context cx, Bdd b, Range[] accum) { - if (b instanceof BddAllOrNothing allOrNothing) { - return allOrNothing.isAll() ? accum : new Range[0]; - } else { - BddNode bddNode = (BddNode) b; - ListMemberTypes listMemberTypes = listAtomicTypeAllMemberTypesInnerVal(cx.listAtomType(bddNode.atom())); - return distinctRanges(bddListAllRanges(cx, bddNode.left(), - distinctRanges(listMemberTypes.ranges().toArray(Range[]::new), accum)), - distinctRanges(bddListAllRanges(cx, bddNode.middle(), accum), - bddListAllRanges(cx, bddNode.right(), accum))); - } - } - - static Range[] distinctRanges(Range[] range1, Range[] range2) { - CombinedRange[] combined = combineRanges(range1, range2); - Range[] range = new Range[combined.length]; - for (int i = 0; i < combined.length; i++) { - range[i] = combined[i].range(); - } - return range; - } - - // If [r, i1, i2] is included in the result, then - // at least one of i1 and i2 are not () - // if i1 is not (), then r is completely included in ranges1[i1] - // if i2 is not (), then r is completely included in ranges2[i2] - // The ranges in the result are ordered and non-overlapping. - public static CombinedRange[] combineRanges(Range[] ranges1, Range[] ranges2) { - List combined = new ArrayList<>(); - int i1 = 0; - int i2 = 0; - int len1 = ranges1.length; - int len2 = ranges2.length; - long cur = MIN_VALUE; - // This iterates over the boundaries between ranges - while (true) { - while (i1 < len1 && cur > ranges1[i1].max) { - i1 += 1; - } - while (i2 < len2 && cur > ranges2[i2].max) { - i2 += 1; - } - - Long next = null; - if (i1 < len1) { - next = nextBoundary(cur, ranges1[i1], next); - } - if (i2 < len2) { - next = nextBoundary(cur, ranges2[i2], next); - } - long max = next == null ? MAX_VALUE : next - 1; - Long in1 = null; - if (i1 < len1) { - Range r = ranges1[i1]; - if (cur >= r.min && max <= r.max) { - in1 = (long) i1; - } - } - Long in2 = null; - if (i2 < len2) { - Range r = ranges2[i2]; - if (cur >= r.min && max <= r.max) { - in2 = (long) i2; - } - } - if (in1 != null || in2 != null) { - combined.add(CombinedRange.from(Range.from(cur, max), in1, in2)); - } - if (next == null) { - break; - } - cur = next; - } - return combined.toArray(CombinedRange[]::new); - } - - // Helper function for combineRanges - // Return smallest range boundary that is > cur and <= next - // null represents int:MAX_VALUE + 1 - static Long nextBoundary(long cur, Range r, Long next) { - if ((r.min > cur) && (next == null || r.min < next)) { - return r.min; - } - if (r.max != MAX_VALUE) { - long i = r.max + 1; - if (i > cur && (next == null || i < next)) { - return i; - } - } - return next; - } - - public static ListMemberTypes listAtomicTypeAllMemberTypesInnerVal(ListAtomicType atomicType) { - List ranges = new ArrayList<>(); - List types = new ArrayList<>(); - - List cellInitial = atomicType.members().initial(); - int initialLength = cellInitial.size(); - - List initial = new ArrayList<>(initialLength); - for (CellSemType c : cellInitial) { - initial.add(cellInnerVal(c)); - } - - int fixedLength = atomicType.members().fixedLength(); - if (initialLength != 0) { - types.addAll(initial); - for (int i = 0; i < initialLength; i++) { - ranges.add(Range.from(i, i)); - } - if (initialLength < fixedLength) { - ranges.set(initialLength - 1, Range.from(initialLength - 1, fixedLength - 1)); - } - } - - SemType rest = cellInnerVal(atomicType.rest()); - if (!Core.isNever(rest)) { - types.add(rest); - ranges.add(Range.from(fixedLength, MAX_VALUE)); - } - - return ListMemberTypes.from(ranges, types); - } - - public static MappingAtomicType mappingAtomicType(Context cx, SemType t) { - MappingAtomicType mappingAtomicInner = MAPPING_ATOMIC_INNER; - if (t instanceof BasicTypeBitSet b) { - return b.bitset == MAPPING.bitset ? mappingAtomicInner : null; - } else { - Env env = cx.env; - if (!isSubtypeSimple(t, MAPPING)) { - return null; - } - return bddMappingAtomicType(env, - (Bdd) getComplexSubtypeData((ComplexSemType) t, BT_MAPPING), - mappingAtomicInner); - } - } - - private static MappingAtomicType bddMappingAtomicType(Env env, Bdd bdd, MappingAtomicType top) { - if (bdd instanceof BddAllOrNothing allOrNothing) { - if (allOrNothing.isAll()) { - return top; - } - return null; - } - BddNode bddNode = (BddNode) bdd; - if (bddNode instanceof BddNodeSimple bddNodeSimple) { - return env.mappingAtomType(bddNodeSimple.atom()); - } - return null; - } - - public static SemType mappingMemberTypeInnerVal(Context cx, SemType t, SemType k) { - return diff(mappingMemberTypeInner(cx, t, k), UNDEF); - } - - // This computes the spec operation called "member type of K in T", - // for when T is a subtype of mapping, and K is either `string` or a singleton string. - // This is what Castagna calls projection. - public static SemType mappingMemberTypeInner(Context cx, SemType t, SemType k) { - if (t instanceof BasicTypeBitSet b) { - return (b.bitset & MAPPING.bitset) != 0 ? VAL : UNDEF; - } else { - SubtypeData keyData = stringSubtype(k); - if (isNothingSubtype(keyData)) { - return UNDEF; - } - return bddMappingMemberTypeInner(cx, (Bdd) getComplexSubtypeData((ComplexSemType) t, BT_MAPPING), keyData, - INNER); - } - } - - public static ListAtomicType listAtomicType(Context cx, SemType t) { - ListAtomicType listAtomicInner = LIST_ATOMIC_INNER; - if (t instanceof BasicTypeBitSet b) { - return b.bitset == LIST.bitset ? listAtomicInner : null; - } else { - Env env = cx.env; - if (!isSubtypeSimple(t, LIST)) { - return null; - } - return bddListAtomicType(env, - (Bdd) getComplexSubtypeData((ComplexSemType) t, BT_LIST), - listAtomicInner); - } - } - - private static ListAtomicType bddListAtomicType(Env env, Bdd bdd, ListAtomicType top) { - if (bdd instanceof BddAllOrNothing allOrNothing) { - if (allOrNothing.isAll()) { - return top; - } - return null; - } - BddNode bddNode = (BddNode) bdd; - if (bddNode instanceof BddNodeSimple bddNodeSimple) { - return env.listAtomType(bddNodeSimple.atom()); - } - return null; - } - - public static SemType cellInnerVal(CellSemType t) { - return diff(cellInner(t), UNDEF); - } - - public static SemType cellInner(CellSemType t) { - CellAtomicType cat = cellAtomicType(t); - assert cat != null; - return cat.ty(); - } - - public static CellSemType cellContainingInnerVal(Env env, CellSemType t) { - CellAtomicType cat = cellAtomicType(t); - assert cat != null; - return cellContaining(env, diff(cat.ty(), UNDEF), cat.mut()); - } - - public static CellAtomicType cellAtomicType(SemType t) { - if (t instanceof BasicTypeBitSet) { - return PredefinedType.CELL.equals(t) ? CELL_ATOMIC_VAL : null; - } else { - if (!isSubtypeSimple(t, PredefinedType.CELL)) { - return null; - } - return bddCellAtomicType((Bdd) getComplexSubtypeData((ComplexSemType) t, BT_CELL), CELL_ATOMIC_VAL); - } - } - - static CellAtomicType bddCellAtomicType(Bdd bdd, CellAtomicType top) { - if (bdd instanceof BddAllOrNothing allOrNothing) { - if (allOrNothing.isAll()) { - return top; - } - return null; - } - BddNode bddNode = (BddNode) bdd; - if (bddNode.left().equals(BddAllOrNothing.bddAll()) && - bddNode.middle().equals(BddAllOrNothing.bddNothing()) && - bddNode.right().equals(BddAllOrNothing.bddNothing())) { - return cellAtomType(bddNode.atom()); - } - return null; - } - - public static Optional singleShape(SemType t) { - if (PredefinedType.NIL.equals(t)) { - return Optional.of(Value.from(null)); - } else if (t instanceof BasicTypeBitSet) { - return Optional.empty(); - } else if (isSubtypeSimple(t, PredefinedType.INT)) { - SubtypeData sd = getComplexSubtypeData((ComplexSemType) t, BT_INT); - Optional value = IntSubtype.intSubtypeSingleValue(sd); - return value.isEmpty() ? Optional.empty() : Optional.of(Value.from(value.get())); - } else if (isSubtypeSimple(t, PredefinedType.FLOAT)) { - SubtypeData sd = getComplexSubtypeData((ComplexSemType) t, BT_FLOAT); - Optional value = FloatSubtype.floatSubtypeSingleValue(sd); - return value.isEmpty() ? Optional.empty() : Optional.of(Value.from(value.get())); - } else if (isSubtypeSimple(t, PredefinedType.STRING)) { - SubtypeData sd = getComplexSubtypeData((ComplexSemType) t, BT_STRING); - Optional value = StringSubtype.stringSubtypeSingleValue(sd); - return value.isEmpty() ? Optional.empty() : Optional.of(Value.from(value.get())); - } else if (isSubtypeSimple(t, PredefinedType.BOOLEAN)) { - SubtypeData sd = getComplexSubtypeData((ComplexSemType) t, BT_BOOLEAN); - Optional value = BooleanSubtype.booleanSubtypeSingleValue(sd); - return value.isEmpty() ? Optional.empty() : Optional.of(Value.from(value.get())); - } else if (isSubtypeSimple(t, PredefinedType.DECIMAL)) { - SubtypeData sd = getComplexSubtypeData((ComplexSemType) t, BT_DECIMAL); - Optional value = DecimalSubtype.decimalSubtypeSingleValue(sd); - return value.isEmpty() ? Optional.empty() : Optional.of(Value.from(value.get().toString())); - } - return Optional.empty(); - } - - public static SemType singleton(Object v) { - if (v == null) { - return PredefinedType.NIL; - } - - if (v instanceof Long lng) { - return IntSubtype.intConst(lng); - } else if (v instanceof Double d) { - return FloatSubtype.floatConst(d); - } else if (v instanceof String s) { - return StringSubtype.stringConst(s); - } else if (v instanceof Boolean b) { - return BooleanSubtype.booleanConst(b); - } else { - throw new IllegalStateException("Unsupported type: " + v.getClass().getName()); - } - } - - public static boolean containsConst(SemType t, Object v) { - if (v == null) { - return containsNil(t); - } else if (v instanceof Long lng) { - return containsConstInt(t, lng); - } else if (v instanceof Double d) { - return containsConstFloat(t, d); - } else if (v instanceof String s) { - return containsConstString(t, s); - } else if (v instanceof Boolean b) { - return containsConstBoolean(t, b); - } else { - return containsConstDecimal(t, (BigDecimal) v); - } - } - - public static boolean containsNil(SemType t) { - if (t instanceof BasicTypeBitSet b) { - return (b.bitset & (1 << BT_NIL.code)) != 0; - } else { - // todo: Need to verify this behavior - AllOrNothingSubtype complexSubtypeData = - (AllOrNothingSubtype) getComplexSubtypeData((ComplexSemType) t, BT_NIL); - return complexSubtypeData.isAllSubtype(); - } - } - - - public static boolean containsConstString(SemType t, String s) { - if (t instanceof BasicTypeBitSet b) { - return (b.bitset & (1 << BT_STRING.code)) != 0; - } else { - return StringSubtype.stringSubtypeContains( - getComplexSubtypeData((ComplexSemType) t, BT_STRING), s); - } - } - - public static boolean containsConstInt(SemType t, long n) { - if (t instanceof BasicTypeBitSet b) { - return (b.bitset & (1 << BT_INT.code)) != 0; - } else { - return IntSubtype.intSubtypeContains( - getComplexSubtypeData((ComplexSemType) t, BT_INT), n); - } - } - - public static boolean containsConstFloat(SemType t, double n) { - if (t instanceof BasicTypeBitSet b) { - return (b.bitset & (1 << BT_FLOAT.code)) != 0; - } else { - return FloatSubtype.floatSubtypeContains( - getComplexSubtypeData((ComplexSemType) t, BT_FLOAT), EnumerableFloat.from(n)); - } - } - - public static boolean containsConstDecimal(SemType t, BigDecimal n) { - if (t instanceof BasicTypeBitSet b) { - return (b.bitset & (1 << BT_DECIMAL.code)) != 0; - } else { - return DecimalSubtype.decimalSubtypeContains( - getComplexSubtypeData((ComplexSemType) t, BT_DECIMAL), EnumerableDecimal.from(n)); - } - } - - public static boolean containsConstBoolean(SemType t, boolean bool) { - if (t instanceof BasicTypeBitSet b) { - return (b.bitset & (1 << BT_BOOLEAN.code)) != 0; - } else { - return BooleanSubtype.booleanSubtypeContains( - getComplexSubtypeData((ComplexSemType) t, BT_BOOLEAN), bool); - } - } - - public static Optional singleNumericType(SemType semType) { - SemType numType = intersect(semType, PredefinedType.NUMBER); - if (numType instanceof BasicTypeBitSet b) { - if (b.bitset == NEVER.bitset) { - return Optional.empty(); - } - } - if (isSubtypeSimple(numType, PredefinedType.INT)) { - return Optional.of(PredefinedType.INT); - } - if (isSubtypeSimple(numType, PredefinedType.FLOAT)) { - return Optional.of(PredefinedType.FLOAT); - } - if (isSubtypeSimple(numType, PredefinedType.DECIMAL)) { - return Optional.of(PredefinedType.DECIMAL); - } - return Optional.empty(); - } - - public static SubtypeData subtypeData(SemType s, BasicTypeCode code) { - if (s instanceof BasicTypeBitSet b) { - if ((b.bitset & (1 << code.code)) != 0) { - return AllOrNothingSubtype.createAll(); - } - return AllOrNothingSubtype.createNothing(); - } else { - return getComplexSubtypeData((ComplexSemType) s, code); - } - } - - public static Context typeCheckContext(Env env) { - return Context.from(env); - } - - public static SemType createJson(Context context) { - SemType memo = context.jsonMemo; - Env env = context.env; - - if (memo != null) { - return memo; - } - ListDefinition listDef = new ListDefinition(); - MappingDefinition mapDef = new MappingDefinition(); - SemType j = union(PredefinedType.SIMPLE_OR_STRING, union(listDef.getSemType(env), mapDef.getSemType(env))); - listDef.defineListTypeWrapped(env, j); - mapDef.defineMappingTypeWrapped(env, new ArrayList<>(), j); - context.jsonMemo = j; - return j; - } - - public static SemType createAnydata(Context context) { - SemType memo = context.anydataMemo; - Env env = context.env; - - if (memo != null) { - return memo; - } - ListDefinition listDef = new ListDefinition(); - MappingDefinition mapDef = new MappingDefinition(); - SemType tableTy = TableSubtype.tableContaining(env, mapDef.getSemType(env)); - SemType ad = union(union(SIMPLE_OR_STRING, union(XML, union(REGEXP, tableTy))), - union(listDef.getSemType(env), mapDef.getSemType(env))); - listDef.defineListTypeWrapped(env, ad); - mapDef.defineMappingTypeWrapped(env, new ArrayList<>(), ad); - context.anydataMemo = ad; - return ad; - } - - public static SemType createCloneable(Context context) { - SemType memo = context.cloneableMemo; - Env env = context.env; - - if (memo != null) { - return memo; - } - ListDefinition listDef = new ListDefinition(); - MappingDefinition mapDef = new MappingDefinition(); - SemType tableTy = TableSubtype.tableContaining(env, mapDef.getSemType(env)); - SemType ad = union(VAL_READONLY, union(XML, union(listDef.getSemType(env), union(tableTy, - mapDef.getSemType(env))))); - listDef.defineListTypeWrapped(env, ad); - mapDef.defineMappingTypeWrapped(env, new ArrayList<>(), ad); - context.cloneableMemo = ad; - return ad; - } - - public static SemType createIsolatedObject(Context context) { - SemType memo = context.isolatedObjectMemo; - if (memo != null) { - return memo; - } - - ObjectQualifiers quals = new ObjectQualifiers(true, false, ObjectQualifiers.NetworkQualifier.None); - SemType isolatedObj = new ObjectDefinition().define(context.env, quals, Collections.emptyList()); - context.isolatedObjectMemo = isolatedObj; - return isolatedObj; - } - - public static SemType createServiceObject(Context context) { - SemType memo = context.serviceObjectMemo; - if (memo != null) { - return memo; - } - - ObjectQualifiers quals = new ObjectQualifiers(false, false, ObjectQualifiers.NetworkQualifier.Service); - SemType serviceObj = new ObjectDefinition().define(context.env, quals, Collections.emptyList()); - context.serviceObjectMemo = serviceObj; - return serviceObj; - } - - public static SemType createBasicSemType(BasicTypeCode typeCode, SubtypeData subtypeData) { - if (subtypeData instanceof AllOrNothingSubtype) { - if (Common.isAllSubtype(subtypeData)) { - return BasicTypeBitSet.from(1 << typeCode.code); - } else { - return BasicTypeBitSet.from(0); - } - } else { - return ComplexSemType.createComplexSemType(0, - BasicSubtype.from(typeCode, (ProperSubtypeData) subtypeData)); - } - } - - // ------------------------- Newly Introduced APIs (Does not exist in nBallerina) -------------------------------- - - // Consider map|map|...|map. This API will return all MappingAtomicTypes in the union. - public static Optional> mappingAtomicTypesInUnion(Context cx, SemType t) { - ArrayList matList = new ArrayList<>(); - MappingAtomicType mappingAtomicInner = MAPPING_ATOMIC_INNER; - if (t instanceof BasicTypeBitSet b) { - if (b.bitset == MAPPING.bitset) { - matList.add(mappingAtomicInner); - return Optional.of(matList); - } - return Optional.empty(); - } else { - Env env = cx.env; - if (!isSubtypeSimple(t, MAPPING)) { - return Optional.empty(); - } - return collectBddMappingAtomicTypesInUnion(env, - (Bdd) getComplexSubtypeData((ComplexSemType) t, BT_MAPPING), - mappingAtomicInner, matList) ? Optional.of(matList) : Optional.empty(); - } - } - - private static boolean collectBddMappingAtomicTypesInUnion(Env env, Bdd bdd, MappingAtomicType top, - List matList) { - if (bdd instanceof BddAllOrNothing allOrNothing) { - if (allOrNothing.isAll()) { - matList.add(top); - return true; - } - return false; - } - BddNode bddNode = (BddNode) bdd; - if (bddNode instanceof BddNodeSimple bddNodeSimple) { - matList.add(env.mappingAtomType(bddNodeSimple.atom())); - return true; - } - - BddNodeImpl bddNodeImpl = (BddNodeImpl) bddNode; - if (bddNodeImpl.left() instanceof BddAllOrNothing leftNode && leftNode.isAll() && - bddNodeImpl.right() instanceof BddAllOrNothing rightNode && rightNode.isNothing()) { - matList.add(env.mappingAtomType(bddNodeImpl.atom())); - return collectBddMappingAtomicTypesInUnion(env, bddNodeImpl.middle(), top, matList); - } - - return false; - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/EnumerableCharString.java b/semtypes/src/main/java/io/ballerina/types/EnumerableCharString.java deleted file mode 100644 index d017d133c65c..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/EnumerableCharString.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -/** - * Enumerable type wrapper for string. - * - * @since 2201.8.0 - */ -public class EnumerableCharString implements EnumerableType { - // String since Java char can't hold some Unicode characters - public final String value; - - private EnumerableCharString(String value) { - this.value = value; - } - - public static EnumerableCharString from(String v) { - return new EnumerableCharString(v); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof EnumerableCharString e)) { - return false; - } - return (e.value.equals(this.value)); - } - - @Override - public int hashCode() { - return value.hashCode(); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/EnumerableDecimal.java b/semtypes/src/main/java/io/ballerina/types/EnumerableDecimal.java deleted file mode 100644 index 09fc64e5fdf9..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/EnumerableDecimal.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import java.math.BigDecimal; - -/** - * Enumerable type wrapper for decimal. - * - * @since 2201.8.0 - */ -public class EnumerableDecimal implements EnumerableType { - public final BigDecimal value; - - private EnumerableDecimal(BigDecimal value) { - this.value = value; - } - - public static EnumerableDecimal from(BigDecimal d) { - return new EnumerableDecimal(d); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof EnumerableDecimal e)) { - return false; - } - return (e.value.compareTo(this.value) == 0); - } - - @Override - public int hashCode() { - return value.hashCode(); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/EnumerableFloat.java b/semtypes/src/main/java/io/ballerina/types/EnumerableFloat.java deleted file mode 100644 index 09531897daef..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/EnumerableFloat.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -/** - * Enumerable type wrapper for float. - * - * @since 2201.8.0 - */ -public class EnumerableFloat implements EnumerableType { - public final double value; - - private EnumerableFloat(double value) { - this.value = value; - } - - public static EnumerableFloat from(double d) { - return new EnumerableFloat(d); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof EnumerableFloat e)) { - return false; - } - - Double v1 = e.value; - Double v2 = this.value; - return (v1.compareTo(v2) == 0); - } - - @Override - public int hashCode() { - return Double.hashCode(value); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/EnumerableString.java b/semtypes/src/main/java/io/ballerina/types/EnumerableString.java deleted file mode 100644 index 55a2c8958d4f..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/EnumerableString.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -/** - * Enumerable type wrapper for string. - * - * @since 2201.8.0 - */ -public class EnumerableString implements EnumerableType { - public final String value; - - private EnumerableString(String value) { - this.value = value; - } - - public static EnumerableString from(String v) { - return new EnumerableString(v); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof EnumerableString e)) { - return false; - } - return (e.value.equals(this.value)); - } - - @Override - public int hashCode() { - return value.hashCode(); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/EnumerableSubtype.java b/semtypes/src/main/java/io/ballerina/types/EnumerableSubtype.java deleted file mode 100644 index 68c5134ed7eb..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/EnumerableSubtype.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import java.math.BigDecimal; -import java.util.List; -import java.util.Objects; - -/** - * EnumerableSubtype with enumerable subtype ops. - * - * @since 2201.8.0 - */ -public abstract class EnumerableSubtype { - public static final int LT = -1; - public static final int EQ = 0; - public static final int GT = 1; - - public abstract boolean allowed(); - public abstract EnumerableType[] values(); - - public static boolean enumerableSubtypeUnion(EnumerableSubtype t1, EnumerableSubtype t2, - List result) { - boolean b1 = t1.allowed(); - boolean b2 = t2.allowed(); - boolean allowed; - if (b1 && b2) { - enumerableListUnion(t1.values(), t2.values(), result); - allowed = true; - } else if (!b1 && !b2) { - enumerableListIntersect(t1.values(), t2.values(), result); - allowed = false; - } else if (b1 && !b2) { - enumerableListDiff(t2.values(), t1.values(), result); - allowed = false; - } else { - // !b1 && b2 - enumerableListDiff(t1.values(), t2.values(), result); - allowed = false; - } - return allowed; - } - - public static boolean enumerableSubtypeIntersect(EnumerableSubtype t1, EnumerableSubtype t2, - List result) { - boolean b1 = t1.allowed(); - boolean b2 = t2.allowed(); - boolean allowed; - if (b1 && b2) { - enumerableListIntersect(t1.values(), t2.values(), result); - allowed = true; - } else if (!b1 && !b2) { - enumerableListUnion(t1.values(), t2.values(), result); - allowed = false; - } else if (b1 && !b2) { - enumerableListDiff(t1.values(), t2.values(), result); - allowed = true; - } else { - // !b1 && b2 - enumerableListDiff(t2.values(), t1.values(), result); - allowed = true; - } - return allowed; - } - - public static void enumerableListUnion(EnumerableType[] v1, EnumerableType[] v2, - List resulte) { - List result = (List) resulte; - int i1 = 0; - int i2 = 0; - int len1 = v1.length; - int len2 = v2.length; - - while (true) { - if (i1 >= len1) { - if (i2 >= len2) { - break; - } - result.add(v2[i2]); - i2 += 1; - } else if (i2 >= len2) { - result.add(v1[i1]); - i1 += 1; - } else { - EnumerableType s1 = v1[i1]; - EnumerableType s2 = v2[i2]; - switch (compareEnumerable(s1, s2)) { - case EQ: - result.add(s1); - i1 += 1; - i2 += 1; - break; - case LT: - result.add(s1); - i1 += 1; - break; - case GT: - result.add(s2); - i2 += 1; - break; - } - } - } - } - - public static void enumerableListIntersect(EnumerableType[] v1, EnumerableType[] v2, - List resulte) { - List result = (List) resulte; - int i1 = 0; - int i2 = 0; - int len1 = v1.length; - int len2 = v2.length; - - while (true) { - if (i1 >= len1 || i2 >= len2) { - break; - } else { - EnumerableType s1 = v1[i1]; - EnumerableType s2 = v2[i2]; - switch (compareEnumerable(s1, s2)) { - case EQ: - result.add(s1); - i1 += 1; - i2 += 1; - break; - case LT: - i1 += 1; - break; - case GT: - i2 += 1; - break; - } - } - } - } - - public static void enumerableListDiff(EnumerableType[] v1, EnumerableType[] v2, - List resulte) { - List result = (List) resulte; - int i1 = 0; - int i2 = 0; - int len1 = v1.length; - int len2 = v2.length; - - while (true) { - if (i1 >= len1) { - break; - } - if (i2 >= len2) { - result.add(v1[i1]); - i1 += 1; - } else { - EnumerableType s1 = v1[i1]; - EnumerableType s2 = v2[i2]; - switch (compareEnumerable(s1, s2)) { - case EQ: - i1 += 1; - i2 += 1; - break; - case LT: - result.add(s1); - i1 += 1; - break; - case GT: - i2 += 1; - break; - } - } - } - } - - public static int compareEnumerable(EnumerableType v1, EnumerableType v2) { - if (v1 instanceof EnumerableString) { - String s2 = ((EnumerableString) v2).value; - String s1 = ((EnumerableString) v1).value; - return Objects.equals(s1, s2) ? EQ : (Common.codePointCompare(s1, s2) ? LT : GT); - } else if (v1 instanceof EnumerableCharString) { - String s2 = ((EnumerableCharString) v2).value + ""; - String s1 = ((EnumerableCharString) v1).value + ""; - return Objects.equals(s1, s2) ? EQ : (Common.codePointCompare(s1, s2) ? LT : GT); - } else if (v1 instanceof EnumerableDecimal) { - BigDecimal d2 = ((EnumerableDecimal) v2).value; - BigDecimal d1 = ((EnumerableDecimal) v1).value; - return d1.compareTo(d2); - } else { - double f1 = ((EnumerableFloat) v1).value; - double f2 = ((EnumerableFloat) v2).value; - if (bFloatEq(f1, f2)) { - return EQ; - } else if (Double.isNaN(f1)) { - return LT; - } else if (Double.isNaN(f2)) { - return GT; - } else if (f1 < f2) { - return LT; - } - return GT; - } - } - - private static boolean bFloatEq(double f1, double f2) { - if (Double.isNaN(f1)) { - return Double.isNaN(f2); - } - return f1 == f2; - } -} - diff --git a/semtypes/src/main/java/io/ballerina/types/EnumerableType.java b/semtypes/src/main/java/io/ballerina/types/EnumerableType.java deleted file mode 100644 index 04c46676fa85..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/EnumerableType.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -/** - * Interface to indicate Enumerable types. - * - * @since 2201.8.0 - */ -public interface EnumerableType { -} diff --git a/semtypes/src/main/java/io/ballerina/types/Env.java b/semtypes/src/main/java/io/ballerina/types/Env.java deleted file mode 100644 index f9b512b72c13..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/Env.java +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import java.lang.ref.Reference; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.WeakHashMap; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * Env node. - * - * @since 2201.8.0 - */ -public class Env { - - private static final int COMPACT_INDEX = 3; - final List recListAtoms; - final List recMappingAtoms; - final List recFunctionAtoms; - private final AtomicInteger distinctAtomCount; - private final Map> atomTable; - - private final LinkedHashMap types; - - public Env() { - this.atomTable = new WeakHashMap<>(); - this.recListAtoms = new ArrayList<>(); - this.recMappingAtoms = new ArrayList<>(); - this.recFunctionAtoms = new ArrayList<>(); - types = new LinkedHashMap<>(); - distinctAtomCount = new AtomicInteger(0); - - PredefinedTypeEnv.getInstance().initializeEnv(this); - } - - public int recListAtomCount() { - return this.recListAtoms.size(); - } - - public int recMappingAtomCount() { - return this.recMappingAtoms.size(); - } - - public int recFunctionAtomCount() { - return this.recFunctionAtoms.size(); - } - - public int distinctAtomCount() { - return this.distinctAtomCount.get(); - } - - public int distinctAtomCountGetAndIncrement() { - return this.distinctAtomCount.getAndIncrement(); - } - - public RecAtom recFunctionAtom() { - synchronized (this.recFunctionAtoms) { - int result = this.recFunctionAtoms.size(); - // represents adding () in nballerina - this.recFunctionAtoms.add(null); - return RecAtom.createRecAtom(result); - } - } - - public void setRecFunctionAtomType(RecAtom ra, FunctionAtomicType atomicType) { - synchronized (this.recFunctionAtoms) { - ra.setKind(Atom.Kind.FUNCTION_ATOM); - this.recFunctionAtoms.set(ra.index, atomicType); - } - } - - public FunctionAtomicType getRecFunctionAtomType(RecAtom ra) { - synchronized (this.recFunctionAtoms) { - return this.recFunctionAtoms.get(ra.index); - } - } - - public TypeAtom listAtom(ListAtomicType atomicType) { - return this.typeAtom(atomicType); - } - - public TypeAtom mappingAtom(MappingAtomicType atomicType) { - return this.typeAtom(atomicType); - } - - public TypeAtom functionAtom(FunctionAtomicType atomicType) { - return this.typeAtom(atomicType); - } - - public TypeAtom cellAtom(CellAtomicType atomicType) { - return this.typeAtom(atomicType); - } - - private TypeAtom typeAtom(AtomicType atomicType) { - synchronized (this.atomTable) { - Reference ref = this.atomTable.get(atomicType); - if (ref != null) { - TypeAtom ta = ref.get(); - if (ta != null) { - return ta; - } - } - TypeAtom result = TypeAtom.createTypeAtom(this.atomTable.size(), atomicType); - this.atomTable.put(result.atomicType(), new WeakReference<>(result)); - return result; - } - } - - public void deserializeTypeAtom(TypeAtom typeAtom) { - synchronized (this.atomTable) { - this.atomTable.put(typeAtom.atomicType(), new WeakReference<>(typeAtom)); - } - } - - public void insertRecAtomAtIndex(int index, AtomicType atomicType) { - if (atomicType instanceof MappingAtomicType mappingAtomicType) { - insertAtomAtIndexInner(index, this.recMappingAtoms, mappingAtomicType); - } else if (atomicType instanceof ListAtomicType listAtomicType) { - insertAtomAtIndexInner(index, this.recListAtoms, listAtomicType); - } else if (atomicType instanceof FunctionAtomicType functionAtomicType) { - insertAtomAtIndexInner(index, this.recFunctionAtoms, functionAtomicType); - } else { - throw new UnsupportedOperationException("Unknown atomic type " + atomicType); - } - } - - private void insertAtomAtIndexInner(int index, List atoms, E atomicType) { - // atoms are always private final fields therefore synchronizing on them should be safe. - synchronized (atoms) { - if (atoms.size() > index && atoms.get(index) != null) { - return; - } - while (atoms.size() < index + 1) { - atoms.add(null); - } - atoms.set(index, atomicType); - } - } - - public ListAtomicType listAtomType(Atom atom) { - if (atom instanceof RecAtom recAtom) { - return getRecListAtomType(recAtom); - } else { - return (ListAtomicType) ((TypeAtom) atom).atomicType(); - } - } - - public FunctionAtomicType functionAtomType(Atom atom) { - if (atom instanceof RecAtom recAtom) { - return getRecFunctionAtomType(recAtom); - } else { - return (FunctionAtomicType) ((TypeAtom) atom).atomicType(); - } - } - - public MappingAtomicType mappingAtomType(Atom atom) { - if (atom instanceof RecAtom recAtom) { - return getRecMappingAtomType(recAtom); - } else { - return (MappingAtomicType) ((TypeAtom) atom).atomicType(); - } - } - - public RecAtom recListAtom() { - synchronized (this.recListAtoms) { - int result = this.recListAtoms.size(); - this.recListAtoms.add(null); - return RecAtom.createRecAtom(result); - } - } - - public RecAtom recMappingAtom() { - synchronized (this.recMappingAtoms) { - int result = this.recMappingAtoms.size(); - this.recMappingAtoms.add(null); - return RecAtom.createRecAtom(result); - } - } - - public void setRecListAtomType(RecAtom ra, ListAtomicType atomicType) { - synchronized (this.recListAtoms) { - ra.setKind(Atom.Kind.LIST_ATOM); - this.recListAtoms.set(ra.index, atomicType); - } - } - - public void setRecMappingAtomType(RecAtom ra, MappingAtomicType atomicType) { - synchronized (this.recListAtoms) { - ra.setKind(Atom.Kind.MAPPING_ATOM); - this.recMappingAtoms.set(ra.index, atomicType); - } - } - - public ListAtomicType getRecListAtomType(RecAtom ra) { - synchronized (this.recListAtoms) { - return this.recListAtoms.get(ra.index); - } - } - - public MappingAtomicType getRecMappingAtomType(RecAtom ra) { - synchronized (this.recMappingAtoms) { - return this.recMappingAtoms.get(ra.index); - } - } - - public static CellAtomicType cellAtomType(Atom atom) { - return (CellAtomicType) ((TypeAtom) atom).atomicType(); - } - - public void addTypeDef(String typeName, SemType semType) { - this.types.put(typeName, semType); - } - - public Map getTypeNameSemTypeMap() { - return new LinkedHashMap<>(this.types); - } - - public int atomCount() { - synchronized (this.atomTable) { - return this.atomTable.size(); - } - } - - // TODO: instead of compact index we should analyze the environment before serialization, but a naive bumping index - // in the BIRTypeWriter created incorrect indexes in the BIR. This is a temporary workaround. - private CompactionData compactionData = null; - - /** - * During type checking we create recursive type atoms that are not parts of the actual ballerina module which will - * not marshalled. This leaves "holes" in the rec atom lists when we unmarshall the BIR, which will then get - * propagated from one module to next. This method will return a new index corrected for such holes. - * - * @param recAtom atom for which you need the corrected index - * @return index corrected for "holes" in rec atom list - */ - public synchronized int compactRecIndex(RecAtom recAtom) { - if (compactionData == null || !compactionData.state().equals(EnvState.from(this))) { - compactionData = compaction(); - } - if (recAtom.index < COMPACT_INDEX) { - return recAtom.index; - } - return switch (recAtom.kind()) { - case LIST_ATOM -> compactionData.listMap().get(recAtom.index()); - case MAPPING_ATOM -> compactionData.mapMap().get(recAtom.index()); - case FUNCTION_ATOM -> compactionData.funcMap().get(recAtom.index()); - case CELL_ATOM, XML_ATOM, DISTINCT_ATOM -> recAtom.index; - }; - } - - private CompactionData compaction() { - EnvState state = EnvState.from(this); - Map listMap = recListCompaction(this.recListAtoms); - Map mapMap = recListCompaction(this.recMappingAtoms); - Map funcMap = recListCompaction(this.recFunctionAtoms); - return new CompactionData(state, listMap, mapMap, funcMap); - } - - private Map recListCompaction(List recAtomList) { - Map map = new HashMap<>(); - int compactIndex = COMPACT_INDEX; - for (int i = COMPACT_INDEX; i < recAtomList.size(); i++) { - if (recAtomList.get(i) != null) { - map.put(i, compactIndex); - compactIndex++; - } - } - return map; - } - - record EnvState(int recListAtomCount, int recMappingAtomCount, int recFunctionAtomCount) { - - public static EnvState from(Env env) { - return new EnvState(env.recListAtomCount(), env.recMappingAtomCount(), - env.recFunctionAtomCount()); - } - } - - private record CompactionData(EnvState state, Map listMap, Map mapMap, - Map funcMap) { - - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/Error.java b/semtypes/src/main/java/io/ballerina/types/Error.java deleted file mode 100644 index a3577b4c9f38..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/Error.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import io.ballerina.types.subtypedata.AllOrNothingSubtype; -import io.ballerina.types.subtypedata.BddNode; - -import static io.ballerina.types.BasicTypeCode.BT_ERROR; -import static io.ballerina.types.Core.subtypeData; -import static io.ballerina.types.PredefinedType.BDD_SUBTYPE_RO; -import static io.ballerina.types.PredefinedType.ERROR; -import static io.ballerina.types.PredefinedType.NEVER; -import static io.ballerina.types.PredefinedType.basicSubtype; -import static io.ballerina.types.RecAtom.createDistinctRecAtom; -import static io.ballerina.types.typeops.BddCommonOps.bddAtom; -import static io.ballerina.types.typeops.BddCommonOps.bddIntersect; - -/** - * Contain functions found in error.bal file. - * - * @since 2201.8.0 - */ -public class Error { - public static SemType errorDetail(SemType detail) { - SubtypeData mappingSd = subtypeData(detail, BasicTypeCode.BT_MAPPING); - if (mappingSd instanceof AllOrNothingSubtype allOrNothingSubtype) { - if (allOrNothingSubtype.isAllSubtype()) { - return ERROR; - } else { - // XXX This should be reported as an error - return NEVER; - } - } - - SubtypeData sd = bddIntersect((Bdd) mappingSd, BDD_SUBTYPE_RO); - if (sd.equals(BDD_SUBTYPE_RO)) { - return ERROR; - } - return basicSubtype(BT_ERROR, (ProperSubtypeData) sd); - } - - public static SemType errorDistinct(int distinctId) { - assert distinctId >= 0; - BddNode bdd = bddAtom(createDistinctRecAtom(-distinctId - 1)); - return basicSubtype(BT_ERROR, bdd); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/FixedLengthArray.java b/semtypes/src/main/java/io/ballerina/types/FixedLengthArray.java deleted file mode 100644 index b12b3a08c103..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/FixedLengthArray.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Represent a fixed length semtype member list similar to a tuple. - * The length of the list is `fixedLength`, the last member of the `initial` is repeated to achieve this semantic. - * { initial: [int], fixedLength: 3, } is same as { initial: [int, int, int], fixedLength: 3 } - * { initial: [string, int], fixedLength: 100 } means `int` is repeated 99 times to get a list of 100 members. - * `fixedLength` must be `0` when `inital` is empty and the `fixedLength` must be at least `initial.length()` - * - * @param initial List of semtypes of the members of the fixes length array. If last member is repeated multiple - * times it is included only once. For example for {@code [string, string, int, int]} initial would - * be {@code [string, string, int]} - * @param fixedLength Actual length of the array. For example for {@code [string, string, int, int]} fixedLength would - * be {@code 4} - * @since 2201.8.0 - */ -public record FixedLengthArray(List initial, int fixedLength) { - - public FixedLengthArray { - initial = List.copyOf(initial); - assert fixedLength >= 0; - } - - public static FixedLengthArray from(List initial, int fixedLength) { - return new FixedLengthArray(initial, fixedLength); - } - - public List initial() { - return Collections.unmodifiableList(initial); - } - - public static FixedLengthArray empty() { - return from(new ArrayList<>(), 0); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/FunctionAtomicType.java b/semtypes/src/main/java/io/ballerina/types/FunctionAtomicType.java deleted file mode 100644 index a4bcfcd4356b..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/FunctionAtomicType.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -/** - * FunctionAtomicType node. - * - * @param paramType semtype of parameters represented as a tuple - * @param retType semtype of the return value - * @param qualifiers qualifiers of the function - * @param isGeneric atomic type represent a generic (i.e. have parameters/return type with {@code typeParam} annotation) - * @since 2201.8.0 - */ -public record FunctionAtomicType(SemType paramType, SemType retType, SemType qualifiers, boolean isGeneric) - implements AtomicType { - - public static FunctionAtomicType from(SemType paramType, SemType rest, SemType qualifiers) { - return new FunctionAtomicType(paramType, rest, qualifiers, false); - } - - public static FunctionAtomicType genericFrom(SemType paramType, SemType rest, SemType qualifiers) { - return new FunctionAtomicType(paramType, rest, qualifiers, true); - } - - @Override - public Atom.Kind atomKind() { - return Atom.Kind.FUNCTION_ATOM; - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/IntSubtypeConstraints.java b/semtypes/src/main/java/io/ballerina/types/IntSubtypeConstraints.java deleted file mode 100644 index b597b70da8e4..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/IntSubtypeConstraints.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import io.ballerina.types.subtypedata.AllOrNothingSubtype; -import io.ballerina.types.subtypedata.IntSubtype; - -import static io.ballerina.types.Core.intSubtype; -import static io.ballerina.types.typeops.IntOps.intSubtypeMax; -import static io.ballerina.types.typeops.IntOps.intSubtypeMin; - -/** - * Port of: - *

- * {@code - * // Constraints on a subtype of `int`. - * public type IntSubtypeConstraints readonly & record {| - * // all values in the subtype are >= min - * int min; - * // all values in the subtype are <= max - * int max; - * // does the subtype contain all values between min and max? - * boolean all; - * |}; - * } - * - * @since 2201.8.0 - */ -public class IntSubtypeConstraints { - final long min; - final long max; - final boolean all; - - private IntSubtypeConstraints(long min, long max, boolean all) { - this.min = min; - this.max = max; - this.all = all; - } - - // Returns `()` if `t` is not a proper, non-empty subtype of `int`. - // i.e. returns `()` if `t` contains all or non of `int`. - public static IntSubtypeConstraints intSubtypeConstraints(SemType t) { - SubtypeData st = intSubtype(t); - // JBUG can't flatten inner if-else - if (st instanceof AllOrNothingSubtype) { - return null; - } else { - IntSubtype ist = (IntSubtype) st; - int len = ist.ranges.length; - return new IntSubtypeConstraints(intSubtypeMin(ist), intSubtypeMax(ist), len == 1); - } - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/ListAtomicType.java b/semtypes/src/main/java/io/ballerina/types/ListAtomicType.java deleted file mode 100644 index 939d74b0b6fa..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/ListAtomicType.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -/** - * ListAtomicType node. - * - * @param members for a given list type this represents the required members - * @param rest for a given list type this represents the rest type. This is NEVER if the list don't have a rest type - * @since 2201.8.0 - */ -public record ListAtomicType(FixedLengthArray members, CellSemType rest) implements AtomicType { - - public ListAtomicType { - assert members != null; - assert rest != null; - } - - public static ListAtomicType from(FixedLengthArray members, CellSemType rest) { - return new ListAtomicType(members, rest); - } - - @Override - public Atom.Kind atomKind() { - return Atom.Kind.LIST_ATOM; - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/ListMemberTypes.java b/semtypes/src/main/java/io/ballerina/types/ListMemberTypes.java deleted file mode 100644 index bb1dea5fb228..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/ListMemberTypes.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import io.ballerina.types.subtypedata.Range; - -import java.util.Collections; -import java.util.List; - -/** - * Holds a pair of SemType list and Range list. - * Note: Member types at the indices that are not contained in `Range` array represent `never. - * The SemTypes in this list are not `never`. - * - * @param ranges Range array - * @param semTypes SemType array - * @since 2201.11.0 - */ -public record ListMemberTypes(List ranges, List semTypes) { - - public ListMemberTypes { - ranges = Collections.unmodifiableList(ranges); - semTypes = Collections.unmodifiableList(semTypes); - } - - @Override - public List ranges() { - return Collections.unmodifiableList(ranges); - } - - @Override - public List semTypes() { - return Collections.unmodifiableList(semTypes); - } - - public static ListMemberTypes from(List ranges, List semTypes) { - assert ranges != null && semTypes != null; - return new ListMemberTypes(ranges, semTypes); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/MappingAlternative.java b/semtypes/src/main/java/io/ballerina/types/MappingAlternative.java deleted file mode 100644 index dc668ee5163d..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/MappingAlternative.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import java.util.ArrayList; -import java.util.List; - -/** - * Represents MappingAlternative record in core.bal. - * - * @since 2201.8.0 - */ -public class MappingAlternative { - SemType semType; - MappingAtomicType[] pos; - MappingAtomicType[] neg; - - private MappingAlternative(SemType semType, MappingAtomicType[] pos, MappingAtomicType[] neg) { - this.semType = semType; - this.pos = pos; - this.neg = neg; - } - - public MappingAlternative[] mappingAlternatives(Context cx, SemType t) { - if (t instanceof BasicTypeBitSet b) { - if ((b.bitset & PredefinedType.MAPPING.bitset) == 0) { - return new MappingAlternative[]{}; - } else { - return new MappingAlternative[]{ - from(cx, PredefinedType.MAPPING, List.of(), List.of()) - }; - } - } else { - List paths = new ArrayList<>(); - BddPath.bddPaths((Bdd) Core.getComplexSubtypeData((ComplexSemType) t, BasicTypeCode.BT_MAPPING), paths, - BddPath.from()); - List alts = new ArrayList<>(); - for (BddPath bddPath : paths) { - SemType semType = Core.createBasicSemType(BasicTypeCode.BT_MAPPING, bddPath.bdd); - if (!Core.isNever(semType)) { - alts.add(from(cx, semType, bddPath.pos, bddPath.neg)); - } - } - return alts.toArray(new MappingAlternative[]{}); - } - } - - public MappingAlternative from(Context cx, SemType semType, List pos, List neg) { - MappingAtomicType[] p = new MappingAtomicType[pos.size()]; - MappingAtomicType[] n = new MappingAtomicType[neg.size()]; - for (int i = 0; i < pos.size(); i++) { - p[i] = cx.mappingAtomType(pos.get(i)); - } - for (int i = 0; i < neg.size(); i++) { - n[i] = cx.mappingAtomType(neg.get(i)); - } - return new MappingAlternative(semType, p, n); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/MappingAtomicType.java b/semtypes/src/main/java/io/ballerina/types/MappingAtomicType.java deleted file mode 100644 index aae9c00fa5c1..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/MappingAtomicType.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -// TODO: consider switching arrays to lists so if does the element wise comparison correctly, (or override equals) - -import java.util.Arrays; -import java.util.Objects; - -/** - * MappingAtomicType node. {@code names} and {@code types} fields must be sorted. - * - * @param names names of the required members - * @param types types of the required members - * @param rest for a given mapping type this represents the rest type. This is NEVER if the mapping don't have a rest - * type - * @since 2201.8.0 - */ -public record MappingAtomicType(String[] names, CellSemType[] types, CellSemType rest) implements AtomicType { - - public MappingAtomicType(String[] names, CellSemType[] types, CellSemType rest) { - this.names = Arrays.copyOf(names, names.length); - this.types = Arrays.copyOf(types, names.length); - this.rest = rest; - } - - // TODO: we can replace these with unmodifiable lists - // (which don't create new lists after changing parameters to lists) - public String[] names() { - return Arrays.copyOf(names, names.length); - } - - public CellSemType[] types() { - return Arrays.copyOf(types, types.length); - } - - public static MappingAtomicType from(String[] names, CellSemType[] types, CellSemType rest) { - return new MappingAtomicType(names, types, rest); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof MappingAtomicType other)) { - return false; - } - return Arrays.equals(names, other.names) && - Arrays.equals(types, other.types) && - Objects.equals(rest, other.rest); - } - - @Override - public int hashCode() { - return Objects.hash(Arrays.hashCode(names), Arrays.hashCode(types), rest); - } - - @Override - public Atom.Kind atomKind() { - return Atom.Kind.MAPPING_ATOM; - } - - @Override - public String toString() { - return "MappingAtomicType{" + - "names=" + Arrays.toString(names) + - ", types=" + Arrays.toString(types) + - ", rest=" + rest + - '}'; - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/OpsTable.java b/semtypes/src/main/java/io/ballerina/types/OpsTable.java deleted file mode 100644 index fae1e15ad486..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/OpsTable.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import io.ballerina.types.typeops.BasicTypeOpsPanicImpl; -import io.ballerina.types.typeops.BooleanOps; -import io.ballerina.types.typeops.CellOps; -import io.ballerina.types.typeops.DecimalOps; -import io.ballerina.types.typeops.ErrorOps; -import io.ballerina.types.typeops.FloatOps; -import io.ballerina.types.typeops.FunctionOps; -import io.ballerina.types.typeops.FutureOps; -import io.ballerina.types.typeops.IntOps; -import io.ballerina.types.typeops.ListOps; -import io.ballerina.types.typeops.MappingOps; -import io.ballerina.types.typeops.ObjectOps; -import io.ballerina.types.typeops.StreamOps; -import io.ballerina.types.typeops.StringOps; -import io.ballerina.types.typeops.TableOps; -import io.ballerina.types.typeops.TypedescOps; -import io.ballerina.types.typeops.XmlOps; - -/** - * Lookup table containing subtype ops for each basic type indexed by basic type code. - * - * @since 2201.8.0 - */ -public class OpsTable { - private static final BasicTypeOpsPanicImpl PANIC_IMPL = new BasicTypeOpsPanicImpl(); - static final BasicTypeOps[] OPS; - - static { - int i = 0; - OPS = new BasicTypeOps[19]; - OPS[i++] = PANIC_IMPL; // nil - OPS[i++] = new BooleanOps(); // boolean - OPS[i++] = new IntOps(); // int - OPS[i++] = new FloatOps(); // float - OPS[i++] = new DecimalOps(); // decimal - OPS[i++] = new StringOps(); // string - OPS[i++] = new ErrorOps(); // error - OPS[i++] = new TypedescOps(); // typedesc - OPS[i++] = PANIC_IMPL; // handle - OPS[i++] = new FunctionOps(); // function - OPS[i++] = PANIC_IMPL; // regexp - OPS[i++] = new FutureOps(); // future - OPS[i++] = new StreamOps(); // stream - OPS[i++] = new ListOps(); // list - OPS[i++] = new MappingOps(); // mapping - OPS[i++] = new TableOps(); // table - OPS[i++] = new XmlOps(); // xml - OPS[i++] = new ObjectOps(); // object - OPS[i] = new CellOps(); // cell - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/PredefinedType.java b/semtypes/src/main/java/io/ballerina/types/PredefinedType.java deleted file mode 100644 index 9815ee12b9e5..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/PredefinedType.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import io.ballerina.types.subtypedata.BddNode; -import io.ballerina.types.subtypedata.IntSubtype; -import io.ballerina.types.subtypedata.StringSubtype; - -import java.util.StringJoiner; - -import static io.ballerina.types.BasicTypeCode.BT_CELL; -import static io.ballerina.types.BasicTypeCode.BT_LIST; -import static io.ballerina.types.BasicTypeCode.BT_MAPPING; -import static io.ballerina.types.BasicTypeCode.BT_OBJECT; -import static io.ballerina.types.BasicTypeCode.BT_TABLE; -import static io.ballerina.types.BasicTypeCode.BT_XML; -import static io.ballerina.types.BasicTypeCode.VT_INHERENTLY_IMMUTABLE; -import static io.ballerina.types.ComplexSemType.createComplexSemType; -import static io.ballerina.types.Core.union; -import static io.ballerina.types.subtypedata.XmlSubtype.XML_PRIMITIVE_COMMENT_RO; -import static io.ballerina.types.subtypedata.XmlSubtype.XML_PRIMITIVE_COMMENT_RW; -import static io.ballerina.types.subtypedata.XmlSubtype.XML_PRIMITIVE_ELEMENT_RO; -import static io.ballerina.types.subtypedata.XmlSubtype.XML_PRIMITIVE_ELEMENT_RW; -import static io.ballerina.types.subtypedata.XmlSubtype.XML_PRIMITIVE_PI_RO; -import static io.ballerina.types.subtypedata.XmlSubtype.XML_PRIMITIVE_PI_RW; -import static io.ballerina.types.subtypedata.XmlSubtype.XML_PRIMITIVE_TEXT; -import static io.ballerina.types.subtypedata.XmlSubtype.xmlSequence; -import static io.ballerina.types.subtypedata.XmlSubtype.xmlSingleton; -import static io.ballerina.types.typeops.BddCommonOps.bddAtom; -import static io.ballerina.types.typeops.XmlOps.XML_SUBTYPE_RO; - -/** - * Contain predefined types used for constructing other types. - * - * @since 2201.8.0 - */ -public final class PredefinedType { - - private static final PredefinedTypeEnv predefinedTypeEnv = PredefinedTypeEnv.getInstance(); - public static final BasicTypeBitSet NEVER = basicTypeUnion(0); - public static final BasicTypeBitSet NIL = basicType(BasicTypeCode.BT_NIL); - public static final BasicTypeBitSet BOOLEAN = basicType(BasicTypeCode.BT_BOOLEAN); - public static final BasicTypeBitSet INT = basicType(BasicTypeCode.BT_INT); - public static final BasicTypeBitSet FLOAT = basicType(BasicTypeCode.BT_FLOAT); - public static final BasicTypeBitSet DECIMAL = basicType(BasicTypeCode.BT_DECIMAL); - public static final BasicTypeBitSet STRING = basicType(BasicTypeCode.BT_STRING); - public static final BasicTypeBitSet ERROR = basicType(BasicTypeCode.BT_ERROR); - public static final BasicTypeBitSet LIST = basicType(BasicTypeCode.BT_LIST); - public static final BasicTypeBitSet MAPPING = basicType(BasicTypeCode.BT_MAPPING); - public static final BasicTypeBitSet TABLE = basicType(BasicTypeCode.BT_TABLE); - public static final BasicTypeBitSet CELL = basicType(BT_CELL); - public static final BasicTypeBitSet UNDEF = basicType(BasicTypeCode.BT_UNDEF); - public static final BasicTypeBitSet REGEXP = basicType(BasicTypeCode.BT_REGEXP); - - // matches all functions - public static final BasicTypeBitSet FUNCTION = basicType(BasicTypeCode.BT_FUNCTION); - public static final BasicTypeBitSet TYPEDESC = basicType(BasicTypeCode.BT_TYPEDESC); - public static final BasicTypeBitSet HANDLE = basicType(BasicTypeCode.BT_HANDLE); - - public static final BasicTypeBitSet XML = basicType(BasicTypeCode.BT_XML); - public static final BasicTypeBitSet OBJECT = basicType(BasicTypeCode.BT_OBJECT); - public static final BasicTypeBitSet STREAM = basicType(BasicTypeCode.BT_STREAM); - public static final BasicTypeBitSet FUTURE = basicType(BasicTypeCode.BT_FUTURE); - - // this is SubtypeData|error - public static final BasicTypeBitSet VAL = basicTypeUnion(BasicTypeCode.VT_MASK); - public static final BasicTypeBitSet INNER = BasicTypeBitSet.from(VAL.bitset | UNDEF.bitset); - public static final BasicTypeBitSet ANY = - basicTypeUnion(BasicTypeCode.VT_MASK & ~(1 << BasicTypeCode.BT_ERROR.code)); - - public static final BasicTypeBitSet SIMPLE_OR_STRING = - basicTypeUnion((1 << BasicTypeCode.BT_NIL.code) - | (1 << BasicTypeCode.BT_BOOLEAN.code) - | (1 << BasicTypeCode.BT_INT.code) - | (1 << BasicTypeCode.BT_FLOAT.code) - | (1 << BasicTypeCode.BT_DECIMAL.code) - | (1 << BasicTypeCode.BT_STRING.code)); - - public static final BasicTypeBitSet NUMBER = - basicTypeUnion((1 << BasicTypeCode.BT_INT.code) - | (1 << BasicTypeCode.BT_FLOAT.code) - | (1 << BasicTypeCode.BT_DECIMAL.code)); - public static final SemType BYTE = IntSubtype.intWidthUnsigned(8); - public static final SemType STRING_CHAR = StringSubtype.stringChar(); - - public static final SemType XML_ELEMENT = xmlSingleton(XML_PRIMITIVE_ELEMENT_RO | XML_PRIMITIVE_ELEMENT_RW); - public static final SemType XML_COMMENT = xmlSingleton(XML_PRIMITIVE_COMMENT_RO | XML_PRIMITIVE_COMMENT_RW); - public static final SemType XML_TEXT = xmlSequence(xmlSingleton(XML_PRIMITIVE_TEXT)); - public static final SemType XML_PI = xmlSingleton(XML_PRIMITIVE_PI_RO | XML_PRIMITIVE_PI_RW); - - public static final int BDD_REC_ATOM_READONLY = 0; - // represents both readonly & map and readonly & readonly[] - public static final BddNode BDD_SUBTYPE_RO = bddAtom(RecAtom.createRecAtom(BDD_REC_ATOM_READONLY)); - // represents (map)[] - public static final ComplexSemType MAPPING_RO = basicSubtype(BT_MAPPING, BDD_SUBTYPE_RO); - - public static final CellAtomicType CELL_ATOMIC_VAL = predefinedTypeEnv.cellAtomicVal(); - public static final TypeAtom ATOM_CELL_VAL = predefinedTypeEnv.atomCellVal(); - - public static final CellAtomicType CELL_ATOMIC_NEVER = predefinedTypeEnv.cellAtomicNever(); - public static final TypeAtom ATOM_CELL_NEVER = predefinedTypeEnv.atomCellNever(); - - public static final CellAtomicType CELL_ATOMIC_INNER = predefinedTypeEnv.cellAtomicInner(); - public static final TypeAtom ATOM_CELL_INNER = predefinedTypeEnv.atomCellInner(); - - public static final CellAtomicType CELL_ATOMIC_UNDEF = predefinedTypeEnv.cellAtomicUndef(); - public static final TypeAtom ATOM_CELL_UNDEF = predefinedTypeEnv.atomCellUndef(); - - static final CellSemType CELL_SEMTYPE_INNER = (CellSemType) basicSubtype(BT_CELL, bddAtom(ATOM_CELL_INNER)); - public static final MappingAtomicType MAPPING_ATOMIC_INNER = MappingAtomicType.from( - new String[]{}, new CellSemType[]{}, CELL_SEMTYPE_INNER - ); - public static final ListAtomicType LIST_ATOMIC_INNER = ListAtomicType.from( - FixedLengthArray.empty(), CELL_SEMTYPE_INNER - ); - - public static final CellAtomicType CELL_ATOMIC_INNER_MAPPING = predefinedTypeEnv.cellAtomicInnerMapping(); - public static final TypeAtom ATOM_CELL_INNER_MAPPING = predefinedTypeEnv.atomCellInnerMapping(); - public static final CellSemType CELL_SEMTYPE_INNER_MAPPING = (CellSemType) basicSubtype( - BT_CELL, bddAtom(ATOM_CELL_INNER_MAPPING) - ); - - public static final ListAtomicType LIST_ATOMIC_MAPPING = predefinedTypeEnv.listAtomicMapping(); - static final TypeAtom ATOM_LIST_MAPPING = predefinedTypeEnv.atomListMapping(); - // represents (map)[] - public static final BddNode LIST_SUBTYPE_MAPPING = bddAtom(ATOM_LIST_MAPPING); - - public static final CellAtomicType CELL_ATOMIC_INNER_MAPPING_RO = predefinedTypeEnv.cellAtomicInnerMappingRO(); - public static final TypeAtom ATOM_CELL_INNER_MAPPING_RO = predefinedTypeEnv.atomCellInnerMappingRO(); - - public static final CellSemType CELL_SEMTYPE_INNER_MAPPING_RO = (CellSemType) basicSubtype( - BT_CELL, bddAtom(ATOM_CELL_INNER_MAPPING_RO) - ); - - public static final ListAtomicType LIST_ATOMIC_MAPPING_RO = predefinedTypeEnv.listAtomicMappingRO(); - static final TypeAtom ATOM_LIST_MAPPING_RO = predefinedTypeEnv.atomListMappingRO(); - // represents readonly & (map)[] - static final BddNode LIST_SUBTYPE_MAPPING_RO = bddAtom(ATOM_LIST_MAPPING_RO); - - static final CellSemType CELL_SEMTYPE_VAL = (CellSemType) basicSubtype(BT_CELL, bddAtom(ATOM_CELL_VAL)); - static final CellSemType CELL_SEMTYPE_UNDEF = (CellSemType) basicSubtype(BT_CELL, bddAtom(ATOM_CELL_UNDEF)); - private static final TypeAtom ATOM_CELL_OBJECT_MEMBER_KIND = predefinedTypeEnv.atomCellObjectMemberKind(); - static final CellSemType CELL_SEMTYPE_OBJECT_MEMBER_KIND = (CellSemType) basicSubtype( - BT_CELL, bddAtom(ATOM_CELL_OBJECT_MEMBER_KIND) - ); - - private static final TypeAtom ATOM_CELL_OBJECT_MEMBER_VISIBILITY = - predefinedTypeEnv.atomCellObjectMemberVisibility(); - static final CellSemType CELL_SEMTYPE_OBJECT_MEMBER_VISIBILITY = (CellSemType) basicSubtype( - BT_CELL, bddAtom(ATOM_CELL_OBJECT_MEMBER_VISIBILITY) - ); - - public static final TypeAtom ATOM_MAPPING_OBJECT_MEMBER = predefinedTypeEnv.atomMappingObjectMember(); - - static final ComplexSemType MAPPING_SEMTYPE_OBJECT_MEMBER = - basicSubtype(BT_MAPPING, bddAtom(ATOM_MAPPING_OBJECT_MEMBER)); - - public static final TypeAtom ATOM_CELL_OBJECT_MEMBER = predefinedTypeEnv.atomCellObjectMember(); - static final CellSemType CELL_SEMTYPE_OBJECT_MEMBER = - (CellSemType) basicSubtype(BT_CELL, bddAtom(ATOM_CELL_OBJECT_MEMBER)); - - static final CellSemType CELL_SEMTYPE_OBJECT_QUALIFIER = CELL_SEMTYPE_VAL; - public static final TypeAtom ATOM_MAPPING_OBJECT = predefinedTypeEnv.atomMappingObject(); - public static final BddNode MAPPING_SUBTYPE_OBJECT = bddAtom(ATOM_MAPPING_OBJECT); - - private static final int BDD_REC_ATOM_OBJECT_READONLY = 1; - - private static final RecAtom OBJECT_RO_REC_ATOM = RecAtom.createRecAtom(BDD_REC_ATOM_OBJECT_READONLY); - - public static final BddNode MAPPING_SUBTYPE_OBJECT_RO = bddAtom(OBJECT_RO_REC_ATOM); - - public static final ComplexSemType MAPPING_ARRAY_RO = basicSubtype(BT_LIST, LIST_SUBTYPE_MAPPING_RO); - public static final TypeAtom ATOM_CELL_MAPPING_ARRAY_RO = predefinedTypeEnv.atomCellMappingArrayRO(); - public static final CellSemType CELL_SEMTYPE_LIST_SUBTYPE_MAPPING_RO = (CellSemType) basicSubtype( - BT_CELL, bddAtom(ATOM_CELL_MAPPING_ARRAY_RO) - ); - - static final TypeAtom ATOM_LIST_THREE_ELEMENT_RO = predefinedTypeEnv.atomListThreeElementRO(); - // represents [(readonly & map)[], any|error, any|error] - public static final BddNode LIST_SUBTYPE_THREE_ELEMENT_RO = bddAtom(ATOM_LIST_THREE_ELEMENT_RO); - - public static final SemType VAL_READONLY = createComplexSemType(VT_INHERENTLY_IMMUTABLE, - BasicSubtype.from(BT_LIST, BDD_SUBTYPE_RO), - BasicSubtype.from(BT_MAPPING, BDD_SUBTYPE_RO), - BasicSubtype.from(BT_TABLE, LIST_SUBTYPE_THREE_ELEMENT_RO), - BasicSubtype.from(BT_XML, XML_SUBTYPE_RO), - BasicSubtype.from(BT_OBJECT, MAPPING_SUBTYPE_OBJECT_RO) - ); - - public static final SemType INNER_READONLY = union(VAL_READONLY, UNDEF); - public static final CellAtomicType CELL_ATOMIC_INNER_RO = predefinedTypeEnv.cellAtomicInnerRO(); - public static final TypeAtom ATOM_CELL_INNER_RO = predefinedTypeEnv.atomCellInnerRO(); - public static final CellSemType CELL_SEMTYPE_INNER_RO = (CellSemType) basicSubtype( - BT_CELL, bddAtom(ATOM_CELL_INNER_RO) - ); - public static final TypeAtom ATOM_CELL_VAL_RO = predefinedTypeEnv.atomCellValRO(); - - static final CellSemType CELL_SEMTYPE_VAL_RO = - (CellSemType) basicSubtype(BT_CELL, bddAtom(ATOM_CELL_VAL_RO)); - - public static final TypeAtom ATOM_MAPPING_OBJECT_MEMBER_RO = predefinedTypeEnv.atomMappingObjectMemberRO(); - static final ComplexSemType MAPPING_SEMTYPE_OBJECT_MEMBER_RO = - basicSubtype(BT_MAPPING, bddAtom(ATOM_MAPPING_OBJECT_MEMBER_RO)); - - private static final TypeAtom ATOM_CELL_OBJECT_MEMBER_RO = predefinedTypeEnv.atomCellObjectMemberRO(); - static final CellSemType CELL_SEMTYPE_OBJECT_MEMBER_RO = - (CellSemType) basicSubtype(BT_CELL, bddAtom(ATOM_CELL_OBJECT_MEMBER_RO)); - - public static final ListAtomicType LIST_ATOMIC_TWO_ELEMENT = predefinedTypeEnv.listAtomicTwoElement(); - static final TypeAtom ATOM_LIST_TWO_ELEMENT = predefinedTypeEnv.atomListTwoElement(); - // represents [any|error, any|error] - public static final BddNode LIST_SUBTYPE_TWO_ELEMENT = bddAtom(ATOM_LIST_TWO_ELEMENT); - - public static final ComplexSemType MAPPING_ARRAY = basicSubtype(BT_LIST, LIST_SUBTYPE_MAPPING); - public static final TypeAtom ATOM_CELL_MAPPING_ARRAY = predefinedTypeEnv.atomCellMappingArray(); - public static final CellSemType CELL_SEMTYPE_LIST_SUBTYPE_MAPPING = (CellSemType) basicSubtype( - BT_CELL, bddAtom(ATOM_CELL_MAPPING_ARRAY) - ); - static final TypeAtom ATOM_LIST_THREE_ELEMENT = predefinedTypeEnv.atomListThreeElement(); - // represents [(map)[], any|error, any|error] - public static final BddNode LIST_SUBTYPE_THREE_ELEMENT = bddAtom(ATOM_LIST_THREE_ELEMENT); - - public static final MappingAtomicType MAPPING_ATOMIC_RO = predefinedTypeEnv.mappingAtomicRO(); - public static final MappingAtomicType MAPPING_ATOMIC_OBJECT_RO = predefinedTypeEnv.getMappingAtomicObjectRO(); - - public static final ListAtomicType LIST_ATOMIC_RO = predefinedTypeEnv.listAtomicRO(); - - private PredefinedType() { - } - - // Union of complete basic types - // bits is bit vector indexed by BasicTypeCode - // I would like to make the arg int:Unsigned32 - // but are language/impl bugs that make this not work well - static BasicTypeBitSet basicTypeUnion(int bitset) { - return BasicTypeBitSet.from(bitset); - } - - public static BasicTypeBitSet basicType(BasicTypeCode code) { - return BasicTypeBitSet.from(1 << code.code); - } - - public static ComplexSemType basicSubtype(BasicTypeCode code, ProperSubtypeData data) { - // TODO: We need a more efficient way to do this - if (code.equals(BT_CELL)) { - return CellSemType.from(new ProperSubtypeData[]{data}); - } - return ComplexSemType.createComplexSemType(0, BasicSubtype.from(code, data)); - } - - static String toString(int bitset) { - StringJoiner sj = new StringJoiner("|", Integer.toBinaryString(bitset) + "[", "]"); - - addIfBitSet(sj, bitset, NEVER.bitset, "never"); - addIfBitSet(sj, bitset, NIL.bitset, "nil"); - addIfBitSet(sj, bitset, BOOLEAN.bitset, "boolean"); - addIfBitSet(sj, bitset, INT.bitset, "int"); - addIfBitSet(sj, bitset, FLOAT.bitset, "float"); - addIfBitSet(sj, bitset, DECIMAL.bitset, "decimal"); - addIfBitSet(sj, bitset, STRING.bitset, "string"); - addIfBitSet(sj, bitset, ERROR.bitset, "error"); - addIfBitSet(sj, bitset, TYPEDESC.bitset, "typedesc"); - addIfBitSet(sj, bitset, HANDLE.bitset, "handle"); - addIfBitSet(sj, bitset, FUNCTION.bitset, "function"); - addIfBitSet(sj, bitset, REGEXP.bitset, "regexp"); - addIfBitSet(sj, bitset, FUTURE.bitset, "future"); - addIfBitSet(sj, bitset, STREAM.bitset, "stream"); - addIfBitSet(sj, bitset, LIST.bitset, "list"); - addIfBitSet(sj, bitset, MAPPING.bitset, "map"); - addIfBitSet(sj, bitset, TABLE.bitset, "table"); - addIfBitSet(sj, bitset, XML.bitset, "xml"); - addIfBitSet(sj, bitset, OBJECT.bitset, "object"); - addIfBitSet(sj, bitset, CELL.bitset, "cell"); - addIfBitSet(sj, bitset, UNDEF.bitset, "undef"); - return sj.toString(); - } - - private static void addIfBitSet(StringJoiner sj, int bitset, int bitToBeCheck, String strToBeAdded) { - if ((bitset & bitToBeCheck) != 0) { - sj.add(strToBeAdded); - } - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/PredefinedTypeEnv.java b/semtypes/src/main/java/io/ballerina/types/PredefinedTypeEnv.java deleted file mode 100644 index 7ca357ba04e1..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/PredefinedTypeEnv.java +++ /dev/null @@ -1,645 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.types; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicInteger; - -import static io.ballerina.types.Core.union; -import static io.ballerina.types.PredefinedType.CELL_SEMTYPE_INNER_MAPPING; -import static io.ballerina.types.PredefinedType.CELL_SEMTYPE_INNER_MAPPING_RO; -import static io.ballerina.types.PredefinedType.CELL_SEMTYPE_INNER_RO; -import static io.ballerina.types.PredefinedType.CELL_SEMTYPE_LIST_SUBTYPE_MAPPING; -import static io.ballerina.types.PredefinedType.CELL_SEMTYPE_LIST_SUBTYPE_MAPPING_RO; -import static io.ballerina.types.PredefinedType.CELL_SEMTYPE_OBJECT_MEMBER; -import static io.ballerina.types.PredefinedType.CELL_SEMTYPE_OBJECT_MEMBER_KIND; -import static io.ballerina.types.PredefinedType.CELL_SEMTYPE_OBJECT_MEMBER_RO; -import static io.ballerina.types.PredefinedType.CELL_SEMTYPE_OBJECT_MEMBER_VISIBILITY; -import static io.ballerina.types.PredefinedType.CELL_SEMTYPE_OBJECT_QUALIFIER; -import static io.ballerina.types.PredefinedType.CELL_SEMTYPE_UNDEF; -import static io.ballerina.types.PredefinedType.CELL_SEMTYPE_VAL; -import static io.ballerina.types.PredefinedType.CELL_SEMTYPE_VAL_RO; -import static io.ballerina.types.PredefinedType.INNER; -import static io.ballerina.types.PredefinedType.INNER_READONLY; -import static io.ballerina.types.PredefinedType.MAPPING; -import static io.ballerina.types.PredefinedType.MAPPING_ARRAY; -import static io.ballerina.types.PredefinedType.MAPPING_ARRAY_RO; -import static io.ballerina.types.PredefinedType.MAPPING_RO; -import static io.ballerina.types.PredefinedType.MAPPING_SEMTYPE_OBJECT_MEMBER; -import static io.ballerina.types.PredefinedType.MAPPING_SEMTYPE_OBJECT_MEMBER_RO; -import static io.ballerina.types.PredefinedType.NEVER; -import static io.ballerina.types.PredefinedType.UNDEF; -import static io.ballerina.types.PredefinedType.VAL; -import static io.ballerina.types.PredefinedType.VAL_READONLY; -import static io.ballerina.types.SemTypes.stringConst; -import static io.ballerina.types.TypeAtom.createTypeAtom; - -/** - * This is a utility class used to create various type atoms that needs to be initialized without an environment and - * common to all environments. When we construct an {@code Env}, we can use {@code initializeEnv} to populate it with - * those atoms. - * NOTE: While this class lazy initialize all the atoms technically {@code PredefinedType} will cause it initialize - * all the atoms currently. - * @since 2201.10.0 - */ -public final class PredefinedTypeEnv { - - private PredefinedTypeEnv() { - } - - // Due to some reason spot bug thinks we are returning an array via getInstance(), if this is not public - public static final PredefinedTypeEnv INSTANCE = new PredefinedTypeEnv(); - - public static PredefinedTypeEnv getInstance() { - return INSTANCE; - } - - private final List> initializedCellAtoms = new ArrayList<>(); - private final List> initializedListAtoms = new ArrayList<>(); - private final List> initializedMappingAtoms = new ArrayList<>(); - private final List initializedRecListAtoms = new ArrayList<>(); - private final List initializedRecMappingAtoms = new ArrayList<>(); - private final AtomicInteger nextAtomIndex = new AtomicInteger(0); - - // This is to avoid passing down env argument when doing cell type operations. - // Please refer to the cellSubtypeDataEnsureProper() in cell.bal - private CellAtomicType cellAtomicVal; - private CellAtomicType cellAtomicNever; - - // Represent the typeAtom required to construct equivalent subtypes of map and (any|error)[]. - private CellAtomicType callAtomicInner; - - // TypeAtoms related to (map)[]. This is to avoid passing down env argument when doing - // tableSubtypeComplement operation. - private CellAtomicType cellAtomicInnerMapping; - private ListAtomicType listAtomicMapping; - - // TypeAtoms related to readonly type. This is to avoid requiring context when referring to readonly type. - // CELL_ATOMIC_INNER_MAPPING_RO & LIST_ATOMIC_MAPPING_RO are typeAtoms required to construct - // readonly & (map)[] which is then used for readonly table type when constructing VAL_READONLY - private CellAtomicType cellAtomicInnerMappingRO; - private ListAtomicType listAtomicMappingRO; - private CellAtomicType cellAtomicInnerRO; - private ListAtomicType listAtomicThreeElementRO; - private CellAtomicType cellAtomicMappingArrayRO; - - // TypeAtoms related to [any|error, any|error]. This is to avoid passing down env argument when doing - // streamSubtypeComplement operation. - private CellAtomicType cellAtomicUndef; - private ListAtomicType listAtomicTwoElement; - - // TypeAtoms related to [(map)[], any|error, any|error]. This is to avoid passing down env argument - // when doing tableSubtypeComplement operation. - private CellAtomicType cellAtomicMappingArray; - private ListAtomicType listAtomicThreeElement; - - private CellAtomicType cellAtomicObjectMember; - private CellAtomicType cellAtomicObjectMemberKind; - private CellAtomicType cellAtomicObjectMemberRO; - private CellAtomicType cellAtomicObjectMemberVisibility; - private CellAtomicType cellAtomicValRO; - private ListAtomicType listAtomicRO; - private MappingAtomicType mappingAtomicObject; - private MappingAtomicType mappingAtomicObjectMember; - private MappingAtomicType mappingAtomicObjectMemberRO; - private MappingAtomicType mappingAtomicObjectRO; - private MappingAtomicType mappingAtomicRO; - private TypeAtom atomCellInner; - private TypeAtom atomCellInnerMapping; - private TypeAtom atomCellInnerMappingRO; - private TypeAtom atomCellInnerRO; - private TypeAtom atomCellNever; - private TypeAtom atomCellObjectMember; - private TypeAtom atomCellObjectMemberKind; - private TypeAtom atomCellObjectMemberRO; - private TypeAtom atomCellObjectMemberVisibility; - private TypeAtom atomCellUndef; - private TypeAtom atomCellVal; - private TypeAtom atomCellValRO; - private TypeAtom atomListMapping; - private TypeAtom atomListMappingRO; - private TypeAtom atomListTwoElement; - private TypeAtom atomMappingObject; - private TypeAtom atomMappingObjectMember; - private TypeAtom atomMappingObjectMemberRO; - private TypeAtom atomCellMappingArray; - private TypeAtom atomCellMappingArrayRO; - private TypeAtom atomListThreeElement; - private TypeAtom atomListThreeElementRO; - - private void addInitializedCellAtom(CellAtomicType atom) { - addInitializedAtom(initializedCellAtoms, atom); - } - - private void addInitializedListAtom(ListAtomicType atom) { - addInitializedAtom(initializedListAtoms, atom); - } - - private void addInitializedMapAtom(MappingAtomicType atom) { - addInitializedAtom(initializedMappingAtoms, atom); - } - - private void addInitializedAtom(Collection> atoms, E atom) { - atoms.add(new InitializedTypeAtom<>(atom, nextAtomIndex.getAndIncrement())); - } - - private int cellAtomIndex(CellAtomicType atom) { - return atomIndex(initializedCellAtoms, atom); - } - - private int listAtomIndex(ListAtomicType atom) { - return atomIndex(initializedListAtoms, atom); - } - - private int mappingAtomIndex(MappingAtomicType atom) { - return atomIndex(initializedMappingAtoms, atom); - } - - private int atomIndex(List> initializedAtoms, E atom) { - for (InitializedTypeAtom initializedListAtom : initializedAtoms) { - if (initializedListAtom.atomicType() == atom) { - return initializedListAtom.index(); - } - } - throw new IndexOutOfBoundsException(); - } - - synchronized CellAtomicType cellAtomicVal() { - if (cellAtomicVal == null) { - cellAtomicVal = CellAtomicType.from(VAL, CellAtomicType.CellMutability.CELL_MUT_LIMITED); - addInitializedCellAtom(cellAtomicVal); - } - return cellAtomicVal; - } - - synchronized TypeAtom atomCellVal() { - if (atomCellVal == null) { - CellAtomicType cellAtomicVal = cellAtomicVal(); - atomCellVal = createTypeAtom(cellAtomIndex(cellAtomicVal), cellAtomicVal); - } - return atomCellVal; - } - - synchronized CellAtomicType cellAtomicNever() { - if (cellAtomicNever == null) { - cellAtomicNever = CellAtomicType.from(NEVER, CellAtomicType.CellMutability.CELL_MUT_LIMITED); - addInitializedCellAtom(cellAtomicNever); - } - return cellAtomicNever; - } - - synchronized TypeAtom atomCellNever() { - if (atomCellNever == null) { - CellAtomicType cellAtomicNever = cellAtomicNever(); - atomCellNever = createTypeAtom(cellAtomIndex(cellAtomicNever), cellAtomicNever); - } - return atomCellNever; - } - - synchronized CellAtomicType cellAtomicInner() { - if (callAtomicInner == null) { - callAtomicInner = CellAtomicType.from(INNER, CellAtomicType.CellMutability.CELL_MUT_LIMITED); - addInitializedCellAtom(callAtomicInner); - } - return callAtomicInner; - } - - synchronized TypeAtom atomCellInner() { - if (atomCellInner == null) { - CellAtomicType cellAtomicInner = cellAtomicInner(); - atomCellInner = createTypeAtom(cellAtomIndex(cellAtomicInner), cellAtomicInner); - } - return atomCellInner; - } - - synchronized CellAtomicType cellAtomicInnerMapping() { - if (cellAtomicInnerMapping == null) { - cellAtomicInnerMapping = - CellAtomicType.from(union(MAPPING, UNDEF), CellAtomicType.CellMutability.CELL_MUT_LIMITED); - addInitializedCellAtom(cellAtomicInnerMapping); - } - return cellAtomicInnerMapping; - } - - synchronized TypeAtom atomCellInnerMapping() { - if (atomCellInnerMapping == null) { - CellAtomicType cellAtomicInnerMapping = cellAtomicInnerMapping(); - atomCellInnerMapping = createTypeAtom(cellAtomIndex(cellAtomicInnerMapping), cellAtomicInnerMapping); - } - return atomCellInnerMapping; - } - - synchronized CellAtomicType cellAtomicInnerMappingRO() { - if (cellAtomicInnerMappingRO == null) { - cellAtomicInnerMappingRO = - CellAtomicType.from(union(MAPPING_RO, UNDEF), CellAtomicType.CellMutability.CELL_MUT_LIMITED); - addInitializedCellAtom(cellAtomicInnerMappingRO); - } - return cellAtomicInnerMappingRO; - } - - synchronized TypeAtom atomCellInnerMappingRO() { - if (atomCellInnerMappingRO == null) { - CellAtomicType cellAtomicInnerMappingRO = cellAtomicInnerMappingRO(); - atomCellInnerMappingRO = - createTypeAtom(cellAtomIndex(cellAtomicInnerMappingRO), cellAtomicInnerMappingRO); - } - return atomCellInnerMappingRO; - } - - synchronized ListAtomicType listAtomicMapping() { - if (listAtomicMapping == null) { - listAtomicMapping = ListAtomicType.from( - FixedLengthArray.empty(), CELL_SEMTYPE_INNER_MAPPING - ); - addInitializedListAtom(listAtomicMapping); - } - return listAtomicMapping; - } - - synchronized TypeAtom atomListMapping() { - if (atomListMapping == null) { - ListAtomicType listAtomicMapping = listAtomicMapping(); - atomListMapping = createTypeAtom(listAtomIndex(listAtomicMapping), listAtomicMapping); - } - return atomListMapping; - } - - synchronized ListAtomicType listAtomicMappingRO() { - if (listAtomicMappingRO == null) { - listAtomicMappingRO = ListAtomicType.from(FixedLengthArray.empty(), CELL_SEMTYPE_INNER_MAPPING_RO); - addInitializedListAtom(listAtomicMappingRO); - } - return listAtomicMappingRO; - } - - synchronized TypeAtom atomListMappingRO() { - if (atomListMappingRO == null) { - ListAtomicType listAtomicMappingRO = listAtomicMappingRO(); - atomListMappingRO = createTypeAtom(listAtomIndex(listAtomicMappingRO), listAtomicMappingRO); - } - return atomListMappingRO; - } - - synchronized CellAtomicType cellAtomicInnerRO() { - if (cellAtomicInnerRO == null) { - cellAtomicInnerRO = CellAtomicType.from(INNER_READONLY, CellAtomicType.CellMutability.CELL_MUT_NONE); - addInitializedCellAtom(cellAtomicInnerRO); - } - return cellAtomicInnerRO; - } - - synchronized TypeAtom atomCellInnerRO() { - if (atomCellInnerRO == null) { - CellAtomicType cellAtomicInnerRO = cellAtomicInnerRO(); - atomCellInnerRO = createTypeAtom(cellAtomIndex(cellAtomicInnerRO), cellAtomicInnerRO); - } - return atomCellInnerRO; - } - - synchronized CellAtomicType cellAtomicUndef() { - if (cellAtomicUndef == null) { - cellAtomicUndef = CellAtomicType.from(UNDEF, CellAtomicType.CellMutability.CELL_MUT_NONE); - addInitializedCellAtom(cellAtomicUndef); - } - return cellAtomicUndef; - } - - synchronized TypeAtom atomCellUndef() { - if (atomCellUndef == null) { - CellAtomicType cellAtomicUndef = cellAtomicUndef(); - atomCellUndef = createTypeAtom(cellAtomIndex(cellAtomicUndef), cellAtomicUndef); - } - return atomCellUndef; - } - - synchronized ListAtomicType listAtomicTwoElement() { - if (listAtomicTwoElement == null) { - listAtomicTwoElement = - ListAtomicType.from(FixedLengthArray.from(List.of(CELL_SEMTYPE_VAL), 2), CELL_SEMTYPE_UNDEF); - addInitializedListAtom(listAtomicTwoElement); - } - return listAtomicTwoElement; - } - - synchronized TypeAtom atomListTwoElement() { - if (atomListTwoElement == null) { - ListAtomicType listAtomicTwoElement = listAtomicTwoElement(); - atomListTwoElement = createTypeAtom(listAtomIndex(listAtomicTwoElement), listAtomicTwoElement); - } - return atomListTwoElement; - } - - synchronized CellAtomicType cellAtomicValRO() { - if (cellAtomicValRO == null) { - cellAtomicValRO = CellAtomicType.from( - VAL_READONLY, CellAtomicType.CellMutability.CELL_MUT_NONE - ); - addInitializedCellAtom(cellAtomicValRO); - } - return cellAtomicValRO; - } - - synchronized TypeAtom atomCellValRO() { - if (atomCellValRO == null) { - CellAtomicType cellAtomicValRO = cellAtomicValRO(); - atomCellValRO = createTypeAtom(cellAtomIndex(cellAtomicValRO), cellAtomicValRO); - } - return atomCellValRO; - } - - synchronized MappingAtomicType mappingAtomicObjectMemberRO() { - if (mappingAtomicObjectMemberRO == null) { - mappingAtomicObjectMemberRO = MappingAtomicType.from( - new String[]{"kind", "value", "visibility"}, - new CellSemType[]{CELL_SEMTYPE_OBJECT_MEMBER_KIND, CELL_SEMTYPE_VAL_RO, - CELL_SEMTYPE_OBJECT_MEMBER_VISIBILITY}, - CELL_SEMTYPE_UNDEF); - addInitializedMapAtom(mappingAtomicObjectMemberRO); - } - return mappingAtomicObjectMemberRO; - } - - synchronized TypeAtom atomMappingObjectMemberRO() { - if (atomMappingObjectMemberRO == null) { - MappingAtomicType mappingAtomicObjectMemberRO = mappingAtomicObjectMemberRO(); - atomMappingObjectMemberRO = createTypeAtom(mappingAtomIndex(mappingAtomicObjectMemberRO), - mappingAtomicObjectMemberRO); - } - return atomMappingObjectMemberRO; - } - - synchronized CellAtomicType cellAtomicObjectMemberRO() { - if (cellAtomicObjectMemberRO == null) { - cellAtomicObjectMemberRO = CellAtomicType.from( - MAPPING_SEMTYPE_OBJECT_MEMBER_RO, CellAtomicType.CellMutability.CELL_MUT_NONE - ); - addInitializedCellAtom(cellAtomicObjectMemberRO); - } - return cellAtomicObjectMemberRO; - } - - synchronized TypeAtom atomCellObjectMemberRO() { - if (atomCellObjectMemberRO == null) { - CellAtomicType cellAtomicObjectMemberRO = cellAtomicObjectMemberRO(); - atomCellObjectMemberRO = createTypeAtom(cellAtomIndex(cellAtomicObjectMemberRO), cellAtomicObjectMemberRO); - } - return atomCellObjectMemberRO; - } - - synchronized CellAtomicType cellAtomicObjectMemberKind() { - if (cellAtomicObjectMemberKind == null) { - cellAtomicObjectMemberKind = CellAtomicType.from( - Core.union(stringConst("field"), stringConst("method")), - CellAtomicType.CellMutability.CELL_MUT_NONE - ); - addInitializedCellAtom(cellAtomicObjectMemberKind); - } - return cellAtomicObjectMemberKind; - } - - synchronized TypeAtom atomCellObjectMemberKind() { - if (atomCellObjectMemberKind == null) { - CellAtomicType cellAtomicObjectMemberKind = cellAtomicObjectMemberKind(); - atomCellObjectMemberKind = - createTypeAtom(cellAtomIndex(cellAtomicObjectMemberKind), cellAtomicObjectMemberKind); - } - return atomCellObjectMemberKind; - } - - synchronized CellAtomicType cellAtomicObjectMemberVisibility() { - if (cellAtomicObjectMemberVisibility == null) { - cellAtomicObjectMemberVisibility = CellAtomicType.from( - Core.union(stringConst("public"), stringConst("private")), - CellAtomicType.CellMutability.CELL_MUT_NONE - ); - addInitializedCellAtom(cellAtomicObjectMemberVisibility); - } - return cellAtomicObjectMemberVisibility; - } - - synchronized TypeAtom atomCellObjectMemberVisibility() { - if (atomCellObjectMemberVisibility == null) { - CellAtomicType cellAtomicObjectMemberVisibility = cellAtomicObjectMemberVisibility(); - atomCellObjectMemberVisibility = createTypeAtom(cellAtomIndex(cellAtomicObjectMemberVisibility), - cellAtomicObjectMemberVisibility); - } - return atomCellObjectMemberVisibility; - } - - synchronized MappingAtomicType mappingAtomicObjectMember() { - if (mappingAtomicObjectMember == null) { - mappingAtomicObjectMember = MappingAtomicType.from( - new String[]{"kind", "value", "visibility"}, - new CellSemType[]{CELL_SEMTYPE_OBJECT_MEMBER_KIND, CELL_SEMTYPE_VAL, - CELL_SEMTYPE_OBJECT_MEMBER_VISIBILITY}, - CELL_SEMTYPE_UNDEF); - ; - addInitializedMapAtom(mappingAtomicObjectMember); - } - return mappingAtomicObjectMember; - } - - synchronized TypeAtom atomMappingObjectMember() { - if (atomMappingObjectMember == null) { - MappingAtomicType mappingAtomicObjectMember = mappingAtomicObjectMember(); - atomMappingObjectMember = createTypeAtom(mappingAtomIndex(mappingAtomicObjectMember), - mappingAtomicObjectMember); - } - return atomMappingObjectMember; - } - - synchronized CellAtomicType cellAtomicObjectMember() { - if (cellAtomicObjectMember == null) { - cellAtomicObjectMember = CellAtomicType.from( - MAPPING_SEMTYPE_OBJECT_MEMBER, CellAtomicType.CellMutability.CELL_MUT_UNLIMITED - ); - addInitializedCellAtom(cellAtomicObjectMember); - } - return cellAtomicObjectMember; - } - - synchronized TypeAtom atomCellObjectMember() { - if (atomCellObjectMember == null) { - CellAtomicType cellAtomicObjectMember = cellAtomicObjectMember(); - atomCellObjectMember = createTypeAtom(cellAtomIndex(cellAtomicObjectMember), cellAtomicObjectMember); - } - return atomCellObjectMember; - } - - synchronized MappingAtomicType mappingAtomicObject() { - if (mappingAtomicObject == null) { - mappingAtomicObject = MappingAtomicType.from( - new String[]{"$qualifiers"}, new CellSemType[]{CELL_SEMTYPE_OBJECT_QUALIFIER}, - CELL_SEMTYPE_OBJECT_MEMBER - ); - addInitializedMapAtom(mappingAtomicObject); - } - return mappingAtomicObject; - } - - synchronized TypeAtom atomMappingObject() { - if (atomMappingObject == null) { - MappingAtomicType mappingAtomicObject = mappingAtomicObject(); - atomMappingObject = createTypeAtom(mappingAtomIndex(mappingAtomicObject), mappingAtomicObject); - } - return atomMappingObject; - } - - synchronized ListAtomicType listAtomicRO() { - if (listAtomicRO == null) { - listAtomicRO = ListAtomicType.from(FixedLengthArray.empty(), CELL_SEMTYPE_INNER_RO); - initializedRecListAtoms.add(listAtomicRO); - } - return listAtomicRO; - } - - synchronized MappingAtomicType mappingAtomicRO() { - if (mappingAtomicRO == null) { - mappingAtomicRO = MappingAtomicType.from(new String[]{}, new CellSemType[]{}, CELL_SEMTYPE_INNER_RO); - initializedRecMappingAtoms.add(mappingAtomicRO); - } - return mappingAtomicRO; - } - - synchronized MappingAtomicType getMappingAtomicObjectRO() { - if (mappingAtomicObjectRO == null) { - mappingAtomicObjectRO = MappingAtomicType.from( - new String[]{"$qualifiers"}, new CellSemType[]{CELL_SEMTYPE_OBJECT_QUALIFIER}, - CELL_SEMTYPE_OBJECT_MEMBER_RO - ); - initializedRecMappingAtoms.add(mappingAtomicObjectRO); - } - return mappingAtomicObjectRO; - } - - synchronized CellAtomicType cellAtomicMappingArray() { - if (cellAtomicMappingArray == null) { - cellAtomicMappingArray = CellAtomicType.from(MAPPING_ARRAY, CellAtomicType.CellMutability.CELL_MUT_LIMITED); - addInitializedCellAtom(cellAtomicMappingArray); - } - return cellAtomicMappingArray; - } - - synchronized TypeAtom atomCellMappingArray() { - if (atomCellMappingArray == null) { - CellAtomicType cellAtomicMappingArray = cellAtomicMappingArray(); - atomCellMappingArray = createTypeAtom(cellAtomIndex(cellAtomicMappingArray), cellAtomicMappingArray); - } - return atomCellMappingArray; - } - - synchronized CellAtomicType cellAtomicMappingArrayRO() { - if (cellAtomicMappingArrayRO == null) { - cellAtomicMappingArrayRO = CellAtomicType.from(MAPPING_ARRAY_RO, - CellAtomicType.CellMutability.CELL_MUT_LIMITED); - addInitializedCellAtom(cellAtomicMappingArrayRO); - } - return cellAtomicMappingArrayRO; - } - - synchronized TypeAtom atomCellMappingArrayRO() { - if (atomCellMappingArrayRO == null) { - CellAtomicType cellAtomicMappingArrayRO = cellAtomicMappingArrayRO(); - atomCellMappingArrayRO = createTypeAtom(cellAtomIndex(cellAtomicMappingArrayRO), cellAtomicMappingArrayRO); - } - return atomCellMappingArrayRO; - } - - synchronized ListAtomicType listAtomicThreeElement() { - if (listAtomicThreeElement == null) { - listAtomicThreeElement = - ListAtomicType.from(FixedLengthArray.from(List.of(CELL_SEMTYPE_LIST_SUBTYPE_MAPPING, - CELL_SEMTYPE_VAL), 3), - CELL_SEMTYPE_UNDEF); - addInitializedListAtom(listAtomicThreeElement); - } - return listAtomicThreeElement; - } - - synchronized TypeAtom atomListThreeElement() { - if (atomListThreeElement == null) { - ListAtomicType listAtomicThreeElement = listAtomicThreeElement(); - atomListThreeElement = createTypeAtom(listAtomIndex(listAtomicThreeElement), listAtomicThreeElement); - } - return atomListThreeElement; - } - - synchronized ListAtomicType listAtomicThreeElementRO() { - if (listAtomicThreeElementRO == null) { - listAtomicThreeElementRO = - ListAtomicType.from(FixedLengthArray.from(List.of(CELL_SEMTYPE_LIST_SUBTYPE_MAPPING_RO, - CELL_SEMTYPE_VAL), 3), CELL_SEMTYPE_UNDEF); - addInitializedListAtom(listAtomicThreeElementRO); - } - return listAtomicThreeElementRO; - } - - synchronized TypeAtom atomListThreeElementRO() { - if (atomListThreeElementRO == null) { - ListAtomicType listAtomicThreeElementRO = listAtomicThreeElementRO(); - atomListThreeElementRO = createTypeAtom(listAtomIndex(listAtomicThreeElementRO), listAtomicThreeElementRO); - } - return atomListThreeElementRO; - } - - // Due to some reason SpotBug thinks this method is overrideable if we don't put final here as well. - final void initializeEnv(Env env) { - fillRecAtoms(env.recListAtoms, initializedRecListAtoms); - fillRecAtoms(env.recMappingAtoms, initializedRecMappingAtoms); - initializedCellAtoms.forEach(each -> env.cellAtom(each.atomicType())); - initializedListAtoms.forEach(each -> env.listAtom(each.atomicType())); - } - - private void fillRecAtoms(List envRecAtomList, List initializedRecAtoms) { - int count = reservedRecAtomCount(); - for (int i = 0; i < count; i++) { - if (i < initializedRecAtoms.size()) { - envRecAtomList.add(initializedRecAtoms.get(i)); - } else { - // This is mainly to help with bir serialization/deserialization logic. Given the number of such atoms - // will be small this shouldn't be a problem. - envRecAtomList.add(null); - } - } - } - - public int reservedRecAtomCount() { - return Integer.max(initializedRecListAtoms.size(), initializedRecMappingAtoms.size()); - } - - private record InitializedTypeAtom(E atomicType, int index) { - - } - - public Optional getPredefinedRecAtom(int index) { - // NOTE: when adding new reserved rec atoms update the bir.ksy file as well - if (isPredefinedRecAtom(index)) { - return Optional.of(RecAtom.createRecAtom(index)); - } - return Optional.empty(); - } - - public boolean isPredefinedRecAtom(int index) { - return index >= 0 && index < reservedRecAtomCount(); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/RecAtom.java b/semtypes/src/main/java/io/ballerina/types/RecAtom.java deleted file mode 100644 index 6530e43a6588..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/RecAtom.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import static io.ballerina.types.PredefinedType.BDD_REC_ATOM_READONLY; - -/** - * Represent a recursive type atom. - * - * @since 2201.8.0 - */ -public class RecAtom implements Atom { - public final int index; - private Kind targetKind = null; - public static final RecAtom ZERO = new RecAtom(BDD_REC_ATOM_READONLY); - - private RecAtom(int index) { - this.index = index; - } - - private RecAtom(int index, Kind targetKind) { - this.index = index; - this.targetKind = targetKind; - } - - public static RecAtom createRecAtom(int index) { - if (index == BDD_REC_ATOM_READONLY) { - return ZERO; - } - return new RecAtom(index); - } - - public static RecAtom createXMLRecAtom(int index) { - return new RecAtom(index, Kind.XML_ATOM); - } - - public static RecAtom createDistinctRecAtom(int index) { - return new RecAtom(index, Kind.DISTINCT_ATOM); - } - - public void setKind(Kind targetKind) { - this.targetKind = targetKind; - } - - @Override - public int index() { - return index; - } - - @Override - public Kind kind() { - if (targetKind == null) { - throw new IllegalStateException("Target kind is not set for the recursive type atom"); - } - return targetKind; - } - - @Override - public int hashCode() { - if (targetKind == null) { - return index; - } else { - return getIdentifier().hashCode(); - } - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof RecAtom recAtom) { - return recAtom.index == this.index; - } - return false; - } - - @Override - public String toString() { - return "RecAtom{ index=" + index + ", targetKind=" + targetKind + '}'; - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/SemTypePair.java b/semtypes/src/main/java/io/ballerina/types/SemTypePair.java deleted file mode 100644 index 1a30f941796a..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/SemTypePair.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -/** - * Holds a pair of semtypes. - * - * @param t1 first semtype - * @param t2 second semtype - * @since 2201.11.0 - */ -public record SemTypePair(SemType t1, SemType t2) { - - public static SemTypePair from(SemType t1, SemType t2) { - assert t1 != null && t2 != null; - return new SemTypePair(t1, t2); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/SemTypes.java b/semtypes/src/main/java/io/ballerina/types/SemTypes.java deleted file mode 100644 index 037c9deac740..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/SemTypes.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import io.ballerina.types.definition.ObjectDefinition; -import io.ballerina.types.subtypedata.BooleanSubtype; -import io.ballerina.types.subtypedata.DecimalSubtype; -import io.ballerina.types.subtypedata.FloatSubtype; -import io.ballerina.types.subtypedata.FutureSubtype; -import io.ballerina.types.subtypedata.IntSubtype; -import io.ballerina.types.subtypedata.StringSubtype; -import io.ballerina.types.subtypedata.TableSubtype; -import io.ballerina.types.subtypedata.TypedescSubtype; -import io.ballerina.types.subtypedata.XmlSubtype; -import io.ballerina.types.typeops.ListProj; - -import java.math.BigDecimal; - -/** - * Public API for creating type values. - * - * @since 2201.8.0 - */ -public final class SemTypes { - public static final SemType SINT8 = IntSubtype.intWidthSigned(8); - public static final SemType SINT16 = IntSubtype.intWidthSigned(16); - public static final SemType SINT32 = IntSubtype.intWidthSigned(32); - public static final SemType UINT8 = PredefinedType.BYTE; - public static final SemType UINT16 = IntSubtype.intWidthUnsigned(16); - public static final SemType UINT32 = IntSubtype.intWidthUnsigned(32); - public static final SemType CHAR = PredefinedType.STRING_CHAR; - public static final SemType XML_ELEMENT = PredefinedType.XML_ELEMENT; - public static final SemType XML_COMMENT = PredefinedType.XML_COMMENT; - public static final SemType XML_TEXT = PredefinedType.XML_TEXT; - public static final SemType XML_PI = PredefinedType.XML_PI; - - public static SemType floatConst(double v) { - return FloatSubtype.floatConst(v); - } - - public static SemType intConst(long value) { - return IntSubtype.intConst(value); - } - - public static SemType stringConst(String value) { - return StringSubtype.stringConst(value); - } - - public static SemType booleanConst(boolean value) { - return BooleanSubtype.booleanConst(value); - } - - public static SemType decimalConst(String value) { - if (value.contains("d") || value.contains("D")) { - value = value.substring(0, value.length() - 1); - } - BigDecimal d = new BigDecimal(value); - return DecimalSubtype.decimalConst(d); - } - - public static SemType union(SemType t1, SemType t2) { - return Core.union(t1, t2); - } - - public static SemType union(SemType first, SemType second, SemType... rest) { - SemType u = Core.union(first, second); - for (SemType s : rest) { - u = Core.union(u, s); - } - return u; - } - - public static SemType intersect(SemType t1, SemType t2) { - return Core.intersect(t1, t2); - } - - public static SemType intersect(SemType first, SemType second, SemType... rest) { - SemType i = Core.intersect(first, second); - for (SemType s : rest) { - i = Core.intersect(i, s); - } - return i; - } - - public static boolean isSubtype(Context context, SemType t1, SemType t2) { - return Core.isSubtype(context, t1, t2); - } - - public static boolean isSubtypeSimple(SemType t1, BasicTypeBitSet t2) { - return Core.isSubtypeSimple(t1, t2); - } - - public static boolean isSubtypeSimpleNotNever(SemType t1, BasicTypeBitSet t2) { - return !Core.isNever(t1) && Core.isSubtypeSimple(t1, t2); - } - - public static boolean containsBasicType(SemType t1, BasicTypeBitSet t2) { - return (Core.widenToBasicTypes(t1).bitset & t2.bitset) != 0; - } - - public static boolean containsType(Context context, SemType type, SemType typeToBeContained) { - return Core.isSameType(context, Core.intersect(type, typeToBeContained), typeToBeContained); - } - - public static boolean isSameType(Context context, SemType t1, SemType t2) { - return Core.isSameType(context, t1, t2); - } - - public static SemType errorDetail(SemType detail) { - return Error.errorDetail(detail); - } - - public static SemType errorDistinct(int distinctId) { - return Error.errorDistinct(distinctId); - } - - public static SemType objectDistinct(int distinctId) { - return ObjectDefinition.distinct(distinctId); - } - - public static SemType tableContaining(Env env, SemType tableConstraint) { - return TableSubtype.tableContaining(env, tableConstraint); - } - - public static SemType tableContainingKeySpecifier(Context cx, SemType tableConstraint, String[] fieldNames) { - return TableSubtype.tableContainingKeySpecifier(cx, tableConstraint, fieldNames); - } - - public static SemType tableContainingKeyConstraint(Context cx, SemType tableConstraint, SemType keyConstraint) { - return TableSubtype.tableContainingKeyConstraint(cx, tableConstraint, keyConstraint); - } - - public static SemType futureContaining(Env env, SemType constraint) { - return FutureSubtype.futureContaining(env, constraint); - } - - public static SemType typedescContaining(Env env, SemType constraint) { - return TypedescSubtype.typedescContaining(env, constraint); - } - - public static SemType mappingMemberTypeInnerVal(Context context, SemType t, SemType m) { - return Core.mappingMemberTypeInnerVal(context, t, m); - } - - public static SemType listProj(Context context, SemType t, SemType key) { - return ListProj.listProjInnerVal(context, t, key); - } - - public static SemType listMemberType(Context context, SemType t, SemType key) { - return Core.listMemberTypeInnerVal(context, t, key); - } - - public static SemType xmlSequence(SemType t) { - return XmlSubtype.xmlSequence(t); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/TypeAtom.java b/semtypes/src/main/java/io/ballerina/types/TypeAtom.java deleted file mode 100644 index b83a82364a2c..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/TypeAtom.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -/** - * Represent a TypeAtom. - * - * @param index index of the type atom. This is unique within a given {@code Env}. {@code RecAtom}'s that refer to - * this type atom will also have the same index. - * @param atomicType atomic type representing the actual type represented by this atom. - * @since 2201.8.0 - */ -public record TypeAtom(int index, AtomicType atomicType) implements Atom { - - // Note: Whenever creating a 'TypeAtom', its 'atomicType' needs to be added to the 'Env.atomTable' - public static TypeAtom createTypeAtom(int index, AtomicType atomicType) { - assert index >= 0; - return new TypeAtom(index, atomicType); - } - - @Override - public int hashCode() { - return this.getIdentifier().hashCode(); - } - - @Override - public Kind kind() { - return atomicType.atomKind(); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/Value.java b/semtypes/src/main/java/io/ballerina/types/Value.java deleted file mode 100644 index 6408dd2f3383..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/Value.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -/** - * Represent `Value` type. - * - * @since 2201.8.0 - */ -public class Value { - public final Object value; - - private Value(Object value) { - this.value = value; - } - - public static Value from(Object value) { - return new Value(value); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/definition/CellField.java b/semtypes/src/main/java/io/ballerina/types/definition/CellField.java deleted file mode 100644 index df4a40fae836..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/definition/CellField.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.definition; - -import io.ballerina.types.CellSemType; - -/** - * Represents a cell field in a mapping type. - * - * @param name name of the field - * @param type cell-sem-type of the field - * @since 2201.10.0 - */ -public record CellField(String name, CellSemType type) { - - public static CellField from(String name, CellSemType type) { - return new CellField(name, type); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/definition/Field.java b/semtypes/src/main/java/io/ballerina/types/definition/Field.java deleted file mode 100644 index 288fc2374e2b..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/definition/Field.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.definition; - -import io.ballerina.types.SemType; - -/** - * Represent a field in a mapping type. - * - * @param name field name - * @param ty field type - * @param ro whether the field is readonly - * @param opt whether the field is optional - * @since 2201.10.0 - */ -public record Field(String name, SemType ty, boolean ro, boolean opt) { - - public static Field from(String name, SemType type, boolean ro, boolean opt) { - return new Field(name, type, ro, opt); - } - - @Override - public String toString() { - return "Field[" + - "name=" + name + ", " + - "ty=" + ty + ", " + - "ro=" + ro + ", " + - "opt=" + opt + ']'; - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/definition/FunctionDefinition.java b/semtypes/src/main/java/io/ballerina/types/definition/FunctionDefinition.java deleted file mode 100644 index e1c6c33df23b..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/definition/FunctionDefinition.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.definition; - -import io.ballerina.types.Atom; -import io.ballerina.types.BasicTypeCode; -import io.ballerina.types.ComplexSemType; -import io.ballerina.types.Definition; -import io.ballerina.types.Env; -import io.ballerina.types.FunctionAtomicType; -import io.ballerina.types.RecAtom; -import io.ballerina.types.SemType; -import io.ballerina.types.subtypedata.BddNode; - -import static io.ballerina.types.PredefinedType.basicSubtype; -import static io.ballerina.types.typeops.BddCommonOps.bddAtom; - -/** - * Represent function type desc. - * - * @since 2201.8.0 - */ -public final class FunctionDefinition implements Definition { - - private RecAtom rec; - private SemType semType; - - @Override - public SemType getSemType(Env env) { - if (semType != null) { - return semType; - } - RecAtom rec = env.recFunctionAtom(); - this.rec = rec; - return this.createSemType(rec); - } - - private SemType createSemType(Atom rec) { - BddNode bdd = bddAtom(rec); - ComplexSemType s = basicSubtype(BasicTypeCode.BT_FUNCTION, bdd); - this.semType = s; - return s; - } - - public SemType define(Env env, SemType args, SemType ret, FunctionQualifiers qualifiers) { - FunctionAtomicType atomicType = FunctionAtomicType.from(args, ret, qualifiers.semType()); - return defineInternal(env, atomicType); - } - - public SemType defineGeneric(Env env, SemType args, SemType ret, FunctionQualifiers qualifiers) { - FunctionAtomicType atomicType = FunctionAtomicType.genericFrom(args, ret, qualifiers.semType()); - return defineInternal(env, atomicType); - } - - private SemType defineInternal(Env env, FunctionAtomicType atomicType) { - Atom atom; - RecAtom rec = this.rec; - if (rec != null) { - atom = rec; - env.setRecFunctionAtomType(rec, atomicType); - } else { - atom = env.functionAtom(atomicType); - } - return this.createSemType(atom); - } - -} diff --git a/semtypes/src/main/java/io/ballerina/types/definition/FunctionQualifiers.java b/semtypes/src/main/java/io/ballerina/types/definition/FunctionQualifiers.java deleted file mode 100644 index 17e73aac75c4..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/definition/FunctionQualifiers.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package io.ballerina.types.definition; - -import io.ballerina.types.Core; -import io.ballerina.types.Env; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypes; - -import java.util.List; - -/** - * Wrapper class for the semtype representing the {@code function-quals} of a function. - * - * @param semType the semtype representing the function qualifiers - * @since 2201.10.0 - */ -public record FunctionQualifiers(SemType semType) { - - public FunctionQualifiers { - assert semType != null; - assert Core.isSubtypeSimple(semType, PredefinedType.LIST); - } - - public static FunctionQualifiers from(Env env, boolean isolated, boolean transactional) { - return new FunctionQualifiers(createSemType(env, isolated, transactional)); - } - - private static SemType createSemType(Env env, boolean isolated, boolean transactional) { - ListDefinition ld = new ListDefinition(); - return ld.defineListTypeWrapped(env, List.of( - isolated ? SemTypes.booleanConst(true) : PredefinedType.BOOLEAN, - transactional ? PredefinedType.BOOLEAN : SemTypes.booleanConst(false)), - 2); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/definition/ListDefinition.java b/semtypes/src/main/java/io/ballerina/types/definition/ListDefinition.java deleted file mode 100644 index e1b22ed82b1e..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/definition/ListDefinition.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.definition; - -import io.ballerina.types.Atom; -import io.ballerina.types.BasicTypeCode; -import io.ballerina.types.CellAtomicType; -import io.ballerina.types.CellSemType; -import io.ballerina.types.ComplexSemType; -import io.ballerina.types.Definition; -import io.ballerina.types.Env; -import io.ballerina.types.FixedLengthArray; -import io.ballerina.types.ListAtomicType; -import io.ballerina.types.RecAtom; -import io.ballerina.types.SemType; -import io.ballerina.types.subtypedata.BddNode; -import io.ballerina.types.typeops.BddCommonOps; - -import java.util.List; - -import static io.ballerina.types.CellAtomicType.CellMutability.CELL_MUT_LIMITED; -import static io.ballerina.types.CellAtomicType.CellMutability.CELL_MUT_NONE; -import static io.ballerina.types.Core.isNever; -import static io.ballerina.types.Core.union; -import static io.ballerina.types.PredefinedType.NEVER; -import static io.ballerina.types.PredefinedType.UNDEF; -import static io.ballerina.types.PredefinedType.basicSubtype; -import static io.ballerina.types.subtypedata.CellSubtype.cellContaining; - -/** - * Represent list/tuple type desc. - * - * @since 2201.8.0 - */ -public class ListDefinition implements Definition { - - private RecAtom rec = null; - private ComplexSemType semType = null; - - @Override - public SemType getSemType(Env env) { - ComplexSemType s = this.semType; - if (s == null) { - RecAtom rec = env.recListAtom(); - this.rec = rec; - return this.createSemType(env, rec); - } else { - return s; - } - } - - public SemType tupleTypeWrapped(Env env, SemType... members) { - return defineListTypeWrapped(env, List.of(members), members.length); - } - - public SemType tupleTypeWrappedRo(Env env, SemType... members) { - return defineListTypeWrapped(env, List.of(members), members.length, NEVER, CELL_MUT_NONE); - } - - - public SemType defineListTypeWrapped(Env env, List initial, int fixedLength, SemType rest, - CellAtomicType.CellMutability mut) { - assert rest != null; - List initialCells = initial.stream().map(t -> cellContaining(env, t, mut)).toList(); - CellSemType restCell = cellContaining(env, union(rest, UNDEF), isNever(rest) ? CELL_MUT_NONE : mut); - return define(env, initialCells, fixedLength, restCell); - } - - // Overload defineListTypeWrapped method for commonly used default parameter values - public SemType defineListTypeWrapped(Env env, List initial, int size) { - return defineListTypeWrapped(env, initial, size, NEVER, CELL_MUT_LIMITED); - } - - public SemType defineListTypeWrapped(Env env, List initial, int fixedLength, SemType rest) { - return defineListTypeWrapped(env, initial, fixedLength, rest, CELL_MUT_LIMITED); - } - - public SemType defineListTypeWrapped(Env env, SemType rest) { - return defineListTypeWrapped(env, List.of(), 0, rest); - } - - public SemType defineListTypeWrapped(Env env, SemType rest, CellAtomicType.CellMutability mut) { - return defineListTypeWrapped(env, List.of(), 0, rest, mut); - } - - public SemType defineListTypeWrapped(Env env, List initial, SemType rest) { - return defineListTypeWrapped(env, initial, initial.size(), rest, CELL_MUT_LIMITED); - } - - private ComplexSemType define(Env env, List initial, int fixedLength, CellSemType rest) { - assert rest != null; - FixedLengthArray members = fixedLengthNormalize(FixedLengthArray.from(initial, fixedLength)); - ListAtomicType atomicType = ListAtomicType.from(members, rest); - Atom atom; - RecAtom rec = this.rec; - if (rec != null) { - atom = rec; - env.setRecListAtomType(rec, atomicType); - } else { - atom = env.listAtom(atomicType); - } - return this.createSemType(env, atom); - } - - private FixedLengthArray fixedLengthNormalize(FixedLengthArray array) { - List initial = array.initial(); - int i = initial.size() - 1; - if (i <= 0) { - return array; - } - SemType last = initial.get(i); - i -= 1; - while (i >= 0) { - if (last != initial.get(i)) { - break; - } - i -= 1; - } - return FixedLengthArray.from(initial.subList(0, i + 2), array.fixedLength()); - } - - private ComplexSemType createSemType(Env env, Atom atom) { - BddNode bdd = BddCommonOps.bddAtom(atom); - ComplexSemType complexSemType = basicSubtype(BasicTypeCode.BT_LIST, bdd); - this.semType = complexSemType; - return complexSemType; - } - -} diff --git a/semtypes/src/main/java/io/ballerina/types/definition/MappingDefinition.java b/semtypes/src/main/java/io/ballerina/types/definition/MappingDefinition.java deleted file mode 100644 index 4c1e7bc0ee6e..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/definition/MappingDefinition.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.definition; - -import io.ballerina.types.Atom; -import io.ballerina.types.BasicTypeCode; -import io.ballerina.types.CellAtomicType; -import io.ballerina.types.CellSemType; -import io.ballerina.types.ComplexSemType; -import io.ballerina.types.Core; -import io.ballerina.types.Definition; -import io.ballerina.types.Env; -import io.ballerina.types.MappingAtomicType; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.RecAtom; -import io.ballerina.types.SemType; -import io.ballerina.types.subtypedata.BddNode; -import io.ballerina.types.typeops.BddCommonOps; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; - -import static io.ballerina.types.CellAtomicType.CellMutability.CELL_MUT_LIMITED; -import static io.ballerina.types.CellAtomicType.CellMutability.CELL_MUT_NONE; -import static io.ballerina.types.Core.union; -import static io.ballerina.types.PredefinedType.UNDEF; -import static io.ballerina.types.subtypedata.CellSubtype.cellContaining; - -/** - * Represent mapping type desc. - * - * @since 2201.8.0 - */ -public class MappingDefinition implements Definition { - - private RecAtom rec = null; - private SemType semType = null; - - @Override - public SemType getSemType(Env env) { - SemType s = this.semType; - if (s == null) { - RecAtom rec = env.recMappingAtom(); - this.rec = rec; - return this.createSemType(env, rec); - } else { - return s; - } - } - - /** - * This is a deviation from nBallerina. jBallerina considers `record {never x;}` as `never`. - * This method is to support jBallerina behavior. - */ - public void setSemTypeToNever() { - this.semType = PredefinedType.NEVER; - } - - public SemType define(Env env, List fields, CellSemType rest) { - SplitField sfh = splitFields(fields); - MappingAtomicType atomicType = MappingAtomicType.from(sfh.names.toArray(String[]::new), - sfh.types.toArray(CellSemType[]::new), rest); - Atom atom; - RecAtom rec = this.rec; - if (rec != null) { - atom = rec; - env.setRecMappingAtomType(rec, atomicType); - } else { - atom = env.mappingAtom(atomicType); - } - return this.createSemType(env, atom); - } - - public SemType defineMappingTypeWrapped(Env env, List fields, SemType rest) { - return defineMappingTypeWrapped(env, fields, rest, CELL_MUT_LIMITED); - } - - public SemType defineMappingTypeWrapped(Env env, List fields, SemType rest, - CellAtomicType.CellMutability mut) { - List cellFields = new ArrayList<>(fields.size()); - for (Field field : fields) { - SemType ty = field.ty(); - cellFields.add( - CellField.from(field.name(), cellContaining( - env, - field.opt() ? union(ty, UNDEF) : ty, - field.ro() ? CELL_MUT_NONE : mut - )) - ); - } - CellSemType restCell = cellContaining( - env, - union(rest, UNDEF), - Core.isNever(rest) ? CELL_MUT_NONE : mut - ); - return define(env, cellFields, restCell); - } - - private SemType createSemType(Env env, Atom atom) { - BddNode bdd = BddCommonOps.bddAtom(atom); - ComplexSemType s = PredefinedType.basicSubtype(BasicTypeCode.BT_MAPPING, bdd); - this.semType = s; - return s; - } - - private SplitField splitFields(List fields) { - CellField[] sortedFields = fields.toArray(CellField[]::new); - Arrays.sort(sortedFields, Comparator.comparing(MappingDefinition::fieldName)); - List names = new ArrayList<>(); - List types = new ArrayList<>(); - for (CellField field : sortedFields) { - names.add(field.name()); - types.add(field.type()); - } - return SplitField.from(names, types); - } - - private static String fieldName(CellField f) { - return f.name(); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/definition/Member.java b/semtypes/src/main/java/io/ballerina/types/definition/Member.java deleted file mode 100644 index f5d3f98244bb..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/definition/Member.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.types.definition; - -import io.ballerina.types.SemType; - -import static io.ballerina.types.SemTypes.stringConst; -import static io.ballerina.types.SemTypes.union; - -/** - * Represent a member of an object type definition. - * - * @param name member name - * @param valueTy member type - * @param kind is member a field or a method - * @param visibility is member private or public - * @param immutable is member readonly. If this is set valueTy must be a subtype of readonly - * @since 2201.10.0 - */ -public record Member(String name, SemType valueTy, Kind kind, Visibility visibility, boolean immutable) { - - public Member { - assert name != null && valueTy != null && kind != null && visibility != null; - } - - // Various "tag" values associated with a member. Each of these tag values must be convertible to a Field in Map - // type for the member - @FunctionalInterface - interface MemberTag { - - Field field(); - } - - public enum Kind implements MemberTag { - Field, - Method; - - // In nBallerina these are stings since they fit small strings. Maybe consider more efficient representation - // for java - private static final Field FIELD = new Field("kind", stringConst("field"), true, false); - private static final Field METHOD = new Field("kind", stringConst("method"), true, false); - - public Field field() { - return switch (this) { - case Field -> FIELD; - case Method -> METHOD; - }; - } - } - - public enum Visibility implements MemberTag { - Public, - Private; - - private static final SemType PUBLIC_TAG = stringConst("public"); - private static final Field PUBLIC = new Field("visibility", PUBLIC_TAG, true, false); - private static final SemType PRIVATE_TAG = stringConst("private"); - private static final Field PRIVATE = new Field("visibility", PRIVATE_TAG, true, false); - static final Field ALL = new Field("visibility", union(PRIVATE_TAG, PUBLIC_TAG), true, false); - - public Field field() { - return switch (this) { - case Public -> PUBLIC; - case Private -> PRIVATE; - }; - } - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/definition/ObjectDefinition.java b/semtypes/src/main/java/io/ballerina/types/definition/ObjectDefinition.java deleted file mode 100644 index 1ca827f1b038..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/definition/ObjectDefinition.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.types.definition; - -import io.ballerina.types.BasicTypeCode; -import io.ballerina.types.Bdd; -import io.ballerina.types.CellAtomicType; -import io.ballerina.types.CellSemType; -import io.ballerina.types.Core; -import io.ballerina.types.Definition; -import io.ballerina.types.Env; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SubtypeData; -import io.ballerina.types.subtypedata.BddNode; - -import java.util.Collection; -import java.util.List; -import java.util.stream.Stream; - -import static io.ballerina.types.BasicTypeCode.BT_OBJECT; -import static io.ballerina.types.Core.createBasicSemType; -import static io.ballerina.types.Core.union; -import static io.ballerina.types.PredefinedType.basicSubtype; -import static io.ballerina.types.RecAtom.createDistinctRecAtom; -import static io.ballerina.types.subtypedata.CellSubtype.cellContaining; -import static io.ballerina.types.typeops.BddCommonOps.bddAtom; - -/** - * Represent object type desc. - * - * @since 2201.10.0 - */ -public final class ObjectDefinition implements Definition { - - private final MappingDefinition mappingDefinition = new MappingDefinition(); - - public static SemType distinct(int distinctId) { - assert distinctId >= 0; - BddNode bdd = bddAtom(createDistinctRecAtom(-distinctId - 1)); - return basicSubtype(BT_OBJECT, bdd); - } - - // Each object type is represented as mapping type (with its basic type set to object) as fallows - // { - // "$qualifiers": { - // boolean isolated, - // "client"|"service" network - // }, - // [field_name]: { - // "field"|"method" kind, - // "public"|"private" visibility, - // VAL value; - // } - // ...{ - // "field" kind, - // "public"|"private" visibility, - // VAL value; - // } | { - // "method" kind, - // "public"|"private" visibility, - // FUNCTION value; - // } - // } - public SemType define(Env env, ObjectQualifiers qualifiers, Collection members) { - assert validataMembers(members); // This should never happen, so let's not run this in production - CellAtomicType.CellMutability mut = qualifiers.readonly() ? CellAtomicType.CellMutability.CELL_MUT_NONE : - CellAtomicType.CellMutability.CELL_MUT_LIMITED; - Stream memberStream = members.stream() - .map(member -> memberField(env, member, mut)); - Stream qualifierStream = Stream.of(qualifiers.field(env)); - SemType mappingType = mappingDefinition.define(env, Stream.concat(memberStream, qualifierStream).toList(), - restMemberType(env, mut, qualifiers.readonly())); - return objectContaining(mappingType); - } - - private static boolean validataMembers(Collection members) { - // Check if there are two members with same name - return members.stream().map(Member::name).distinct().count() == members.size(); - } - - private SemType objectContaining(SemType mappingType) { - SubtypeData bdd = Core.subtypeData(mappingType, BasicTypeCode.BT_MAPPING); - assert bdd instanceof Bdd; - return createBasicSemType(BT_OBJECT, bdd); - } - - private CellSemType restMemberType(Env env, CellAtomicType.CellMutability mut, boolean immutable) { - MappingDefinition fieldDefn = new MappingDefinition(); - SemType fieldMemberType = fieldDefn.defineMappingTypeWrapped( - env, - List.of( - new Field("value", immutable ? PredefinedType.VAL_READONLY : PredefinedType.VAL, - immutable, false), - Member.Kind.Field.field(), - Member.Visibility.ALL - ), - PredefinedType.NEVER); - - MappingDefinition methodDefn = new MappingDefinition(); - SemType methodMemberType = methodDefn.defineMappingTypeWrapped( - env, - List.of( - new Field("value", PredefinedType.FUNCTION, true, false), - Member.Kind.Method.field(), - Member.Visibility.ALL - ), - PredefinedType.NEVER); - return cellContaining(env, union(fieldMemberType, methodMemberType), mut); - } - - private static CellField memberField(Env env, Member member, CellAtomicType.CellMutability mut) { - MappingDefinition md = new MappingDefinition(); - CellAtomicType.CellMutability fieldMut = member.immutable() ? CellAtomicType.CellMutability.CELL_MUT_NONE : mut; - SemType semtype = md.defineMappingTypeWrapped( - env, - List.of( - new Field("value", member.valueTy(), member.immutable(), false), - member.kind().field(), - member.visibility().field() - ), - PredefinedType.NEVER); - return CellField.from(member.name(), cellContaining(env, semtype, fieldMut)); - } - - @Override - public SemType getSemType(Env env) { - return objectContaining(mappingDefinition.getSemType(env)); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/definition/ObjectQualifiers.java b/semtypes/src/main/java/io/ballerina/types/definition/ObjectQualifiers.java deleted file mode 100644 index 4f7bc17fd6a1..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/definition/ObjectQualifiers.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.types.definition; - -import io.ballerina.types.CellAtomicType; -import io.ballerina.types.Env; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; - -import java.util.List; - -import static io.ballerina.types.SemTypes.booleanConst; -import static io.ballerina.types.SemTypes.stringConst; -import static io.ballerina.types.SemTypes.union; -import static io.ballerina.types.subtypedata.CellSubtype.cellContaining; - -/** - * Represent {@code object-type-quals} in the spec. - * - * @param isolated is object isolated - * @param readonly represent {@code class readonly}. Note this is used to determining "rest" part of the object - * only {@code Member} types must be correctly set as intersection with readonly where - * applicable even with this set to true - * @param networkQualifier is object client, service or none - * @since 2201.10.0 - */ -public record ObjectQualifiers(boolean isolated, boolean readonly, NetworkQualifier networkQualifier) { - - private static final ObjectQualifiers DEFAULT = new ObjectQualifiers(false, false, NetworkQualifier.None); - - public static ObjectQualifiers defaultQualifiers() { - return DEFAULT; - } - - public static ObjectQualifiers from(boolean isolated, boolean readonly, NetworkQualifier networkQualifier) { - if (networkQualifier == NetworkQualifier.None && !isolated) { - return defaultQualifiers(); - } - return new ObjectQualifiers(isolated, readonly, networkQualifier); - } - - public enum NetworkQualifier { - Client, - Service, - None; - - private static final SemType CLIENT_TAG = stringConst("client"); - private static final Field CLIENT = new Field("network", CLIENT_TAG, true, false); - - private static final SemType SERVICE_TAG = stringConst("service"); - private static final Field SERVICE = new Field("network", SERVICE_TAG, true, false); - - // Object can't be both client and service, which is enforced by the enum. We are using a union here so that - // if this is none it matches both - private static final Field NONE = new Field("network", union(CLIENT_TAG, SERVICE_TAG), true, false); - - private Field field() { - return switch (this) { - case Client -> CLIENT; - case Service -> SERVICE; - case None -> NONE; - }; - } - } - - public CellField field(Env env) { - MappingDefinition md = new MappingDefinition(); - Field isolatedField = - new Field("isolated", isolated ? booleanConst(true) : PredefinedType.BOOLEAN, true, false); - Field networkField = networkQualifier.field(); - SemType ty = md.defineMappingTypeWrapped(env, List.of(isolatedField, networkField), PredefinedType.NEVER, - CellAtomicType.CellMutability.CELL_MUT_NONE); - - return CellField.from("$qualifiers", cellContaining(env, ty)); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/definition/SplitField.java b/semtypes/src/main/java/io/ballerina/types/definition/SplitField.java deleted file mode 100644 index 14a56ee7bafa..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/definition/SplitField.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.definition; - -import io.ballerina.types.CellSemType; - -import java.util.List; - -/** - * Holds the [string[], CellSemType[]] return type. - * - * @since 2201.10.0 - */ -public class SplitField { - public final List names; - public final List types; - - private SplitField(List strings, List semTypes) { - this.names = strings; - this.types = semTypes; - } - - public static SplitField from(List strings, List semTypes) { - return new SplitField(strings, semTypes); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/definition/StreamDefinition.java b/semtypes/src/main/java/io/ballerina/types/definition/StreamDefinition.java deleted file mode 100644 index dc700a5ecad4..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/definition/StreamDefinition.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.definition; - -import io.ballerina.types.Bdd; -import io.ballerina.types.Definition; -import io.ballerina.types.Env; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SubtypeData; - -import static io.ballerina.types.BasicTypeCode.BT_LIST; -import static io.ballerina.types.BasicTypeCode.BT_STREAM; -import static io.ballerina.types.Core.createBasicSemType; -import static io.ballerina.types.Core.subtypeData; - -/** - * Represent stream type desc. - * - * @since 2201.10.0 - */ -public final class StreamDefinition implements Definition { - - private final ListDefinition listDefinition = new ListDefinition(); - - @Override - public SemType getSemType(Env env) { - return streamContaining((listDefinition.getSemType(env))); - } - - public SemType define(Env env, SemType valueTy, SemType completionTy) { - if (PredefinedType.VAL.equals(completionTy) && PredefinedType.VAL.equals(valueTy)) { - return PredefinedType.STREAM; - } - SemType tuple = listDefinition.tupleTypeWrapped(env, valueTy, completionTy); - return streamContaining(tuple); - } - - private static SemType streamContaining(SemType tupleType) { - SubtypeData bdd = subtypeData(tupleType, BT_LIST); - assert bdd instanceof Bdd; - return createBasicSemType(BT_STREAM, bdd); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/subtypedata/BddAllOrNothing.java b/semtypes/src/main/java/io/ballerina/types/subtypedata/BddAllOrNothing.java deleted file mode 100644 index 56ce186ae170..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/subtypedata/BddAllOrNothing.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.subtypedata; - -import io.ballerina.types.Bdd; - -/** - * Represent boolean subtype of Bdd type. - * - * @since 2201.8.0 - */ -public class BddAllOrNothing implements Bdd { - private final boolean isAll; - - private static final BddAllOrNothing all = new BddAllOrNothing(true); - private static final BddAllOrNothing nothing = new BddAllOrNothing(false); - - private BddAllOrNothing(boolean isAll) { - this.isAll = isAll; - } - - public static BddAllOrNothing bddAll() { - return all; - } - - public static BddAllOrNothing bddNothing() { - return nothing; - } - - public boolean isAll() { - return this.isAll; - } - - public boolean isNothing() { - return !this.isAll; - } - - public BddAllOrNothing complement() { - if (isAll) { - return nothing; - } - return all; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj instanceof BddAllOrNothing allOrNothing) { - return this.isAll == allOrNothing.isAll; - } - - return false; - } - - @Override - public int hashCode() { - return 0xa11084 + (isAll ? 1 : 0); - } - - @Override - public String toString() { - return Boolean.toString(isAll); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/subtypedata/BddNode.java b/semtypes/src/main/java/io/ballerina/types/subtypedata/BddNode.java deleted file mode 100644 index c4c61efede1a..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/subtypedata/BddNode.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.types.subtypedata; - -import io.ballerina.types.Atom; -import io.ballerina.types.Bdd; - -/** - * Internal node of a BDD, which represents a disjunction of conjunctions of atoms. - */ -public interface BddNode extends Bdd { - - static BddNode create(Atom atom, Bdd left, Bdd middle, Bdd right) { - if (isSimpleNode(left, middle, right)) { - return new BddNodeSimple(atom); - } - return new BddNodeImpl(atom, left, middle, right); - } - - private static boolean isSimpleNode(Bdd left, Bdd middle, Bdd right) { - return left instanceof BddAllOrNothing leftNode && leftNode.isAll() && - middle instanceof BddAllOrNothing middleNode && middleNode.isNothing() && - right instanceof BddAllOrNothing rightNode && rightNode.isNothing(); - } - - Atom atom(); - - Bdd left(); - - Bdd middle(); - - Bdd right(); -} diff --git a/semtypes/src/main/java/io/ballerina/types/subtypedata/BddNodeImpl.java b/semtypes/src/main/java/io/ballerina/types/subtypedata/BddNodeImpl.java deleted file mode 100644 index f2bea68b01ef..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/subtypedata/BddNodeImpl.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.subtypedata; - -import io.ballerina.types.Atom; -import io.ballerina.types.Bdd; - -/** - * Actual implementation of a generic Bdd node. - * - * @param atom the atom that this node represents - * @param left path that include this node's atom positively - * @param middle path that doesn't include this node's atom - * @param right path that include this node's atom negatively - * @since 2201.10.0 - */ -public record BddNodeImpl(Atom atom, Bdd left, Bdd middle, Bdd right) implements BddNode { - -} diff --git a/semtypes/src/main/java/io/ballerina/types/subtypedata/BddNodeSimple.java b/semtypes/src/main/java/io/ballerina/types/subtypedata/BddNodeSimple.java deleted file mode 100644 index 7ead5fbeb3f3..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/subtypedata/BddNodeSimple.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.subtypedata; - -import io.ballerina.types.Atom; -import io.ballerina.types.Bdd; - -/** - * Represent a Bdd node that contains a single atom as positive. This is used to reduce the memory overhead of - * BddNodeImpl in representing such nodes - * - * @param atom Atom this node represents - * @since 2201.10.0 - */ -public record BddNodeSimple(Atom atom) implements BddNode { - - @Override - public Bdd left() { - return BddAllOrNothing.bddAll(); - } - - @Override - public Bdd middle() { - return BddAllOrNothing.bddNothing(); - } - - @Override - public Bdd right() { - return BddAllOrNothing.bddNothing(); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/subtypedata/BooleanSubtype.java b/semtypes/src/main/java/io/ballerina/types/subtypedata/BooleanSubtype.java deleted file mode 100644 index 4eaa4f4f5e1b..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/subtypedata/BooleanSubtype.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.subtypedata; - -import io.ballerina.types.BasicTypeCode; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.ProperSubtypeData; -import io.ballerina.types.SemType; -import io.ballerina.types.SubtypeData; - -import java.util.Optional; - -/** - * Represent BooleanSubtype. - * - * @since 2201.8.0 - */ -public class BooleanSubtype implements ProperSubtypeData { - public final boolean value; - - private BooleanSubtype(boolean value) { - this.value = value; - } - - public static BooleanSubtype from(boolean value) { - return new BooleanSubtype(value); - } - - public static boolean booleanSubtypeContains(SubtypeData d, boolean b) { - if (d instanceof AllOrNothingSubtype allOrNothingSubtype) { - return allOrNothingSubtype.isAllSubtype(); - } - BooleanSubtype r = (BooleanSubtype) d; - return r.value == b; - } - - public static SemType booleanConst(boolean value) { - BooleanSubtype t = BooleanSubtype.from(value); - return PredefinedType.basicSubtype(BasicTypeCode.BT_BOOLEAN, t); - } - - public static Optional booleanSubtypeSingleValue(SubtypeData d) { - if (d instanceof AllOrNothingSubtype) { - return Optional.empty(); - } - BooleanSubtype b = (BooleanSubtype) d; - return Optional.of(b.value); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/subtypedata/CellSubtype.java b/semtypes/src/main/java/io/ballerina/types/subtypedata/CellSubtype.java deleted file mode 100644 index e7dcae506dd6..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/subtypedata/CellSubtype.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.subtypedata; - -import io.ballerina.types.BasicTypeCode; -import io.ballerina.types.CellAtomicType; -import io.ballerina.types.CellSemType; -import io.ballerina.types.ComplexSemType; -import io.ballerina.types.Core; -import io.ballerina.types.Env; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.TypeAtom; - -import static io.ballerina.types.CellAtomicType.CellMutability.CELL_MUT_LIMITED; -import static io.ballerina.types.CellAtomicType.CellMutability.CELL_MUT_NONE; -import static io.ballerina.types.typeops.BddCommonOps.bddAtom; - -/** - * CellSubType. - * - * @since 2201.10.0 - */ -public class CellSubtype { - - // TODO: cache common cells such as cell containing NEVER - public static CellSemType cellContaining(Env env, SemType ty) { - return cellContaining(env, ty, CELL_MUT_LIMITED); - } - - public static CellSemType roCellContaining(Env env, SemType ty) { - return cellContaining(env, ty, CELL_MUT_NONE); - } - - public static CellSemType cellContaining(Env env, SemType ty, CellAtomicType.CellMutability mut) { - assert Core.isNever(ty) || !Core.isSubtypeSimple(ty, PredefinedType.CELL); - CellAtomicType atomicCell = CellAtomicType.from(ty, mut); - TypeAtom atom = env.cellAtom(atomicCell); - BddNode bdd = bddAtom(atom); - ComplexSemType complexSemType = PredefinedType.basicSubtype(BasicTypeCode.BT_CELL, bdd); - return CellSemType.from(complexSemType.subtypeDataList()); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/subtypedata/CharStringSubtype.java b/semtypes/src/main/java/io/ballerina/types/subtypedata/CharStringSubtype.java deleted file mode 100644 index b8f9a7bcbe18..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/subtypedata/CharStringSubtype.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.subtypedata; - -import io.ballerina.types.EnumerableCharString; -import io.ballerina.types.EnumerableSubtype; -import io.ballerina.types.EnumerableType; - -/** - * Represent CharStringSubtype. - * - * @since 2201.8.0 - */ -public class CharStringSubtype extends EnumerableSubtype { - - public boolean allowed; - public EnumerableCharString[] values; - - private CharStringSubtype(boolean allowed, EnumerableCharString[] values) { - this.allowed = allowed; - this.values = values; - } - - public static CharStringSubtype from(boolean allowed, EnumerableCharString[] values) { - return new CharStringSubtype(allowed, values); - } - - @Override - public boolean allowed() { - return allowed; - } - - @Override - public EnumerableType[] values() { - return values; - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/subtypedata/DecimalSubtype.java b/semtypes/src/main/java/io/ballerina/types/subtypedata/DecimalSubtype.java deleted file mode 100644 index 22b5fb7483c6..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/subtypedata/DecimalSubtype.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.subtypedata; - -import io.ballerina.types.BasicTypeCode; -import io.ballerina.types.EnumerableDecimal; -import io.ballerina.types.EnumerableSubtype; -import io.ballerina.types.EnumerableType; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.ProperSubtypeData; -import io.ballerina.types.SemType; -import io.ballerina.types.SubtypeData; - -import java.math.BigDecimal; -import java.util.Optional; -import java.util.StringJoiner; - -/** - * Represent DecimalSubtype. - * - * @since 2201.8.0 - */ -public class DecimalSubtype extends EnumerableSubtype implements ProperSubtypeData { - public boolean allowed; - public EnumerableDecimal[] values; - - private DecimalSubtype(boolean allowed, EnumerableDecimal value) { - this(allowed, new EnumerableDecimal[]{value}); - } - - private DecimalSubtype(boolean allowed, EnumerableDecimal[] values) { - this.allowed = allowed; - this.values = values; - } - - public static SemType decimalConst(BigDecimal value) { - return PredefinedType.basicSubtype(BasicTypeCode.BT_DECIMAL, - new DecimalSubtype(true, EnumerableDecimal.from(value))); - } - - public static Optional decimalSubtypeSingleValue(SubtypeData d) { - if (d instanceof AllOrNothingSubtype) { - return Optional.empty(); - } - - DecimalSubtype f = (DecimalSubtype) d; - if (!f.allowed) { - return Optional.empty(); - } - - EnumerableDecimal[] values = f.values; - if (values.length != 1) { - return Optional.empty(); - } - return Optional.of(values[0].value); - } - - public static boolean decimalSubtypeContains(SubtypeData d, EnumerableDecimal f) { - if (d instanceof AllOrNothingSubtype allOrNothingSubtype) { - return allOrNothingSubtype.isAllSubtype(); - } - - DecimalSubtype v = (DecimalSubtype) d; - for (EnumerableType val : v.values) { - if (val.equals(f)) { - return v.allowed; - } - } - return !v.allowed; - } - - public static SubtypeData createDecimalSubtype(boolean allowed, EnumerableDecimal[] values) { - if (values.length == 0) { - return allowed ? AllOrNothingSubtype.createNothing() : AllOrNothingSubtype.createAll(); - } - return new DecimalSubtype(allowed, values); - } - - @Override - public boolean allowed() { - return allowed; - } - - @Override - public EnumerableType[] values() { - return values; - } - - @Override - public String toString() { - StringJoiner j = new StringJoiner(", ", "DecimalSubtype:" + (allowed ? "allowed[" : "disallowed["), "]"); - for (EnumerableDecimal value : values) { - j.add(String.valueOf(value.value)); - } - return j.toString(); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/subtypedata/FloatSubtype.java b/semtypes/src/main/java/io/ballerina/types/subtypedata/FloatSubtype.java deleted file mode 100644 index 992b47b0030f..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/subtypedata/FloatSubtype.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.subtypedata; - -import io.ballerina.types.BasicTypeCode; -import io.ballerina.types.EnumerableFloat; -import io.ballerina.types.EnumerableSubtype; -import io.ballerina.types.EnumerableType; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.ProperSubtypeData; -import io.ballerina.types.SemType; -import io.ballerina.types.SubtypeData; - -import java.util.Optional; -import java.util.StringJoiner; - -/** - * Represent FloatSubtype. - * - * @since 2201.8.0 - */ -public class FloatSubtype extends EnumerableSubtype implements ProperSubtypeData { - public boolean allowed; - public EnumerableFloat[] values; - - private FloatSubtype(boolean allowed, EnumerableFloat value) { - this(allowed, new EnumerableFloat[]{value}); - } - - private FloatSubtype(boolean allowed, EnumerableFloat[] values) { - this.allowed = allowed; - this.values = values; - } - - public static SemType floatConst(double value) { - return PredefinedType.basicSubtype(BasicTypeCode.BT_FLOAT, new FloatSubtype(true, - EnumerableFloat.from(value))); - } - - public static Optional floatSubtypeSingleValue(SubtypeData d) { - if (d instanceof AllOrNothingSubtype) { - return Optional.empty(); - } - - FloatSubtype f = (FloatSubtype) d; - if (!f.allowed) { - return Optional.empty(); - } - - EnumerableFloat[] values = f.values; - if (values.length != 1) { - return Optional.empty(); - } - return Optional.of(values[0].value); - } - - public static boolean floatSubtypeContains(SubtypeData d, EnumerableFloat f) { - if (d instanceof AllOrNothingSubtype allOrNothingSubtype) { - return allOrNothingSubtype.isAllSubtype(); - } - - FloatSubtype v = (FloatSubtype) d; - for (EnumerableType val : v.values) { - if (val.equals(f)) { - return v.allowed; - } - } - return !v.allowed; - } - - public static SubtypeData createFloatSubtype(boolean allowed, EnumerableFloat[] values) { - if (values.length == 0) { - return allowed ? AllOrNothingSubtype.createNothing() : AllOrNothingSubtype.createAll(); - } - return new FloatSubtype(allowed, values); - } - - @Override - public boolean allowed() { - return allowed; - } - - @Override - public EnumerableType[] values() { - return values; - } - - @Override - public String toString() { - StringJoiner j = new StringJoiner(", ", "FloatSubtype:" + (allowed ? "allowed[" : "disallowed["), "]"); - for (EnumerableFloat value : values) { - j.add(String.valueOf(value.value)); - } - return j.toString(); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/subtypedata/FutureSubtype.java b/semtypes/src/main/java/io/ballerina/types/subtypedata/FutureSubtype.java deleted file mode 100644 index f7135617ffdf..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/subtypedata/FutureSubtype.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.subtypedata; - -import io.ballerina.types.Bdd; -import io.ballerina.types.Env; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.definition.MappingDefinition; - -import java.util.List; - -import static io.ballerina.types.BasicTypeCode.BT_FUTURE; -import static io.ballerina.types.BasicTypeCode.BT_MAPPING; -import static io.ballerina.types.Core.createBasicSemType; -import static io.ballerina.types.Core.subtypeData; - -/** - * Represent future subtype. - * - * @since 2201.10.0 - */ -public final class FutureSubtype { - - private FutureSubtype() { - } - - public static SemType futureContaining(Env env, SemType constraint) { - if (PredefinedType.VAL.equals(constraint)) { - return PredefinedType.FUTURE; - } - - MappingDefinition mappingDef = new MappingDefinition(); - SemType mappingType = mappingDef.defineMappingTypeWrapped(env, List.of(), constraint); - Bdd bdd = (Bdd) subtypeData(mappingType, BT_MAPPING); - return createBasicSemType(BT_FUTURE, bdd); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/subtypedata/NonCharStringSubtype.java b/semtypes/src/main/java/io/ballerina/types/subtypedata/NonCharStringSubtype.java deleted file mode 100644 index 3d686bd4fcc4..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/subtypedata/NonCharStringSubtype.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.subtypedata; - -import io.ballerina.types.EnumerableString; -import io.ballerina.types.EnumerableSubtype; -import io.ballerina.types.EnumerableType; - -/** - * Represent NonCharStringSubtype. - * - * @since 2201.8.0 - */ -public class NonCharStringSubtype extends EnumerableSubtype { - - public boolean allowed; - public EnumerableString[] values; - - private NonCharStringSubtype(boolean allowed, EnumerableString[] values) { - this.allowed = allowed; - this.values = values; - } - - public static NonCharStringSubtype from(boolean allowed, EnumerableString[] values) { - return new NonCharStringSubtype(allowed, values); - } - - @Override - public boolean allowed() { - return allowed; - } - - @Override - public EnumerableType[] values() { - return values; - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/subtypedata/Range.java b/semtypes/src/main/java/io/ballerina/types/subtypedata/Range.java deleted file mode 100644 index f34ca9f3a501..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/subtypedata/Range.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.subtypedata; - -/** - * Int Range node. - * - * @since 2201.8.0 - */ -public class Range { - public final long min; - public final long max; - - public Range(long min, long max) { - this.min = min; - this.max = max; - } - - public static Range from(long min, long max) { - return new Range(min, max); - } - - @Override - public String toString() { - return "Range[" + min + ", " + max + "]"; - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/subtypedata/RangeUnion.java b/semtypes/src/main/java/io/ballerina/types/subtypedata/RangeUnion.java deleted file mode 100644 index cc7cf4846769..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/subtypedata/RangeUnion.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.subtypedata; - -/** - * Holds a range if there is a single range representing the union/intersect of r1 and r1. - * status -1 means union/intersect is empty because r1 is before r2, with no overlap - * status 1 means union/intersect is empty because r2 is before r1 with no overlap - * Precondition r1 and r2 are non-empty. - * - * @since 2201.8.0 - */ -public class RangeUnion { - public final int status; // -1, 1, default to zero when there is a range - public final Range range; - - private RangeUnion(int status, Range range) { - this.status = status; - this.range = range; - } - - public static RangeUnion from(int status) { - return new RangeUnion(status, null); - } - - public static RangeUnion from(Range range) { - return new RangeUnion(0, range); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/subtypedata/StringSubtype.java b/semtypes/src/main/java/io/ballerina/types/subtypedata/StringSubtype.java deleted file mode 100644 index edd0c4dad869..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/subtypedata/StringSubtype.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.subtypedata; - -import io.ballerina.types.BasicTypeCode; -import io.ballerina.types.EnumerableCharString; -import io.ballerina.types.EnumerableString; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.ProperSubtypeData; -import io.ballerina.types.SemType; -import io.ballerina.types.SubtypeData; - -import java.util.Arrays; -import java.util.Optional; - -/** - * Represent StringSubtype. - * - * @since 2201.8.0 - */ -public class StringSubtype implements ProperSubtypeData { - - private static final EnumerableString[] EMPTY_STRING_ARR = {}; - private static final EnumerableCharString[] EMPTY_CHAR_ARR = {}; - CharStringSubtype charData; - NonCharStringSubtype nonCharData; - - public CharStringSubtype getChar() { - return charData; - } - - public NonCharStringSubtype getNonChar() { - return nonCharData; - } - - private StringSubtype(CharStringSubtype charData, NonCharStringSubtype nonCharData) { - this.charData = charData; - this.nonCharData = nonCharData; - } - - public static StringSubtype from(CharStringSubtype chara, NonCharStringSubtype nonChar) { - return new StringSubtype(chara, nonChar); - } - - public static boolean stringSubtypeContains(SubtypeData d, String s) { - if (d instanceof AllOrNothingSubtype allOrNothingSubtype) { - return allOrNothingSubtype.isAllSubtype(); - } - StringSubtype st = (StringSubtype) d; - CharStringSubtype chara = st.charData; - NonCharStringSubtype nonChar = st.nonCharData; - if (s.length() == 1) { - return Arrays.asList(chara.values).contains(EnumerableCharString.from(s)) == chara.allowed; - } - return Arrays.asList(nonChar.values).contains(EnumerableString.from(s)) == nonChar.allowed; - } - - public static SubtypeData createStringSubtype(CharStringSubtype chara, NonCharStringSubtype nonChar) { - if (chara.values.length == 0 && nonChar.values.length == 0) { - if (!chara.allowed && !nonChar.allowed) { - return AllOrNothingSubtype.createAll(); - } else if (chara.allowed && nonChar.allowed) { - return AllOrNothingSubtype.createNothing(); - } - } - return StringSubtype.from(chara, nonChar); - } - - public static Optional stringSubtypeSingleValue(SubtypeData d) { - if (d instanceof AllOrNothingSubtype) { - return Optional.empty(); - } - StringSubtype st = (StringSubtype) d; - CharStringSubtype chara = st.charData; - NonCharStringSubtype nonChar = st.nonCharData; - int charCount = chara.allowed ? chara.values.length : 2; - int nonCharCount = nonChar.allowed ? nonChar.values.length : 2; - if (charCount + nonCharCount == 1) { - return charCount != 0 ? - Optional.of(chara.values[0].value) : Optional.of(nonChar.values[0].value); - } - return Optional.empty(); - } - - public static SemType stringConst(String value) { - CharStringSubtype chara; - NonCharStringSubtype nonChar; - if (value.codePointCount(0, value.length()) == 1) { - chara = CharStringSubtype.from(true, - new EnumerableCharString[]{EnumerableCharString.from(value)}); - nonChar = NonCharStringSubtype.from(true, EMPTY_STRING_ARR); - } else { - chara = CharStringSubtype.from(true, EMPTY_CHAR_ARR); - nonChar = NonCharStringSubtype.from(true, new EnumerableString[]{EnumerableString.from(value)}); - } - return PredefinedType.basicSubtype(BasicTypeCode.BT_STRING, new StringSubtype(chara, nonChar)); - } - - public static SemType stringChar() { - StringSubtype st = new StringSubtype( - CharStringSubtype.from(false, EMPTY_CHAR_ARR), - NonCharStringSubtype.from(true, EMPTY_STRING_ARR)); - return PredefinedType.basicSubtype(BasicTypeCode.BT_STRING, st); - } - - /** - * Describes the relationship between a StringSubtype and a list of strings - * How the StringSubtype covers the list and vice versa. - * type StringSubtypeListCoverage record {| - * // true if the StringSubtype is a subtype of the type containing the strings in the lists - * boolean isSubtype; - * // contains the index in order of each member of the list that is in the StringSubtype - * int[] indices; - * |}; - */ - public static class StringSubtypeListCoverage { - public final boolean isSubtype; - public final int[] indices; - - public StringSubtypeListCoverage(boolean isSubtype, int[] indices) { - this.isSubtype = isSubtype; - this.indices = indices; - } - - public static StringSubtypeListCoverage from(boolean isSubtype, int[] indices) { - return new StringSubtypeListCoverage(isSubtype, indices); - } - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/subtypedata/TableSubtype.java b/semtypes/src/main/java/io/ballerina/types/subtypedata/TableSubtype.java deleted file mode 100644 index 680065c91ff9..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/subtypedata/TableSubtype.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.subtypedata; - -import io.ballerina.types.Bdd; -import io.ballerina.types.CellAtomicType; -import io.ballerina.types.Context; -import io.ballerina.types.Core; -import io.ballerina.types.Env; -import io.ballerina.types.FixedLengthArray; -import io.ballerina.types.ListAtomicType; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypes; -import io.ballerina.types.definition.ListDefinition; - -import static io.ballerina.types.BasicTypeCode.BT_LIST; -import static io.ballerina.types.BasicTypeCode.BT_TABLE; -import static io.ballerina.types.CellAtomicType.CellMutability.CELL_MUT_LIMITED; -import static io.ballerina.types.Core.createBasicSemType; -import static io.ballerina.types.Core.subtypeData; - -/** - * TableSubtype. - * - * @since 2201.8.0 - */ -public final class TableSubtype { - - private TableSubtype() { - } - - public static SemType tableContainingKeyConstraint(Context cx, SemType tableConstraint, SemType keyConstraint) { - SemType normalizedKc; - ListAtomicType lat = Core.listAtomicType(cx, keyConstraint); - if (lat != null && PredefinedType.CELL_ATOMIC_UNDEF.equals(Core.cellAtomicType(lat.rest()))) { - FixedLengthArray members = lat.members(); - normalizedKc = switch (members.fixedLength()) { - case 0 -> PredefinedType.VAL; - case 1 -> Core.cellAtomicType(members.initial().get(0)).ty(); - default -> keyConstraint; - }; - } else { - normalizedKc = keyConstraint; - } - return tableContaining(cx.env, tableConstraint, normalizedKc, PredefinedType.VAL); - } - - public static SemType tableContainingKeySpecifier(Context cx, SemType tableConstraint, String[] fieldNames) { - SemType[] fieldNameSingletons = new SemType[fieldNames.length]; - SemType[] fieldTypes = new SemType[fieldNames.length]; - for (int i = 0; i < fieldNames.length; i++) { - SemType key = SemTypes.stringConst(fieldNames[i]); - fieldNameSingletons[i] = key; - fieldTypes[i] = Core.mappingMemberTypeInnerVal(cx, tableConstraint, key); - } - - SemType normalizedKs = new ListDefinition().tupleTypeWrapped(cx.env, fieldNameSingletons); - - SemType normalizedKc; - if (fieldTypes.length > 1) { - ListDefinition ld = new ListDefinition(); - normalizedKc = ld.tupleTypeWrapped(cx.env, fieldTypes); - } else { - normalizedKc = fieldTypes[0]; - } - return tableContaining(cx.env, tableConstraint, normalizedKc, normalizedKs); - } - - public static SemType tableContaining(Env env, SemType tableConstraint) { - return tableContaining(env, tableConstraint, CELL_MUT_LIMITED); - } - - public static SemType tableContaining(Env env, SemType tableConstraint, CellAtomicType.CellMutability mut) { - SemType normalizedKc = PredefinedType.VAL; // TODO: Ideally this should be anydata - SemType normalizedKs = PredefinedType.VAL; // TODO: Ideally this should be string[] - return tableContaining(env, tableConstraint, normalizedKc, normalizedKs, mut); - } - - private static SemType tableContaining(Env env, SemType tableConstraint, - SemType normalizedKc, SemType normalizedKs, - CellAtomicType.CellMutability mut) { - - assert SemTypes.isSubtypeSimple(tableConstraint, PredefinedType.MAPPING); - ListDefinition typeParamArrDef = new ListDefinition(); - SemType typeParamArray = typeParamArrDef.defineListTypeWrapped(env, tableConstraint, mut); - - ListDefinition listDef = new ListDefinition(); - SemType tupleType = listDef.tupleTypeWrapped(env, typeParamArray, normalizedKc, normalizedKs); - Bdd bdd = (Bdd) subtypeData(tupleType, BT_LIST); - return createBasicSemType(BT_TABLE, bdd); - } - - private static SemType tableContaining(Env env, SemType tableConstraint, - SemType normalizedKc, SemType normalizedKs) { - return tableContaining(env, tableConstraint, normalizedKc, normalizedKs, CELL_MUT_LIMITED); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/subtypedata/TypedescSubtype.java b/semtypes/src/main/java/io/ballerina/types/subtypedata/TypedescSubtype.java deleted file mode 100644 index a56171f854c1..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/subtypedata/TypedescSubtype.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.subtypedata; - -import io.ballerina.types.Bdd; -import io.ballerina.types.CellAtomicType; -import io.ballerina.types.Env; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.definition.MappingDefinition; - -import java.util.List; - -import static io.ballerina.types.BasicTypeCode.BT_MAPPING; -import static io.ballerina.types.BasicTypeCode.BT_TYPEDESC; -import static io.ballerina.types.Core.createBasicSemType; -import static io.ballerina.types.Core.subtypeData; - -/** - * Represent typedesc subtype. - * - * @since 2201.10.0 - */ -public final class TypedescSubtype { - - private TypedescSubtype() { - } - - public static SemType typedescContaining(Env env, SemType constraint) { - if (PredefinedType.VAL.equals(constraint)) { - return PredefinedType.TYPEDESC; - } - - MappingDefinition mappingDef = new MappingDefinition(); - SemType mappingType = mappingDef.defineMappingTypeWrapped(env, List.of(), constraint, - CellAtomicType.CellMutability.CELL_MUT_NONE); - Bdd bdd = (Bdd) subtypeData(mappingType, BT_MAPPING); - return createBasicSemType(BT_TYPEDESC, bdd); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/subtypedata/XmlSubtype.java b/semtypes/src/main/java/io/ballerina/types/subtypedata/XmlSubtype.java deleted file mode 100644 index 1991dd0eb86f..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/subtypedata/XmlSubtype.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.subtypedata; - -import io.ballerina.types.BasicTypeBitSet; -import io.ballerina.types.BasicTypeCode; -import io.ballerina.types.Bdd; -import io.ballerina.types.ComplexSemType; -import io.ballerina.types.Core; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.ProperSubtypeData; -import io.ballerina.types.RecAtom; -import io.ballerina.types.SemType; -import io.ballerina.types.SubtypeData; -import io.ballerina.types.typeops.BddCommonOps; - -/** - * Implementation specific to basic type xml. - * - * @since 2201.8.0 - */ -public class XmlSubtype implements ProperSubtypeData { - // This is the bitwise-or of above XML_PRIMITIVE_* fields. - // If the XML_PRIMITIVE_NEVER bit is set, then the empty XML sequence belongs to the type. - // If one of the other XML_PRIMITVE_* bits is set, then the type contains the - // corresponding singleton type. - public final int primitives; - // This is a logical combination of the allowed sequences types. The `atom` field of - // the `BddNode` is a bitwise-or of XML_PRIMTIVE_* (except for XML_PRIMITIVE_NEVER). - // It represents a sequence of two or more singletons, where the allowed singletons - // are those whose bit is set in the `atom` field. - public final Bdd sequence; - - public static final int XML_PRIMITIVE_NEVER = 1; - public static final int XML_PRIMITIVE_TEXT = 1 << 1; - public static final int XML_PRIMITIVE_ELEMENT_RO = 1 << 2; - public static final int XML_PRIMITIVE_PI_RO = 1 << 3; - public static final int XML_PRIMITIVE_COMMENT_RO = 1 << 4; - public static final int XML_PRIMITIVE_ELEMENT_RW = 1 << 5; - public static final int XML_PRIMITIVE_PI_RW = 1 << 6; - public static final int XML_PRIMITIVE_COMMENT_RW = 1 << 7; - - public static final int XML_PRIMITIVE_RO_SINGLETON = XML_PRIMITIVE_TEXT | XML_PRIMITIVE_ELEMENT_RO - | XML_PRIMITIVE_PI_RO | XML_PRIMITIVE_COMMENT_RO; - public static final int XML_PRIMITIVE_RO_MASK = XML_PRIMITIVE_NEVER | XML_PRIMITIVE_RO_SINGLETON; - public static final int XML_PRIMITIVE_RW_MASK = XML_PRIMITIVE_ELEMENT_RW | XML_PRIMITIVE_PI_RW - | XML_PRIMITIVE_COMMENT_RW; - public static final int XML_PRIMITIVE_SINGLETON = XML_PRIMITIVE_RO_SINGLETON | XML_PRIMITIVE_RW_MASK; - public static final int XML_PRIMITIVE_ALL_MASK = XML_PRIMITIVE_RO_MASK | XML_PRIMITIVE_RW_MASK; - - private XmlSubtype(int primitives, Bdd sequence) { - this.primitives = primitives; - this.sequence = sequence; - } - - public static XmlSubtype from(int primitives, Bdd sequence) { - return new XmlSubtype(primitives, sequence); - } - - public static SemType xmlSingleton(int primitives) { - return createXmlSemtype(createXmlSubtype(primitives, BddAllOrNothing.bddNothing())); - } - - public static SemType xmlSequence(SemType constituentType) { - // It is a precondition that constituentType is a subtype of XML - assert Core.isSubtypeSimple(constituentType, PredefinedType.XML); - - if (Core.isNever(constituentType)) { - return xmlSequence(xmlSingleton(XML_PRIMITIVE_NEVER)); - } - if (constituentType instanceof BasicTypeBitSet) { - return constituentType; - } else { - ComplexSemType cct = (ComplexSemType) constituentType; - SubtypeData xmlSubtype = Core.getComplexSubtypeData(cct, BasicTypeCode.BT_XML); - xmlSubtype = (xmlSubtype instanceof AllOrNothingSubtype) ? - xmlSubtype : makeXmlSequence((XmlSubtype) xmlSubtype); - return createXmlSemtype(xmlSubtype); - } - } - - private static SubtypeData makeXmlSequence(XmlSubtype d) { - int primitives = XML_PRIMITIVE_NEVER | d.primitives; - int atom = d.primitives & XML_PRIMITIVE_SINGLETON; - Bdd sequence = BddCommonOps.bddUnion(BddCommonOps.bddAtom(RecAtom.createXMLRecAtom(atom)), d.sequence); - return createXmlSubtype(primitives, sequence); - } - - public static SemType createXmlSemtype(SubtypeData xmlSubtype) { - if (xmlSubtype instanceof AllOrNothingSubtype allOrNothingSubtype) { - return allOrNothingSubtype.isAllSubtype() ? PredefinedType.XML : PredefinedType.NEVER; - } else { - return PredefinedType.basicSubtype(BasicTypeCode.BT_XML, (ProperSubtypeData) xmlSubtype); - } - } - - public static SubtypeData createXmlSubtype(int primitives, Bdd sequence) { - int p = primitives & XML_PRIMITIVE_ALL_MASK; - if (sequence instanceof BddAllOrNothing allOrNothing && allOrNothing.isAll() && - p == XML_PRIMITIVE_ALL_MASK) { - return AllOrNothingSubtype.createAll(); - } - return createXmlSubtypeOrEmpty(p, sequence); - } - - public static SubtypeData createXmlSubtypeOrEmpty(int primitives, Bdd sequence) { - if (sequence instanceof BddAllOrNothing allOrNothing && allOrNothing.isNothing() && primitives == 0) { - return AllOrNothingSubtype.createNothing(); - } - return from(primitives, sequence); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/BasicTypeOpsPanicImpl.java b/semtypes/src/main/java/io/ballerina/types/typeops/BasicTypeOpsPanicImpl.java deleted file mode 100644 index 923b7b154f8d..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/BasicTypeOpsPanicImpl.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.BasicTypeOps; -import io.ballerina.types.Context; -import io.ballerina.types.SubtypeData; - -/** - * Default implementation for basic subtypes that does not need type-ops. - * - * @since 2201.8.0 - */ -public class BasicTypeOpsPanicImpl implements BasicTypeOps { - @Override - public SubtypeData union(SubtypeData t1, SubtypeData t2) { - throw new IllegalStateException("Binary operation should not be called"); - } - - @Override - public SubtypeData intersect(SubtypeData t1, SubtypeData t2) { - throw new IllegalStateException("Binary operation should not be called"); - } - - @Override - public SubtypeData diff(SubtypeData t1, SubtypeData t2) { - throw new IllegalStateException("Binary operation should not be called"); - } - - @Override - public SubtypeData complement(SubtypeData t) { - throw new IllegalStateException("Unary operation should not be called"); - } - - @Override - public boolean isEmpty(Context cx, SubtypeData t) { - throw new IllegalStateException("Unary boolean operation should not be called"); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/BddCommonOps.java b/semtypes/src/main/java/io/ballerina/types/typeops/BddCommonOps.java deleted file mode 100644 index 6de40258eee1..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/BddCommonOps.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.Atom; -import io.ballerina.types.Bdd; -import io.ballerina.types.RecAtom; -import io.ballerina.types.subtypedata.BddAllOrNothing; -import io.ballerina.types.subtypedata.BddNode; - -/** - * Contain common BDD operations found in bdd.bal file. - * - * @since 2201.8.0 - */ -public abstract class BddCommonOps { - - public static BddNode bddAtom(Atom atom) { - return BddNode.create(atom, - BddAllOrNothing.bddAll(), - BddAllOrNothing.bddNothing(), - BddAllOrNothing.bddNothing()); - } - - public static Bdd bddUnion(Bdd b1, Bdd b2) { - if (b1 == b2) { - return b1; - } else if (b1 instanceof BddAllOrNothing) { - return ((BddAllOrNothing) b1).isAll() ? BddAllOrNothing.bddAll() : b2; - } else if (b2 instanceof BddAllOrNothing) { - return ((BddAllOrNothing) b2).isAll() ? BddAllOrNothing.bddAll() : b1; - } else { - BddNode b1Bdd = (BddNode) b1; - BddNode b2Bdd = (BddNode) b2; - long cmp = atomCmp(b1Bdd.atom(), b2Bdd.atom()); - if (cmp < 0L) { - return bddCreate(b1Bdd.atom(), - b1Bdd.left(), - bddUnion(b1Bdd.middle(), b2), - b1Bdd.right()); - } else if (cmp > 0L) { - return bddCreate(b2Bdd.atom(), - b2Bdd.left(), - bddUnion(b1, b2Bdd.middle()), - b2Bdd.right()); - } else { - return bddCreate(b1Bdd.atom(), - bddUnion(b1Bdd.left(), b2Bdd.left()), - bddUnion(b1Bdd.middle(), b2Bdd.middle()), - bddUnion(b1Bdd.right(), b2Bdd.right())); - } - } - } - - public static Bdd bddIntersect(Bdd b1, Bdd b2) { - if (b1 == b2) { - return b1; - } else if (b1 instanceof BddAllOrNothing) { - return ((BddAllOrNothing) b1).isAll() ? b2 : BddAllOrNothing.bddNothing(); - } else if (b2 instanceof BddAllOrNothing) { - return ((BddAllOrNothing) b2).isAll() ? b1 : BddAllOrNothing.bddNothing(); - } else { - BddNode b1Bdd = (BddNode) b1; - BddNode b2Bdd = (BddNode) b2; - long cmp = atomCmp(b1Bdd.atom(), b2Bdd.atom()); - if (cmp < 0L) { - return bddCreate(b1Bdd.atom(), - bddIntersect(b1Bdd.left(), b2), - bddIntersect(b1Bdd.middle(), b2), - bddIntersect(b1Bdd.right(), b2)); - } else if (cmp > 0L) { - return bddCreate(b2Bdd.atom(), - bddIntersect(b1, b2Bdd.left()), - bddIntersect(b1, b2Bdd.middle()), - bddIntersect(b1, b2Bdd.right())); - } else { - return bddCreate(b1Bdd.atom(), - bddIntersect( - bddUnion(b1Bdd.left(), b1Bdd.middle()), - bddUnion(b2Bdd.left(), b2Bdd.middle())), - BddAllOrNothing.bddNothing(), - bddIntersect( - bddUnion(b1Bdd.right(), b1Bdd.middle()), - bddUnion(b2Bdd.right(), b2Bdd.middle()))); - } - } - } - - public static Bdd bddDiff(Bdd b1, Bdd b2) { - if (b1 == b2) { - return BddAllOrNothing.bddNothing(); - } else if (b2 instanceof BddAllOrNothing allOrNothing) { - return allOrNothing.isAll() ? BddAllOrNothing.bddNothing() : b1; - } else if (b1 instanceof BddAllOrNothing allOrNothing) { - return allOrNothing.isAll() ? bddComplement(b2) : BddAllOrNothing.bddNothing(); - } else { - BddNode b1Bdd = (BddNode) b1; - BddNode b2Bdd = (BddNode) b2; - long cmp = atomCmp(b1Bdd.atom(), b2Bdd.atom()); - if (cmp < 0L) { - return bddCreate(b1Bdd.atom(), - bddDiff(bddUnion(b1Bdd.left(), b1Bdd.middle()), b2), - BddAllOrNothing.bddNothing(), - bddDiff(bddUnion(b1Bdd.right(), b1Bdd.middle()), b2)); - } else if (cmp > 0L) { - return bddCreate(b2Bdd.atom(), - bddDiff(b1, bddUnion(b2Bdd.left(), b2Bdd.middle())), - BddAllOrNothing.bddNothing(), - bddDiff(b1, bddUnion(b2Bdd.right(), b2Bdd.middle()))); - } else { - // There is an error in the Castagna paper for this formula. - // The union needs to be materialized here. - // The original formula does not work in a case like (a0|a1) - a0. - // Castagna confirms that the following formula is the correct one. - return bddCreate(b1Bdd.atom(), - bddDiff(bddUnion(b1Bdd.left(), b1Bdd.middle()), - bddUnion(b2Bdd.left(), b2Bdd.middle())), - BddAllOrNothing.bddNothing(), - bddDiff(bddUnion(b1Bdd.right(), b1Bdd.middle()), - bddUnion(b2Bdd.right(), b2Bdd.middle()))); - } - } - } - - public static Bdd bddComplement(Bdd b) { - if (b instanceof BddAllOrNothing) { - return ((BddAllOrNothing) b).complement(); - } else { - return bddNodeComplement((BddNode) b); - } - } - - public static Bdd bddNodeComplement(BddNode b) { - BddAllOrNothing bddNothing = BddAllOrNothing.bddNothing(); - if (b.right().equals(bddNothing)) { - return bddCreate(b.atom(), - bddNothing, - bddComplement(bddUnion(b.left(), b.middle())), - bddComplement(b.middle())); - } else if (b.left().equals(bddNothing)) { - return bddCreate(b.atom(), - bddComplement(b.middle()), - bddComplement(bddUnion(b.right(), b.middle())), - bddNothing); - } else if (b.middle().equals(bddNothing)) { - return bddCreate(b.atom(), - bddComplement(b.left()), - bddComplement(bddUnion(b.left(), b.right())), - bddComplement(b.right())); - } else { - // There is a typo in the Frisch PhD thesis for this formula. - // (It has left and right swapped.) - // Castagna (the PhD supervisor) confirms that this is the correct formula. - return bddCreate(b.atom(), - bddComplement(bddUnion(b.left(), b.middle())), - bddNothing, - bddComplement(bddUnion(b.right(), b.middle()))); - } - } - - public static Bdd bddCreate(Atom atom, Bdd left, Bdd middle, Bdd right) { - if (middle instanceof BddAllOrNothing && ((BddAllOrNothing) middle).isAll()) { - return middle; - } - if (left.equals(right)) { - return bddUnion(left, right); - } - - return BddNode.create(atom, left, middle, right); - } - - // order RecAtom < TypeAtom - public static long atomCmp(Atom a1, Atom a2) { - if (a1 instanceof RecAtom r1) { - if (a2 instanceof RecAtom r2) { - return r1.index() - r2.index(); - } else { - return -1L; - } - } else if (a2 instanceof RecAtom) { - return 1L; - } else { - return a1.index() - a2.index(); - } - } - - // This is for debugging purposes. - // It uses the Frisch/Castagna notation. - public static String bddToString(Bdd b, boolean inner) { - if (b instanceof BddAllOrNothing) { - return ((BddAllOrNothing) b).isAll() ? "1" : "0"; - } else { - String str; - BddNode bdd = (BddNode) b; - Atom a = bdd.atom(); - - if (a instanceof RecAtom) { - str = "r" + a; - } else { - str = "a" + a.index(); - } - str += "?" + bddToString(bdd.left(), true) + ":" + bddToString(bdd.middle(), true) + - ":" + bddToString(bdd.right(), true); - if (inner) { - str = "(" + str + ")"; - } - return str; - } - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/BooleanOps.java b/semtypes/src/main/java/io/ballerina/types/typeops/BooleanOps.java deleted file mode 100644 index 6268a16fc00b..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/BooleanOps.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.BasicTypeOps; -import io.ballerina.types.Common; -import io.ballerina.types.Context; -import io.ballerina.types.SubtypeData; -import io.ballerina.types.subtypedata.AllOrNothingSubtype; -import io.ballerina.types.subtypedata.BooleanSubtype; - -/** - * Basic type ops for boolean type. - * - * @since 2201.8.0 - */ -public class BooleanOps implements BasicTypeOps { - @Override - public SubtypeData union(SubtypeData d1, SubtypeData d2) { - BooleanSubtype v1 = (BooleanSubtype) d1; - BooleanSubtype v2 = (BooleanSubtype) d2; - return v1.value == v2.value ? v1 : AllOrNothingSubtype.createAll(); - } - - @Override - public SubtypeData intersect(SubtypeData d1, SubtypeData d2) { - BooleanSubtype v1 = (BooleanSubtype) d1; - BooleanSubtype v2 = (BooleanSubtype) d2; - return v1.value == v2.value ? v1 : AllOrNothingSubtype.createNothing(); - } - - @Override - public SubtypeData diff(SubtypeData d1, SubtypeData d2) { - BooleanSubtype v1 = (BooleanSubtype) d1; - BooleanSubtype v2 = (BooleanSubtype) d2; - return v1.value == v2.value ? AllOrNothingSubtype.createNothing() : v1; - } - - @Override - public SubtypeData complement(SubtypeData d) { - BooleanSubtype v = (BooleanSubtype) d; - BooleanSubtype t = BooleanSubtype.from(!v.value); - return t; - } - - @Override - public boolean isEmpty(Context cx, SubtypeData t) { - return Common.notIsEmpty(cx, t); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/CellOps.java b/semtypes/src/main/java/io/ballerina/types/typeops/CellOps.java deleted file mode 100644 index 9a561c33ed5e..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/CellOps.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.Atom; -import io.ballerina.types.BasicTypeOps; -import io.ballerina.types.Bdd; -import io.ballerina.types.CellAtomicType; -import io.ballerina.types.Common; -import io.ballerina.types.Conjunction; -import io.ballerina.types.Context; -import io.ballerina.types.Core; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.ProperSubtypeData; -import io.ballerina.types.SemType; -import io.ballerina.types.SubtypeData; -import io.ballerina.types.subtypedata.AllOrNothingSubtype; - -import java.util.Collections; -import java.util.EnumSet; - -import static io.ballerina.types.Common.bddSubtypeComplement; -import static io.ballerina.types.Common.bddSubtypeDiff; -import static io.ballerina.types.Common.bddSubtypeIntersect; -import static io.ballerina.types.Common.bddSubtypeUnion; -import static io.ballerina.types.Core.cellAtomType; -import static io.ballerina.types.PredefinedType.ATOM_CELL_NEVER; -import static io.ballerina.types.PredefinedType.ATOM_CELL_VAL; -import static io.ballerina.types.typeops.BddCommonOps.bddAtom; - -/** - * Basic type ops for cell type. - * - * @since 2201.10.0 - */ -public class CellOps extends CommonOps implements BasicTypeOps { - - private static boolean cellFormulaIsEmpty(Context cx, SubtypeData t) { - return Common.bddEvery(cx, (Bdd) t, null, null, CellOps::cellFormulaIsEmpty); - } - - private static boolean cellFormulaIsEmpty(Context cx, Conjunction posList, Conjunction negList) { - CellAtomicType combined; - if (posList == null) { - combined = CellAtomicType.from(PredefinedType.VAL, CellAtomicType.CellMutability.CELL_MUT_UNLIMITED); - } else { - combined = cellAtomType(posList.atom); - Conjunction p = posList.next; - while (p != null) { - combined = intersectCellAtomicType(combined, cellAtomType(p.atom)); - p = p.next; - } - } - return !cellInhabited(cx, combined, negList); - } - - private static boolean cellInhabited(Context cx, CellAtomicType posCell, Conjunction negList) { - SemType pos = posCell.ty(); - if (Core.isEmpty(cx, pos)) { - return false; - } - return switch (posCell.mut()) { - case CELL_MUT_NONE -> cellMutNoneInhabited(cx, pos, negList); - case CELL_MUT_LIMITED -> cellMutLimitedInhabited(cx, pos, negList); - default -> cellMutUnlimitedInhabited(cx, pos, negList); - }; - } - - private static boolean cellMutNoneInhabited(Context cx, SemType pos, Conjunction negList) { - SemType negListUnionResult = cellNegListUnion(negList); - // We expect `isNever` condition to be `true` when there are no negative atoms. - // Otherwise, we do `isEmpty` to conclude on the inhabitance. - return Core.isNever(negListUnionResult) || !Core.isEmpty(cx, Core.diff(pos, negListUnionResult)); - } - - private static SemType cellNegListUnion(Conjunction negList) { - SemType negUnion = PredefinedType.NEVER; - Conjunction neg = negList; - while (neg != null) { - negUnion = Core.union(negUnion, cellAtomType(neg.atom).ty()); - neg = neg.next; - } - return negUnion; - } - - private static boolean cellMutLimitedInhabited(Context cx, SemType pos, Conjunction negList) { - if (negList == null) { - return true; - } - CellAtomicType negAtomicCell = cellAtomType(negList.atom); - if ((negAtomicCell.mut().compareTo(CellAtomicType.CellMutability.CELL_MUT_LIMITED) >= 0) && - Core.isEmpty(cx, Core.diff(pos, negAtomicCell.ty()))) { - return false; - } - return cellMutLimitedInhabited(cx, pos, negList.next); - } - - private static boolean cellMutUnlimitedInhabited(Context cx, SemType pos, Conjunction negList) { - Conjunction neg = negList; - while (neg != null) { - if (cellAtomType(neg.atom).mut() == CellAtomicType.CellMutability.CELL_MUT_LIMITED && - Core.isSameType(cx, PredefinedType.VAL, cellAtomType(neg.atom).ty())) { - return false; - } - neg = neg.next; - } - SemType negListUnionResult = cellNegListUnlimitedUnion(negList); - // We expect `isNever` condition to be `true` when there are no negative atoms with unlimited mutability. - // Otherwise, we do `isEmpty` to conclude on the inhabitance. - return Core.isNever(negListUnionResult) || !Core.isEmpty(cx, Core.diff(pos, negListUnionResult)); - } - - private static SemType cellNegListUnlimitedUnion(Conjunction negList) { - SemType negUnion = PredefinedType.NEVER; - Conjunction neg = negList; - while (neg != null) { - if (cellAtomType(neg.atom).mut() == CellAtomicType.CellMutability.CELL_MUT_UNLIMITED) { - negUnion = Core.union(negUnion, cellAtomType(neg.atom).ty()); - } - neg = neg.next; - } - return negUnion; - } - - public static CellAtomicType intersectCellAtomicType(CellAtomicType c1, CellAtomicType c2) { - SemType ty = Core.intersect(c1.ty(), c2.ty()); - CellAtomicType.CellMutability mut = Collections.min(EnumSet.of(c1.mut(), c2.mut())); - return CellAtomicType.from(ty, mut); - } - - private static ProperSubtypeData cellSubtypeUnion(SubtypeData t1, SubtypeData t2) { - return cellSubtypeDataEnsureProper(bddSubtypeUnion(t1, t2)); - } - - private static ProperSubtypeData cellSubtypeIntersect(SubtypeData t1, SubtypeData t2) { - return cellSubtypeDataEnsureProper(bddSubtypeIntersect(t1, t2)); - } - - private static ProperSubtypeData cellSubtypeDiff(SubtypeData t1, SubtypeData t2) { - return cellSubtypeDataEnsureProper(bddSubtypeDiff(t1, t2)); - } - - private static ProperSubtypeData cellSubtypeComplement(SubtypeData t) { - return cellSubtypeDataEnsureProper(bddSubtypeComplement(t)); - } - - /** - * SubtypeData being a boolean would result in a BasicTypeBitSet which could either be 0 or 1 << BT_CELL. - * This is to avoid cell type being a BasicTypeBitSet, as we don't want to lose the cell wrapper. - */ - private static ProperSubtypeData cellSubtypeDataEnsureProper(SubtypeData subtypeData) { - if (subtypeData instanceof AllOrNothingSubtype allOrNothingSubtype) { - Atom atom; - if (allOrNothingSubtype.isAllSubtype()) { - atom = ATOM_CELL_VAL; - } else { - atom = ATOM_CELL_NEVER; - } - return bddAtom(atom); - } else { - return (ProperSubtypeData) subtypeData; - } - } - - @Override - public SubtypeData union(SubtypeData t1, SubtypeData t2) { - return cellSubtypeUnion(t1, t2); - } - - @Override - public SubtypeData intersect(SubtypeData t1, SubtypeData t2) { - return cellSubtypeIntersect(t1, t2); - } - - @Override - public SubtypeData diff(SubtypeData t1, SubtypeData t2) { - return cellSubtypeDiff(t1, t2); - } - - @Override - public SubtypeData complement(SubtypeData t) { - return cellSubtypeComplement(t); - } - - @Override - public boolean isEmpty(Context cx, SubtypeData t) { - return cellFormulaIsEmpty(cx, t); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/DecimalOps.java b/semtypes/src/main/java/io/ballerina/types/typeops/DecimalOps.java deleted file mode 100644 index 9e5fb7ff7fe4..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/DecimalOps.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.BasicTypeOps; -import io.ballerina.types.Common; -import io.ballerina.types.Context; -import io.ballerina.types.EnumerableDecimal; -import io.ballerina.types.EnumerableSubtype; -import io.ballerina.types.SubtypeData; -import io.ballerina.types.subtypedata.DecimalSubtype; - -import java.util.ArrayList; - -/** - * Decimal specific methods operate on SubtypeData. - * - * @since 2201.8.0 - */ -public class DecimalOps extends CommonOps implements BasicTypeOps { - @Override - public SubtypeData union(SubtypeData t1, SubtypeData t2) { - ArrayList values = new ArrayList<>(); - boolean allowed = EnumerableSubtype.enumerableSubtypeUnion((DecimalSubtype) t1, (DecimalSubtype) t2, values); - EnumerableDecimal[] valueArray = new EnumerableDecimal[values.size()]; - return DecimalSubtype.createDecimalSubtype(allowed, values.toArray(valueArray)); - } - - @Override - public SubtypeData intersect(SubtypeData t1, SubtypeData t2) { - ArrayList values = new ArrayList<>(); - boolean allowed = EnumerableSubtype.enumerableSubtypeIntersect((DecimalSubtype) t1, - (DecimalSubtype) t2, values); - return DecimalSubtype.createDecimalSubtype(allowed, values.toArray(new EnumerableDecimal[]{})); - } - - @Override - public SubtypeData diff(SubtypeData t1, SubtypeData t2) { - return intersect(t1, complement(t2)); - } - - @Override - public SubtypeData complement(SubtypeData t) { - DecimalSubtype s = (DecimalSubtype) t; - return DecimalSubtype.createDecimalSubtype(!s.allowed, (EnumerableDecimal[]) s.values); - } - - @Override - public boolean isEmpty(Context tc, SubtypeData t) { - return Common.notIsEmpty(tc, t); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/ErrorOps.java b/semtypes/src/main/java/io/ballerina/types/typeops/ErrorOps.java deleted file mode 100644 index 654d36988c50..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/ErrorOps.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.BasicTypeOps; -import io.ballerina.types.Bdd; -import io.ballerina.types.Context; -import io.ballerina.types.SubtypeData; - -import static io.ballerina.types.Common.bddEveryPositive; -import static io.ballerina.types.Common.bddPosMaybeEmpty; -import static io.ballerina.types.Common.bddSubtypeDiff; -import static io.ballerina.types.Common.memoSubtypeIsEmpty; -import static io.ballerina.types.PredefinedType.BDD_SUBTYPE_RO; -import static io.ballerina.types.typeops.BddCommonOps.bddIntersect; - -/** - * Basic type ops for error type. - * - * @since 2201.8.0 - */ -public class ErrorOps extends CommonOps implements BasicTypeOps { - - private static SubtypeData errorSubtypeComplement(SubtypeData t) { - return bddSubtypeDiff(BDD_SUBTYPE_RO, t); - } - - private static boolean errorSubtypeIsEmpty(Context cx, SubtypeData t) { - Bdd b = (Bdd) t; - // The goal of this is to ensure that mappingFormulaIsEmpty call in errorBddIsEmpty beneath - // does not get an empty posList, because it will interpret that - // as `map` rather than `readonly & map`. - b = bddPosMaybeEmpty(b) ? bddIntersect(b, BDD_SUBTYPE_RO) : b; - return memoSubtypeIsEmpty(cx, cx.mappingMemo, ErrorOps::errorBddIsEmpty, b); - } - - private static boolean errorBddIsEmpty(Context cx, Bdd b) { - return bddEveryPositive(cx, b, null, null, MappingOps::mappingFormulaIsEmpty); - } - - @Override - public SubtypeData complement(SubtypeData d) { - return errorSubtypeComplement(d); - } - - @Override - public boolean isEmpty(Context cx, SubtypeData t) { - return errorSubtypeIsEmpty(cx, t); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/FieldPair.java b/semtypes/src/main/java/io/ballerina/types/typeops/FieldPair.java deleted file mode 100644 index 7f93864922e2..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/FieldPair.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.CellSemType; - -/** - * Represent the FieldPair record. - * - * @param name name of the field - * @param type1 type of the field in the first mapping - * @param type2 type of the field in the second mapping - * @param index1 index of the field in the first mapping - * @param index2 index of the field in the second mapping - * @since 2201.10.0 - */ -public record FieldPair(String name, CellSemType type1, CellSemType type2, Integer index1, Integer index2) { - - public static FieldPair create(String name, CellSemType type1, CellSemType type2, Integer index1, - Integer index2) { - return new FieldPair(name, type1, type2, index1, index2); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/FieldPairs.java b/semtypes/src/main/java/io/ballerina/types/typeops/FieldPairs.java deleted file mode 100644 index bd85a0f99082..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/FieldPairs.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.MappingAtomicType; - -import java.util.Iterator; - -/** - * Ballerina iterator is similar to an iterable in Java. - * This class implements the iterable for `MappingPairing` - * - * @since 2201.8.0 - */ -public class FieldPairs implements Iterable { - - MappingAtomicType m1; - MappingAtomicType m2; - - public FieldPairs(MappingAtomicType m1, MappingAtomicType m2) { - this.m1 = m1; - this.m2 = m2; - } - - @Override - public Iterator iterator() { - return new MappingPairIterator(m1, m2); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/FloatOps.java b/semtypes/src/main/java/io/ballerina/types/typeops/FloatOps.java deleted file mode 100644 index 1264bbcf9671..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/FloatOps.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.BasicTypeOps; -import io.ballerina.types.Common; -import io.ballerina.types.Context; -import io.ballerina.types.EnumerableFloat; -import io.ballerina.types.EnumerableSubtype; -import io.ballerina.types.SubtypeData; -import io.ballerina.types.subtypedata.FloatSubtype; - -import java.util.ArrayList; - -/** - * Float specific methods operate on SubtypeData. - * - * @since 2201.8.0 - */ -public class FloatOps extends CommonOps implements BasicTypeOps { - @Override - public SubtypeData union(SubtypeData t1, SubtypeData t2) { - ArrayList values = new ArrayList<>(); - boolean allowed = EnumerableSubtype.enumerableSubtypeUnion((FloatSubtype) t1, (FloatSubtype) t2, values); - EnumerableFloat[] valueArray = new EnumerableFloat[values.size()]; - return FloatSubtype.createFloatSubtype(allowed, values.toArray(valueArray)); - } - - @Override - public SubtypeData intersect(SubtypeData t1, SubtypeData t2) { - ArrayList values = new ArrayList<>(); - boolean allowed = EnumerableSubtype.enumerableSubtypeIntersect((FloatSubtype) t1, (FloatSubtype) t2, values); - return FloatSubtype.createFloatSubtype(allowed, values.toArray(new EnumerableFloat[]{})); - } - - @Override - public SubtypeData diff(SubtypeData t1, SubtypeData t2) { - return intersect(t1, complement(t2)); - } - - @Override - public SubtypeData complement(SubtypeData t) { - FloatSubtype s = (FloatSubtype) t; - return FloatSubtype.createFloatSubtype(!s.allowed, s.values); - } - - @Override - public boolean isEmpty(Context cx, SubtypeData t) { - return Common.notIsEmpty(cx, t); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/FunctionOps.java b/semtypes/src/main/java/io/ballerina/types/typeops/FunctionOps.java deleted file mode 100644 index 11ce0296a305..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/FunctionOps.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.BasicTypeOps; -import io.ballerina.types.Bdd; -import io.ballerina.types.Common; -import io.ballerina.types.Conjunction; -import io.ballerina.types.Context; -import io.ballerina.types.Core; -import io.ballerina.types.FunctionAtomicType; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SubtypeData; - -import java.io.PrintStream; - -import static io.ballerina.types.Common.memoSubtypeIsEmpty; - -/** - * Function specific methods operate on SubtypeData. - * - * @since 2201.8.0 - */ -public class FunctionOps extends CommonOps implements BasicTypeOps { - - private static final PrintStream console = System.out; - - @Override - public boolean isEmpty(Context cx, SubtypeData t) { - return memoSubtypeIsEmpty(cx, cx.functionMemo, - (context, bdd) -> Common.bddEvery(context, bdd, null, null, FunctionOps::functionFormulaIsEmpty), - (Bdd) t); - } - - private static boolean functionFormulaIsEmpty(Context cx, Conjunction pos, Conjunction neg) { - return functionPathIsEmpty(cx, functionIntersectRet(cx, pos), functionUnionParams(cx, pos), - functionUnionQualifiers(cx, pos), pos, neg); - } - - private static boolean functionPathIsEmpty(Context cx, SemType rets, SemType params, SemType qualifiers, - Conjunction pos, Conjunction neg) { - if (neg == null) { - return false; - } else { - FunctionAtomicType t = cx.functionAtomType(neg.atom); - SemType t0 = t.paramType(); - SemType t1 = t.retType(); - SemType t2 = t.qualifiers(); - if (t.isGeneric()) { - // TODO: this is not correct. Ideally we should either resolve generic function calls to concrete - // function or properly support generics. However in order to support former we need some sort of - // monomorphization (at least for types) since generics can contain calls to other generics, and - // in order to do latter we need to define generics properly in spec. Untill that we are going to use - // a hack just to make sure internal libraries type checks passes - return (Core.isSubtype(cx, qualifiers, t2) && Core.isSubtype(cx, params, t0) && - Core.isSubtype(cx, rets, t1)) - || functionPathIsEmpty(cx, rets, params, qualifiers, pos, neg.next); - } - return (Core.isSubtype(cx, qualifiers, t2) && Core.isSubtype(cx, t0, params) && - functionPhi(cx, t0, Core.complement(t1), pos)) - || functionPathIsEmpty(cx, rets, params, qualifiers, pos, neg.next); - } - } - - private static boolean functionPhi(Context cx, SemType t0, SemType t1, Conjunction pos) { - if (pos == null) { - // t0 is NEVER only for function top types with qualifiers - return !Core.isNever(t0) && (Core.isEmpty(cx, t0) || Core.isEmpty(cx, t1)); - } - return functionPhiInner(cx, t0, t1, pos); - } - - private static boolean functionPhiInner(Context cx, SemType t0, SemType t1, Conjunction pos) { - if (pos == null) { - return Core.isEmpty(cx, t0) || Core.isEmpty(cx, t1); - } else { - FunctionAtomicType s = cx.functionAtomType(pos.atom); - SemType s0 = s.paramType(); - SemType s1 = s.retType(); - return (Core.isSubtype(cx, t0, s0) - || Core.isSubtype(cx, functionIntersectRet(cx, pos.next), Core.complement(t1))) - && functionPhiInner(cx, t0, Core.intersect(t1, s1), pos.next) - && functionPhiInner(cx, Core.diff(t0, s0), t1, pos.next); - } - } - - - private static SemType functionUnionParams(Context cx, Conjunction pos) { - if (pos == null) { - return PredefinedType.NEVER; - } - return Core.union(cx.functionAtomType(pos.atom).paramType(), functionUnionParams(cx, pos.next)); - } - - private static SemType functionUnionQualifiers(Context cx, Conjunction pos) { - if (pos == null) { - return PredefinedType.NEVER; - } - return Core.union(cx.functionAtomType(pos.atom).qualifiers(), functionUnionQualifiers(cx, pos.next)); - } - - - private static SemType functionIntersectRet(Context cx, Conjunction pos) { - if (pos == null) { - return PredefinedType.VAL; - } - return Core.intersect(cx.functionAtomType(pos.atom).retType(), functionIntersectRet(cx, pos.next)); - } - - private boolean functionTheta(Context cx, SemType t0, SemType t1, Conjunction pos) { - if (pos == null) { - return Core.isEmpty(cx, t0) || Core.isEmpty(cx, t1); - } else { - // replaces the SemType[2] [s0, s1] in nballerina where s0 = paramType, s1 = retType - FunctionAtomicType s = cx.functionAtomType(pos.atom); - SemType s0 = s.paramType(); - SemType s1 = s.retType(); - return (Core.isSubtype(cx, t0, s0) || functionTheta(cx, Core.diff(s0, t0), s1, pos.next)) - && (Core.isSubtype(cx, t1, Core.complement(s1)) - || functionTheta(cx, s0, Core.intersect(s1, t1), pos.next)); - } - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/FutureOps.java b/semtypes/src/main/java/io/ballerina/types/typeops/FutureOps.java deleted file mode 100644 index ad4114f41706..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/FutureOps.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.BasicTypeOps; -import io.ballerina.types.Context; -import io.ballerina.types.SubtypeData; - -import static io.ballerina.types.typeops.MappingOps.mappingSubtypeIsEmpty; - -/** - * Basic type ops for future type. - * - * @since 2201.10.0 - */ -public class FutureOps extends CommonOps implements BasicTypeOps { - - @Override - public boolean isEmpty(Context cx, SubtypeData t) { - return mappingSubtypeIsEmpty(cx, t); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/IntOps.java b/semtypes/src/main/java/io/ballerina/types/typeops/IntOps.java deleted file mode 100644 index accaf8640732..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/IntOps.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.BasicTypeOps; -import io.ballerina.types.Common; -import io.ballerina.types.Context; -import io.ballerina.types.SubtypeData; -import io.ballerina.types.subtypedata.AllOrNothingSubtype; -import io.ballerina.types.subtypedata.IntSubtype; -import io.ballerina.types.subtypedata.Range; -import io.ballerina.types.subtypedata.RangeUnion; - -import java.util.ArrayList; -import java.util.List; - -import static java.lang.Long.MAX_VALUE; -import static java.lang.Long.MIN_VALUE; - -/** - * Basic subtype ops for int type. - * - * @since 2201.8.0 - */ -public class IntOps implements BasicTypeOps { - - private static IntOps intOpsInstance = new IntOps(); - - @Override - public SubtypeData union(SubtypeData d1, SubtypeData d2) { - IntSubtype v1 = (IntSubtype) d1; - IntSubtype v2 = (IntSubtype) d2; - Range[] v = rangeListUnion(v1.ranges, v2.ranges); - if (v.length == 1 && v[0].min == MIN_VALUE && v[0].max == MAX_VALUE) { - return AllOrNothingSubtype.createAll(); - } - return IntSubtype.createIntSubtype(v); - } - - @Override - public SubtypeData intersect(SubtypeData d1, SubtypeData d2) { - IntSubtype v1 = (IntSubtype) d1; - IntSubtype v2 = (IntSubtype) d2; - Range[] v = rangeListIntersect(v1.ranges, v2.ranges); - if (v.length == 0) { - return AllOrNothingSubtype.createNothing(); - } - return IntSubtype.createIntSubtype(v); - } - - @Override - public SubtypeData diff(SubtypeData d1, SubtypeData d2) { - IntSubtype v1 = (IntSubtype) d1; - IntSubtype v2 = (IntSubtype) d2; - Range[] v = rangeListIntersect(v1.ranges, rangeListComplement(v2.ranges)); - if (v.length == 0) { - return AllOrNothingSubtype.createNothing(); - } - return IntSubtype.createIntSubtype(v); - } - - @Override - public SubtypeData complement(SubtypeData d) { - IntSubtype v = (IntSubtype) d; - return IntSubtype.createIntSubtype(rangeListComplement(v.ranges)); - } - - static boolean intSubtypeOverlapRange(IntSubtype subtype, Range range) { - SubtypeData subtypeData = intOpsInstance.intersect(subtype, IntSubtype.createIntSubtype(range)); - return !(subtypeData instanceof AllOrNothingSubtype allOrNothingSubtype && - allOrNothingSubtype.isNothingSubtype()); - } - - public static long intSubtypeMax(IntSubtype subtype) { - return subtype.ranges[subtype.ranges.length - 1].max; - } - - public static long intSubtypeMin(IntSubtype subtype) { - return subtype.ranges[0].min; - } - - @Override - public boolean isEmpty(Context cx, SubtypeData t) { - return Common.notIsEmpty(cx, t); - } - - private Range[] rangeListUnion(Range[] v1, Range[] v2) { - List result = new ArrayList<>(); - int i1 = 0; - int i2 = 0; - int len1 = v1.length; - int len2 = v2.length; - - while (true) { - if (i1 >= len1) { - if (i2 >= len2) { - break; - } - rangeUnionPush(result, v2[i2]); - i2 += 1; - } else if (i2 >= len2) { - rangeUnionPush(result, v1[i1]); - i1 += 1; - } else { - Range r1 = v1[i1]; - Range r2 = v2[i2]; - RangeUnion combined = rangeUnion(r1, r2); - if (combined.status == 0) { - rangeUnionPush(result, combined.range); - i1 += 1; - i2 += 1; - } else if (combined.status < 0) { - rangeUnionPush(result, r1); - i1 += 1; - } else { - rangeUnionPush(result, r2); - i2 += 1; - } - } - } - Range[] rangeList = new Range[result.size()]; - return result.toArray(rangeList); - } - - private void rangeUnionPush(List ranges, Range next) { - int lastIndex = ranges.size() - 1; - if (lastIndex < 0) { - ranges.add(next); - return; - } - RangeUnion combined = rangeUnion(ranges.get(lastIndex), next); - if (combined.status == 0) { - ranges.set(lastIndex, combined.range); - } else { - ranges.add(next); - } - } - /* [from nballerina] Returns a range if there is a single range representing the union of r1 and r1. - -1 means union is empty because r1 is before r2, with no overlap - 1 means union is empty because r2 is before r1 with no overlap - Precondition r1 and r2 are non-empty */ - private RangeUnion rangeUnion(Range r1, Range r2) { - if (r1.max < r2.min) { - if (r1.max + 1 != r2.min) { - return RangeUnion.from(-1); - } - } - if (r2.max < r1.min) { - if (r2.max + 1 != r1.min) { - return RangeUnion.from(1); - } - } - return RangeUnion.from(new Range(Long.min(r1.min, r2.min), Long.max(r1.max, r2.max))); - } - - private Range[] rangeListIntersect(Range[] v1, Range[] v2) { - List result = new ArrayList<>(); - int i1 = 0; - int i2 = 0; - int len1 = v1.length; - int len2 = v2.length; - while (true) { - if (i1 >= len1 || i2 >= len2) { - break; - } else { - Range r1 = v1[i1]; - Range r2 = v2[i2]; - RangeUnion combined = rangeIntersect(r1, r2); - if (combined.status == 0) { - result.add(combined.range); - i1 += 1; - i2 += 1; - } else if (combined.status < 0) { - i1 += 1; - } else { - i2 += 1; - } - } - } - Range[] rangeList = new Range[result.size()]; - return result.toArray(rangeList); - } - - /* [from nballerina] When Range is returned, it is non-empty and the intersection of r1 and r2 - -1 means empty intersection because r1 before r2 - 1 means empty intersection because r1 after r2 */ - private RangeUnion rangeIntersect(Range r1, Range r2) { - if (r1.max < r2.min) { - return RangeUnion.from(-1); - } - if (r2.max < r1.min) { - return RangeUnion.from(1); - } - return RangeUnion.from(new Range(Long.max(r1.min, r2.min), Long.min(r1.max, r2.max))); - } - - private Range[] rangeListComplement(Range[] v) { - List result = new ArrayList<>(); - int len = v.length; - long min = v[0].min; - if (min > MIN_VALUE) { - result.add(new Range(MIN_VALUE, min - 1)); - } - for (int i = 1; i < len; i++) { - result.add(new Range(v[i - 1].max + 1, v[i].min - 1)); - } - long max = v[v.length - 1].max; - if (max < MAX_VALUE) { - result.add(new Range(max + 1, MAX_VALUE)); - } - return result.toArray(new Range[]{}); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/ListOps.java b/semtypes/src/main/java/io/ballerina/types/typeops/ListOps.java deleted file mode 100644 index 406bd48e91e3..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/ListOps.java +++ /dev/null @@ -1,441 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.Atom; -import io.ballerina.types.BasicTypeOps; -import io.ballerina.types.Bdd; -import io.ballerina.types.CellSemType; -import io.ballerina.types.Common; -import io.ballerina.types.Conjunction; -import io.ballerina.types.Context; -import io.ballerina.types.Core; -import io.ballerina.types.Env; -import io.ballerina.types.FixedLengthArray; -import io.ballerina.types.ListAtomicType; -import io.ballerina.types.SemType; -import io.ballerina.types.SubtypeData; -import io.ballerina.types.subtypedata.BddAllOrNothing; -import io.ballerina.types.subtypedata.BddNode; -import io.ballerina.types.subtypedata.IntSubtype; -import io.ballerina.types.subtypedata.Range; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.stream.IntStream; - -import static io.ballerina.types.Common.bddSubtypeComplement; -import static io.ballerina.types.Common.bddSubtypeDiff; -import static io.ballerina.types.Common.bddSubtypeIntersect; -import static io.ballerina.types.Common.bddSubtypeUnion; -import static io.ballerina.types.Common.memoSubtypeIsEmpty; -import static io.ballerina.types.Core.cellContainingInnerVal; -import static io.ballerina.types.Core.cellInner; -import static io.ballerina.types.Core.cellInnerVal; -import static io.ballerina.types.Core.intersectMemberSemTypes; -import static io.ballerina.types.PredefinedType.LIST_ATOMIC_INNER; -import static io.ballerina.types.PredefinedType.NEVER; -import static io.ballerina.types.PredefinedType.UNDEF; -import static io.ballerina.types.subtypedata.IntSubtype.intSubtypeContains; -import static io.ballerina.types.typeops.IntOps.intSubtypeMax; -import static io.ballerina.types.typeops.IntOps.intSubtypeOverlapRange; - -/** - * Basic type ops for list type. - * - * @since 2201.8.0 - */ -public class ListOps extends CommonOps implements BasicTypeOps { - - static boolean listSubtypeIsEmpty(Context cx, SubtypeData t) { - return memoSubtypeIsEmpty(cx, cx.listMemo, - (context, bdd) -> Common.bddEvery(context, bdd, null, null, ListOps::listFormulaIsEmpty), - (Bdd) t); - } - - private static boolean listFormulaIsEmpty(Context cx, Conjunction pos, Conjunction neg) { - FixedLengthArray members; - CellSemType rest; - if (pos == null) { - ListAtomicType atom = LIST_ATOMIC_INNER; - members = atom.members(); - rest = atom.rest(); - } else { - // combine all the positive tuples using intersection - ListAtomicType lt = cx.listAtomType(pos.atom); - members = lt.members(); - rest = lt.rest(); - Conjunction p = pos.next; - // the neg case is in case we grow the array in listInhabited - if (p != null || neg != null) { - // Jbal note: we don't need this as we already created copies when converting from array to list. - // Just keeping this for the sake of source similarity between Bal code and Java. - members = fixedArrayShallowCopy(members); - } - while (true) { - if (p == null) { - break; - } else { - Atom d = p.atom; - p = p.next; - lt = cx.listAtomType(d); - TwoTuple - intersected = listIntersectWith(cx.env, members, rest, lt.members(), lt.rest()); - if (intersected == null) { - return true; - } - members = intersected.item1; - rest = intersected.item2; - } - } - if (fixedArrayAnyEmpty(cx, members)) { - return true; - } - } - List indices = listSamples(cx, members, rest, neg); - TwoTuple, Integer> sampleTypes = listSampleTypes(cx, members, rest, indices); - return !listInhabited(cx, indices.toArray(new Integer[0]), - sampleTypes.item1.toArray(SemType[]::new), - sampleTypes.item2, neg); - } - - public static TwoTuple, Integer> listSampleTypes(Context cx, FixedLengthArray members, - CellSemType rest, List indices) { - List memberTypes = new ArrayList<>(); - int nRequired = 0; - for (int i = 0; i < indices.size(); i++) { - int index = indices.get(i); - CellSemType t = cellContainingInnerVal(cx.env, listMemberAt(members, rest, index)); - if (Core.isEmpty(cx, t)) { - break; - } - memberTypes.add(t); - if (index < members.fixedLength()) { - nRequired = i + 1; - } - } - return TwoTuple.from(memberTypes, nRequired); - } - - // Return a list of sample indices for use as second argument of `listInhabited`. - // The positive list type P is represented by `members` and `rest`. - // The negative list types N are represented by `neg` - // The `indices` list (first member of return value) is constructed in two stages. - // First, the set of all non-negative integers is partitioned so that two integers are - // in different partitions if they get different types as an index in P or N. - // Second, we choose a number of samples from each partition. It doesn't matter - // which sample we choose, but (this is the key point) we need at least as many samples - // as there are negatives in N, so that for each negative we can freely choose a type for the sample - // to avoid being matched by that negative. - static List listSamples(Context cx, FixedLengthArray members, SemType rest, Conjunction neg) { - int maxInitialLength = members.initial().size(); - List fixedLengths = new ArrayList<>(); - fixedLengths.add(members.fixedLength()); - Conjunction tem = neg; - int nNeg = 0; - while (true) { - if (tem != null) { - ListAtomicType lt = cx.listAtomType(tem.atom); - FixedLengthArray m = lt.members(); - maxInitialLength = Integer.max(maxInitialLength, m.initial().size()); - if (m.fixedLength() > maxInitialLength) { - fixedLengths.add(m.fixedLength()); - } - nNeg += 1; - tem = tem.next; - } else { - break; - } - } - Collections.sort(fixedLengths); - // `boundaries` partitions the non-negative integers - // Construct `boundaries` from `fixedLengths` and `maxInitialLength` - // An index b is a boundary point if indices < b are different from indices >= b - //int[] boundaries = from int i in 1 ... maxInitialLength select i; - List boundaries = new ArrayList<>(); - for (int i = 1; i <= maxInitialLength; i++) { - boundaries.add(i); - } - for (int n : fixedLengths) { - // this also removes duplicates - if (boundaries.size() == 0 || n > boundaries.get(boundaries.size() - 1)) { - boundaries.add(n); - } - } - // Now construct the list of indices by taking nNeg samples from each partition. - List indices = new ArrayList<>(); - int lastBoundary = 0; - if (nNeg == 0) { - // this is needed for when this is used in listProj - nNeg = 1; - } - for (int b : boundaries) { - int segmentLength = b - lastBoundary; - // Cannot have more samples than are in the parition. - int nSamples = Integer.min(segmentLength, nNeg); - for (int i = b - nSamples; i < b; i++) { - indices.add(i); - } - lastBoundary = b; - } - for (int i = 0; i < nNeg; i++) { - // Be careful to avoid integer overflow. - if (lastBoundary > Integer.MAX_VALUE - i) { - break; - } - indices.add(lastBoundary + i); - } - return indices; - } - - static TwoTuple listIntersectWith(Env env, FixedLengthArray members1, - CellSemType rest1, FixedLengthArray members2, - CellSemType rest2) { - if (listLengthsDisjoint(members1, rest1, members2, rest2)) { - return null; - } - // This is different from nBallerina, but I think assuming we have normalized the FixedLengthArrays we must - // consider fixedLengths not the size of initial members. For example consider any[4] and - // [int, string, float...]. If we don't consider the fixedLength in the initial part we'll consider only the - // first two elements and rest will compare essentially 5th element, meaning we are ignoring 3 and 4 elements - int max = Integer.max(members1.fixedLength(), members2.fixedLength()); - List initial = - IntStream.range(0, max) - .mapToObj(i -> intersectMemberSemTypes(env, listMemberAt(members1, rest1, i), - listMemberAt(members2, rest2, i))) - .toList(); - return TwoTuple.from(FixedLengthArray.from(initial, - Integer.max(members1.fixedLength(), members2.fixedLength())), - intersectMemberSemTypes(env, rest1, rest2)); - } - - static FixedLengthArray fixedArrayShallowCopy(FixedLengthArray array) { - return FixedLengthArray.from(array.initial(), array.fixedLength()); - } - - // This function determines whether a list type P & N is inhabited. - // where P is a positive list type and N is a list of negative list types. - // With just straightforward fixed-length tuples we can consider every index of the tuple. - // But we cannot do this in general because of rest types and fixed length array types e.g. `byte[10000000]`. - // So we consider instead a collection of indices that is sufficient for us to determine inhabitation, - // given the types of P and N. - // `indices` is this list of sample indices: these are indicies into members of the list type. - // We don't represent P directly. Instead P is represented by `memberTypes` and `nRequired`: - // `memberTypes[i]` is the type that P gives to `indices[i]`; - // `nRequired` is the number of members of `memberTypes` that are required by P. - // `neg` represents N. - static boolean listInhabited(Context cx, Integer[] indices, SemType[] memberTypes, int nRequired, Conjunction neg) { - // TODO: Way `listInhabited` method works is essentially removing negative atoms one by one until either we - // run-out of negative atoms or there is nothing left in the positive (intersection) atom. While correctness - // of this method is independent of the order of negative atoms, the performance of this method is dependent - // on the order. For example consider positive atom is int[] and we have negative atoms int[1], int[2], - // int[3], any[]. If we start with any[] we immediately know it is not inhabited whereas in any other order we - // have to evaluate until we come to any[] to figure this out. We say any[] is larger than others since it - // covers more values than them. According to Frisch section 7.3.1 we should use this size as an heuristic to - // sort negative atoms. However it is not clear to me how to estimate the size correctly - if (neg == null) { - return true; - } else { - final ListAtomicType nt = cx.listAtomType(neg.atom); - if (nRequired > 0 && Core.isNever(listMemberAtInnerVal(nt.members(), nt.rest(), indices[nRequired - 1]))) { - // Skip this negative if it is always shorter than the minimum required by the positive - return listInhabited(cx, indices, memberTypes, nRequired, neg.next); - } - int negLen = nt.members().fixedLength(); - if (negLen > 0) { - // If we have isEmpty(T1 & S1) or isEmpty(T2 & S2) then we have [T1, T2] / [S1, S2] = [T1, T2]. - // Therefore, we can skip the negative - for (int i = 0; i < memberTypes.length; i++) { - int index = indices[i]; - if (index >= negLen) { - break; - } - SemType negMemberType = listMemberAt(nt.members(), nt.rest(), index); - SemType common = Core.intersect(memberTypes[i], negMemberType); - if (Core.isEmpty(cx, common)) { - return listInhabited(cx, indices, memberTypes, nRequired, neg.next); - } - } - // Consider cases we can avoid this negative by having a sufficiently short list - int len = memberTypes.length; - if (len < indices.length && indices[len] < negLen) { - return listInhabited(cx, indices, memberTypes, nRequired, neg.next); - } - for (int i = nRequired; i < memberTypes.length; i++) { - if (indices[i] >= negLen) { - break; - } - // TODO: avoid creating new arrays here - SemType[] t = Arrays.copyOfRange(memberTypes, 0, i); - if (listInhabited(cx, indices, t, nRequired, neg.next)) { - return true; - } - } - } - // Now we need to explore the possibility of shapes with length >= neglen - // This is the heart of the algorithm. - // For [v0, v1] not to be in [t0,t1], there are two possibilities - // (1) v0 is not in t0, or - // (2) v1 is not in t1 - // Case (1) - // For v0 to be in s0 but not t0, d0 must not be empty. - // We must then find a [v0,v1] satisfying the remaining negated tuples, - // such that v0 is in d0. - // SemType d0 = diff(s[0], t[0]); - // if !isEmpty(cx, d0) && tupleInhabited(cx, [d0, s[1]], neg.rest) { - // return true; - // } - // Case (2) - // For v1 to be in s1 but not t1, d1 must not be empty. - // We must then find a [v0,v1] satisfying the remaining negated tuples, - // such that v1 is in d1. - // SemType d1 = diff(s[1], t[1]); - // return !isEmpty(cx, d1) && tupleInhabited(cx, [s[0], d1], neg.rest); - // We can generalize this to tuples of arbitrary length. - for (int i = 0; i < memberTypes.length; i++) { - SemType d = Core.diff(memberTypes[i], listMemberAt(nt.members(), nt.rest(), indices[i])); - if (!Core.isEmpty(cx, d)) { - SemType[] t = memberTypes.clone(); - t[i] = d; - // We need to make index i be required - if (listInhabited(cx, indices, t, Integer.max(nRequired, i + 1), neg.next)) { - return true; - } - } - } - // This is correct for length 0, because we know that the length of the - // negative is 0, and [] - [] is empty. - return false; - } - } - - static SemType listMemberAtInnerVal(FixedLengthArray fixedArray, CellSemType rest, int index) { - return cellInnerVal(listMemberAt(fixedArray, rest, index)); - } - - private static boolean listLengthsDisjoint(FixedLengthArray members1, CellSemType rest1, - FixedLengthArray members2, CellSemType rest2) { - int len1 = members1.fixedLength(); - int len2 = members2.fixedLength(); - if (len1 < len2) { - return Core.isNever(cellInnerVal(rest1)); - } - if (len2 < len1) { - return Core.isNever(cellInnerVal(rest2)); - } - return false; - } - - static CellSemType listMemberAt(FixedLengthArray fixedArray, CellSemType rest, int index) { - if (index < fixedArray.fixedLength()) { - return fixedArrayGet(fixedArray, index); - } - return rest; - } - - static boolean fixedArrayAnyEmpty(Context cx, FixedLengthArray array) { - for (var t : array.initial()) { - if (Core.isEmpty(cx, t)) { - return true; - } - } - return false; - } - - private static CellSemType fixedArrayGet(FixedLengthArray members, int index) { - int memberLen = members.initial().size(); - int i = Integer.min(index, memberLen - 1); - return members.initial().get(i); - } - - static SemType listAtomicMemberTypeInnerVal(ListAtomicType atomic, SubtypeData key) { - return Core.diff(listAtomicMemberTypeInner(atomic, key), UNDEF); - } - - private static SemType listAtomicMemberTypeInner(ListAtomicType atomic, SubtypeData key) { - return listAtomicMemberTypeAtInner(atomic.members(), atomic.rest(), key); - } - - static SemType listAtomicMemberTypeAtInner(FixedLengthArray fixedArray, CellSemType rest, SubtypeData key) { - if (key instanceof IntSubtype intSubtype) { - SemType m = NEVER; - int initLen = fixedArray.initial().size(); - int fixedLen = fixedArray.fixedLength(); - if (fixedLen != 0) { - for (int i = 0; i < initLen; i++) { - if (intSubtypeContains(key, i)) { - m = Core.union(m, cellInner(fixedArrayGet(fixedArray, i))); - } - } - if (intSubtypeOverlapRange(intSubtype, Range.from(initLen, fixedLen - 1))) { - m = Core.union(m, cellInner(fixedArrayGet(fixedArray, fixedLen - 1))); - } - } - if (fixedLen == 0 || intSubtypeMax((IntSubtype) key) > fixedLen - 1) { - m = Core.union(m, cellInner(rest)); - } - return m; - } - SemType m = cellInner(rest); - if (fixedArray.fixedLength() > 0) { - for (CellSemType ty : fixedArray.initial()) { - m = Core.union(m, cellInner(ty)); - } - } - return m; - } - - public static SemType bddListMemberTypeInnerVal(Context cx, Bdd b, SubtypeData key, SemType accum) { - if (b instanceof BddAllOrNothing allOrNothing) { - return allOrNothing.isAll() ? accum : NEVER; - } else { - BddNode bddNode = (BddNode) b; - return Core.union(bddListMemberTypeInnerVal(cx, bddNode.left(), key, - Core.intersect(listAtomicMemberTypeInnerVal(cx.listAtomType(bddNode.atom()), key), accum)), - Core.union(bddListMemberTypeInnerVal(cx, bddNode.middle(), key, accum), - bddListMemberTypeInnerVal(cx, bddNode.right(), key, accum))); - } - } - - @Override - public SubtypeData union(SubtypeData d1, SubtypeData d2) { - return bddSubtypeUnion(d1, d2); - } - - @Override - public SubtypeData intersect(SubtypeData d1, SubtypeData d2) { - return bddSubtypeIntersect(d1, d2); - } - - @Override - public SubtypeData diff(SubtypeData d1, SubtypeData d2) { - return bddSubtypeDiff(d1, d2); - } - - @Override - public SubtypeData complement(SubtypeData d) { - return bddSubtypeComplement(d); - } - - @Override - public boolean isEmpty(Context cx, SubtypeData d) { - return listSubtypeIsEmpty(cx, d); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/ListProj.java b/semtypes/src/main/java/io/ballerina/types/typeops/ListProj.java deleted file mode 100644 index 379da6baeae0..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/ListProj.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.Atom; -import io.ballerina.types.BasicTypeBitSet; -import io.ballerina.types.Bdd; -import io.ballerina.types.CellSemType; -import io.ballerina.types.ComplexSemType; -import io.ballerina.types.Conjunction; -import io.ballerina.types.Context; -import io.ballerina.types.Core; -import io.ballerina.types.FixedLengthArray; -import io.ballerina.types.ListAtomicType; -import io.ballerina.types.SemType; -import io.ballerina.types.SubtypeData; -import io.ballerina.types.subtypedata.BddAllOrNothing; -import io.ballerina.types.subtypedata.BddNode; -import io.ballerina.types.subtypedata.CellSubtype; -import io.ballerina.types.subtypedata.IntSubtype; -import io.ballerina.types.subtypedata.Range; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; -import java.util.Objects; - -import static io.ballerina.types.BasicTypeCode.BT_LIST; -import static io.ballerina.types.Common.isNothingSubtype; -import static io.ballerina.types.Conjunction.and; -import static io.ballerina.types.Core.cellInnerVal; -import static io.ballerina.types.Core.diff; -import static io.ballerina.types.Core.getComplexSubtypeData; -import static io.ballerina.types.Core.isEmpty; -import static io.ballerina.types.Core.isNever; -import static io.ballerina.types.Core.union; -import static io.ballerina.types.PredefinedType.LIST; -import static io.ballerina.types.PredefinedType.NEVER; -import static io.ballerina.types.PredefinedType.UNDEF; -import static io.ballerina.types.PredefinedType.VAL; -import static io.ballerina.types.subtypedata.CellSubtype.cellContaining; -import static io.ballerina.types.subtypedata.IntSubtype.intSubtypeContains; -import static io.ballerina.types.typeops.ListOps.fixedArrayAnyEmpty; -import static io.ballerina.types.typeops.ListOps.fixedArrayShallowCopy; -import static io.ballerina.types.typeops.ListOps.listIntersectWith; -import static io.ballerina.types.typeops.ListOps.listMemberAtInnerVal; - -/** - * Class to hold functions ported from `listProj.bal` file. - * - * @since 2201.8.0 - */ -public class ListProj { - // Untested full implementation of list projection. - - // Based on listMemberType - public static SemType listProjInnerVal(Context cx, SemType t, SemType k) { - if (t instanceof BasicTypeBitSet b) { - return (b.bitset & LIST.bitset) != 0 ? VAL : NEVER; - } else { - SubtypeData keyData = Core.intSubtype(k); - if (isNothingSubtype(keyData)) { - return NEVER; - } - return listProjBddInnerVal(cx, keyData, (Bdd) getComplexSubtypeData((ComplexSemType) t, BT_LIST), null, - null); - } - } - - // Based on bddEvery - static SemType listProjBddInnerVal(Context cx, SubtypeData k, Bdd b, Conjunction pos, Conjunction neg) { - if (b instanceof BddAllOrNothing allOrNothing) { - return allOrNothing.isAll() ? listProjPathInnerVal(cx, k, pos, neg) : NEVER; - } else { - BddNode bddNode = (BddNode) b; - return union(listProjBddInnerVal(cx, k, bddNode.left(), and(bddNode.atom(), pos), neg), - union(listProjBddInnerVal(cx, k, bddNode.middle(), pos, neg), - listProjBddInnerVal(cx, k, bddNode.right(), pos, and(bddNode.atom(), neg)))); - } - } - - // Based on listFormulaIsEmpty - static SemType listProjPathInnerVal(Context cx, SubtypeData k, Conjunction pos, Conjunction neg) { - FixedLengthArray members; - CellSemType rest; - if (pos == null) { - members = FixedLengthArray.empty(); - rest = cellContaining(cx.env, union(VAL, UNDEF)); - } else { - // combine all the positive tuples using intersection - ListAtomicType lt = cx.listAtomType(pos.atom); - members = lt.members(); - rest = lt.rest(); - Conjunction p = pos.next; - // the neg case is in case we grow the array in listInhabited - if (p != null || neg != null) { - members = fixedArrayShallowCopy(members); - } - - while (true) { - if (p == null) { - break; - } else { - Atom d = p.atom; - p = p.next; - lt = cx.listAtomType(d); - TwoTuple - intersected = listIntersectWith(cx.env, members, rest, lt.members(), lt.rest()); - if (intersected == null) { - return NEVER; - } - members = intersected.item1; - rest = intersected.item2; - } - } - if (fixedArrayAnyEmpty(cx, members)) { - return NEVER; - } - // Ensure that we can use isNever on rest in listInhabited - if (!Core.isNever(cellInnerVal(rest)) && isEmpty(cx, rest)) { - rest = CellSubtype.roCellContaining(cx.env, NEVER); - } - } - // return listProjExclude(cx, k, members, rest, listConjunction(cx, neg)); - List indices = ListOps.listSamples(cx, members, rest, neg); - TwoTuple, List> projSamples = listProjSamples(indices, k); - indices = projSamples.item1; - TwoTuple, Integer> sampleTypes = ListOps.listSampleTypes(cx, members, rest, indices); - return listProjExcludeInnerVal(cx, projSamples.item1.toArray(Integer[]::new), - projSamples.item2.toArray(Integer[]::new), - sampleTypes.item1.toArray(CellSemType[]::new), - sampleTypes.item2, neg); - } - - // In order to adapt listInhabited to do projection, we need - // to know which samples correspond to keys and to ensure that - // every equivalence class that overlaps with a key has a sample in the - // intersection. - // Here we add samples for both ends of each range. This doesn't handle the - // case where the key is properly within a partition: but that is handled - // because we already have a sample of the end of the partition. - private static TwoTuple, List> listProjSamples(List indices, SubtypeData k) { - List> v = new ArrayList<>(); - for (int i : indices) { - v.add(TwoTuple.from(i, intSubtypeContains(k, i))); - } - if (k instanceof IntSubtype intSubtype) { - for (Range range : intSubtype.ranges) { - long max = range.max; - if (range.max >= 0) { - v.add(TwoTuple.from((int) max, true)); - int min = Integer.max(0, (int) range.min); - if (min < max) { - v.add(TwoTuple.from(min, true)); - } - } - } - } - v.sort(Comparator.comparingInt(p -> p.item1)); - List indices1 = new ArrayList<>(); - List keyIndices = new ArrayList<>(); - for (var ib : v) { - if (indices1.isEmpty() || !Objects.equals(ib.item1, indices1.get(indices1.size() - 1))) { - if (ib.item2) { - keyIndices.add(indices1.size()); - } - indices1.add(ib.item1); - } - } - return TwoTuple.from(indices1, keyIndices); - } - - // `keyIndices` are the indices in `memberTypes` of those samples that belong to the key type. - // Based on listInhabited - // Corresponds to phi^x in AMK tutorial generalized for list types. - static SemType listProjExcludeInnerVal(Context cx, Integer[] indices, Integer[] keyIndices, - CellSemType[] memberTypes, int nRequired, Conjunction neg) { - SemType p = NEVER; - if (neg == null) { - int len = memberTypes.length; - for (int k : keyIndices) { - if (k < len) { - p = union(p, cellInnerVal(memberTypes[k])); - } - } - } else { - final ListAtomicType nt = cx.listAtomType(neg.atom); - if (nRequired > 0 && isNever(listMemberAtInnerVal(nt.members(), nt.rest(), indices[nRequired - 1]))) { - return listProjExcludeInnerVal(cx, indices, keyIndices, memberTypes, nRequired, neg.next); - } - int negLen = nt.members().fixedLength(); - if (negLen > 0) { - int len = memberTypes.length; - if (len < indices.length && indices[len] < negLen) { - return listProjExcludeInnerVal(cx, indices, keyIndices, memberTypes, nRequired, neg.next); - } - for (int i = nRequired; i < memberTypes.length; i++) { - if (indices[i] >= negLen) { - break; - } - // TODO: think about a way to avoid this allocation here and instead create view and pass it in - CellSemType[] t = Arrays.copyOfRange(memberTypes, 0, i); - p = union(p, listProjExcludeInnerVal(cx, indices, keyIndices, t, nRequired, neg.next)); - } - } - for (int i = 0; i < memberTypes.length; i++) { - SemType d = - diff(cellInnerVal(memberTypes[i]), listMemberAtInnerVal(nt.members(), nt.rest(), indices[i])); - if (!Core.isEmpty(cx, d)) { - CellSemType[] t = memberTypes.clone(); - t[i] = cellContaining(cx.env, d); - // We need to make index i be required - p = union(p, listProjExcludeInnerVal(cx, indices, keyIndices, t, Integer.max(nRequired, i + 1), - neg.next)); - } - } - } - return p; - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/MappingOps.java b/semtypes/src/main/java/io/ballerina/types/typeops/MappingOps.java deleted file mode 100644 index 17305851e6cd..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/MappingOps.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.BasicTypeOps; -import io.ballerina.types.Bdd; -import io.ballerina.types.CellSemType; -import io.ballerina.types.Common; -import io.ballerina.types.Conjunction; -import io.ballerina.types.Context; -import io.ballerina.types.Core; -import io.ballerina.types.Env; -import io.ballerina.types.MappingAtomicType; -import io.ballerina.types.SemType; -import io.ballerina.types.SubtypeData; -import io.ballerina.types.subtypedata.BddAllOrNothing; -import io.ballerina.types.subtypedata.BddNode; -import io.ballerina.types.subtypedata.StringSubtype; - -import java.util.ArrayList; -import java.util.List; - -import static io.ballerina.types.Common.bddSubtypeComplement; -import static io.ballerina.types.Common.bddSubtypeDiff; -import static io.ballerina.types.Common.bddSubtypeIntersect; -import static io.ballerina.types.Common.bddSubtypeUnion; -import static io.ballerina.types.Common.isAllSubtype; -import static io.ballerina.types.Common.memoSubtypeIsEmpty; -import static io.ballerina.types.PredefinedType.MAPPING_ATOMIC_INNER; -import static io.ballerina.types.PredefinedType.NEVER; -import static io.ballerina.types.PredefinedType.UNDEF; -import static io.ballerina.types.typeops.StringOps.stringSubtypeListCoverage; - -/** - * Basic type ops for mapping type. - * - * @since 2201.8.0 - */ -public class MappingOps extends CommonOps implements BasicTypeOps { - // This works the same as the tuple case, except that instead of - // just comparing the lengths of the tuples we compare the sorted list of field names - public static boolean mappingFormulaIsEmpty(Context cx, Conjunction posList, Conjunction negList) { - MappingAtomicType combined; - if (posList == null) { - combined = MAPPING_ATOMIC_INNER; - } else { - // combine all the positive atoms using intersection - combined = cx.mappingAtomType(posList.atom); - Conjunction p = posList.next; - while (true) { - if (p == null) { - break; - } else { - MappingAtomicType m = intersectMapping(cx.env, combined, cx.mappingAtomType(p.atom)); - if (m == null) { - return true; - } else { - combined = m; - } - p = p.next; - } - } - for (SemType t : combined.types()) { - if (Core.isEmpty(cx, t)) { - return true; - } - } - - } - return !mappingInhabited(cx, combined, negList); - } - - private static boolean mappingInhabited(Context cx, MappingAtomicType pos, Conjunction negList) { - if (negList == null) { - return true; - } else { - MappingAtomicType neg = cx.mappingAtomType(negList.atom); - - FieldPairs pairing = new FieldPairs(pos, neg); - if (!Core.isEmpty(cx, Core.diff(pos.rest(), neg.rest()))) { - return mappingInhabited(cx, pos, negList.next); - } - for (FieldPair fieldPair : pairing) { - SemType intersect = Core.intersect(fieldPair.type1(), fieldPair.type2()); - // if types of at least one field are disjoint, the neg atom will not contribute to the next iteration. - // Therefore, we can skip the current neg atom. - // i.e. if we have isEmpty(T1 & S1) or isEmpty(T2 & S2) then, - // record { T1 f1; T2 f2; } / record { S1 f1; S2 f2; } = record { T1 f1; T2 f2; } - if (Core.isEmpty(cx, intersect)) { - return mappingInhabited(cx, pos, negList.next); - } - - CellSemType d = (CellSemType) Core.diff(fieldPair.type1(), fieldPair.type2()); - if (!Core.isEmpty(cx, d)) { - MappingAtomicType mt; - if (fieldPair.index1() == null) { - // the posType came from the rest type - mt = insertField(pos, fieldPair.name(), d); - } else { - CellSemType[] posTypes = pos.types(); - posTypes[fieldPair.index1()] = d; - mt = MappingAtomicType.from(pos.names(), posTypes, pos.rest()); - } - if (mappingInhabited(cx, mt, negList.next)) { - return true; - } - } - } - return false; - } - } - - private static MappingAtomicType insertField(MappingAtomicType m, String name, CellSemType t) { - String[] orgNames = m.names(); - String[] names = Common.shallowCopyStrings(orgNames, orgNames.length + 1); - CellSemType[] orgTypes = m.types(); - CellSemType[] types = Common.shallowCopyCellTypes(orgTypes, orgTypes.length + 1); - int i = orgNames.length; - while (true) { - if (i == 0 || Common.codePointCompare(names[i - 1], name)) { - names[i] = name; - types[i] = t; - break; - } - names[i] = names[i - 1]; - types[i] = types[i - 1]; - i -= 1; - } - return MappingAtomicType.from(names, types, m.rest()); - } - - private static MappingAtomicType intersectMapping(Env env, MappingAtomicType m1, MappingAtomicType m2) { - List names = new ArrayList<>(); - List types = new ArrayList<>(); - FieldPairs pairing = new FieldPairs(m1, m2); - for (FieldPair fieldPair : pairing) { - names.add(fieldPair.name()); - CellSemType t = Core.intersectMemberSemTypes(env, fieldPair.type1(), fieldPair.type2()); - if (Core.isNever(Core.cellInner(fieldPair.type1()))) { - return null; - } - types.add(t); - } - CellSemType rest = Core.intersectMemberSemTypes(env, m1.rest(), m2.rest()); - return MappingAtomicType.from(names.toArray(new String[]{}), types.toArray(new CellSemType[]{}), rest); - } - - public static boolean mappingSubtypeIsEmpty(Context cx, SubtypeData t) { - return memoSubtypeIsEmpty(cx, cx.mappingMemo, - (context, bdd) -> Common.bddEvery(context, bdd, null, null, MappingOps::mappingFormulaIsEmpty), - (Bdd) t); - } - - public static SemType bddMappingMemberTypeInner(Context cx, Bdd b, SubtypeData key, SemType accum) { - if (b instanceof BddAllOrNothing allOrNothing) { - return allOrNothing.isAll() ? accum : NEVER; - } else { - BddNode bdd = (BddNode) b; - return Core.union( - bddMappingMemberTypeInner(cx, bdd.left(), key, - Core.intersect(mappingAtomicMemberTypeInner(cx.mappingAtomType(bdd.atom()), key), - accum)), - Core.union(bddMappingMemberTypeInner(cx, bdd.middle(), key, accum), - bddMappingMemberTypeInner(cx, bdd.right(), key, accum))); - } - } - - static SemType mappingAtomicMemberTypeInner(MappingAtomicType atomic, SubtypeData key) { - SemType memberType = null; - for (SemType ty : mappingAtomicApplicableMemberTypesInner(atomic, key)) { - if (memberType == null) { - memberType = ty; - } else { - memberType = Core.union(memberType, ty); - } - } - return memberType == null ? UNDEF : memberType; - } - - static List mappingAtomicApplicableMemberTypesInner(MappingAtomicType atomic, SubtypeData key) { - List types = new ArrayList<>(atomic.types().length); - for (CellSemType t : atomic.types()) { - types.add(Core.cellInner(t)); - } - - List memberTypes = new ArrayList<>(); - SemType rest = Core.cellInner(atomic.rest()); - if (isAllSubtype(key)) { - memberTypes.addAll(types); - memberTypes.add(rest); - } else { - StringSubtype.StringSubtypeListCoverage coverage = stringSubtypeListCoverage((StringSubtype) key, - atomic.names()); - for (int index : coverage.indices) { - memberTypes.add(types.get(index)); - } - if (!coverage.isSubtype) { - memberTypes.add(rest); - } - } - return memberTypes; - } - - @Override - public SubtypeData union(SubtypeData d1, SubtypeData d2) { - return bddSubtypeUnion(d1, d2); - } - - @Override - public SubtypeData intersect(SubtypeData d1, SubtypeData d2) { - return bddSubtypeIntersect(d1, d2); - } - - @Override - public SubtypeData diff(SubtypeData d1, SubtypeData d2) { - return bddSubtypeDiff(d1, d2); - } - - @Override - public SubtypeData complement(SubtypeData d) { - return bddSubtypeComplement(d); - } - - @Override - public boolean isEmpty(Context cx, SubtypeData d) { - return mappingSubtypeIsEmpty(cx, d); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/MappingPairIterator.java b/semtypes/src/main/java/io/ballerina/types/typeops/MappingPairIterator.java deleted file mode 100644 index f929daacf2d5..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/MappingPairIterator.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.CellSemType; -import io.ballerina.types.Common; -import io.ballerina.types.MappingAtomicType; - -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.util.Objects; -import java.util.Optional; - -/** - * Iteration implementation of `MappingPairIterator`. - * - * @since 2201.8.0 - */ -public class MappingPairIterator implements Iterator { - private final String[] names1; - private final String[] names2; - private final CellSemType[] types1; - private final CellSemType[] types2; - private final int len1; - private final int len2; - private int i1 = 0; - private int i2 = 0; - private final CellSemType rest1; - private final CellSemType rest2; - - private boolean doneIteration = false; - private boolean shouldCalculate = true; - private FieldPair cache = null; - - public MappingPairIterator(MappingAtomicType m1, MappingAtomicType m2) { - this.names1 = m1.names(); - this.len1 = this.names1.length; - this.types1 = m1.types(); - this.rest1 = m1.rest(); - this.names2 = m2.names(); - this.len2 = this.names2.length; - this.types2 = m2.types(); - this.rest2 = m2.rest(); - } - - @Override - public boolean hasNext() { - if (this.doneIteration) { - return false; - } - if (this.shouldCalculate) { - FieldPair cache = internalNext(); - if (cache == null) { - this.doneIteration = true; - } - this.cache = cache; - this.shouldCalculate = false; - } - return !this.doneIteration; - } - - @Override - public FieldPair next() { - if (this.doneIteration) { - throw new NoSuchElementException("Exhausted iterator"); - } - - if (this.shouldCalculate) { - FieldPair cache = internalNext(); - if (cache == null) { - // this.doneIteration = true; - throw new IllegalStateException(); - } - this.cache = cache; - } - this.shouldCalculate = true; - return this.cache; - } - - /* - * This method corresponds to `next` method of MappingPairing. - */ - private FieldPair internalNext() { - FieldPair p; - if (this.i1 >= this.len1) { - if (this.i2 >= this.len2) { - return null; - } - p = FieldPair.create(curName2(), this.rest1, curType2(), null, this.i2); - this.i2 += 1; - } else if (this.i2 >= this.len2) { - p = FieldPair.create(curName1(), curType1(), this.rest2, this.i1, null); - this.i1 += 1; - } else { - String name1 = curName1(); - String name2 = curName2(); - if (Common.codePointCompare(name1, name2)) { - p = FieldPair.create(name1, curType1(), this.rest2, this.i1, null); - this.i1 += 1; - } else if (Common.codePointCompare(name2, name1)) { - p = FieldPair.create(name2, this.rest1, curType2(), null, this.i2); - this.i2 += 1; - } else { - p = FieldPair.create(name1, curType1(), curType2(), this.i1, this.i2); - this.i1 += 1; - this.i2 += 1; - } - } - return p; - } - - private CellSemType curType1() { - return this.types1[this.i1]; - } - - private String curName1() { - return this.names1[this.i1]; - } - - private CellSemType curType2() { - return this.types2[this.i2]; - } - - private String curName2() { - return this.names2[this.i2]; - } - - public void reset() { - this.i1 = 0; - this.i2 = 0; - } - - public Optional index1(String name) { - int i1Prev = this.i1 - 1; - return i1Prev >= 0 && Objects.equals(this.names1[i1Prev], name) ? Optional.of(i1Prev) : Optional.empty(); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/ObjectOps.java b/semtypes/src/main/java/io/ballerina/types/typeops/ObjectOps.java deleted file mode 100644 index 47518f536d1b..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/ObjectOps.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.types.typeops; - -import io.ballerina.types.BasicTypeOps; -import io.ballerina.types.Bdd; -import io.ballerina.types.Context; -import io.ballerina.types.SubtypeData; - -import static io.ballerina.types.Common.bddEveryPositive; -import static io.ballerina.types.Common.bddSubtypeDiff; -import static io.ballerina.types.Common.memoSubtypeIsEmpty; -import static io.ballerina.types.PredefinedType.MAPPING_SUBTYPE_OBJECT; - -public final class ObjectOps extends CommonOps implements BasicTypeOps { - - @Override - public SubtypeData complement(SubtypeData t) { - return objectSubTypeComplement(t); - } - - @Override - public boolean isEmpty(Context cx, SubtypeData t) { - return objectSubTypeIsEmpty(cx, t); - } - - private static boolean objectSubTypeIsEmpty(Context cx, SubtypeData t) { - return memoSubtypeIsEmpty(cx, cx.mappingMemo, ObjectOps::objectBddIsEmpty, (Bdd) t); - } - - private static boolean objectBddIsEmpty(Context cx, Bdd b) { - return bddEveryPositive(cx, b, null, null, MappingOps::mappingFormulaIsEmpty); - } - - private SubtypeData objectSubTypeComplement(SubtypeData t) { - return bddSubtypeDiff(MAPPING_SUBTYPE_OBJECT, t); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/StreamOps.java b/semtypes/src/main/java/io/ballerina/types/typeops/StreamOps.java deleted file mode 100644 index 17948aaecc6c..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/StreamOps.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.BasicTypeOps; -import io.ballerina.types.Bdd; -import io.ballerina.types.Context; -import io.ballerina.types.SubtypeData; - -import static io.ballerina.types.Common.bddPosMaybeEmpty; -import static io.ballerina.types.Common.bddSubtypeDiff; -import static io.ballerina.types.PredefinedType.LIST_SUBTYPE_TWO_ELEMENT; -import static io.ballerina.types.typeops.BddCommonOps.bddIntersect; -import static io.ballerina.types.typeops.ListOps.listSubtypeIsEmpty; - -/** - * Basic type ops for stream type. - * - * @since 2201.10.0 - */ -public class StreamOps extends CommonOps implements BasicTypeOps { - - private static SubtypeData streamSubtypeComplement(SubtypeData t) { - return bddSubtypeDiff(LIST_SUBTYPE_TWO_ELEMENT, t); - } - - private static boolean streamSubtypeIsEmpty(Context cx, SubtypeData t) { - Bdd b = (Bdd) t; - // The goal of this is to ensure that listSubtypeIsEmpty call beneath does - // not get an empty posList, because it will interpret that - // as `[any|error...]` rather than `[any|error, any|error]`. - b = bddPosMaybeEmpty(b) ? bddIntersect(b, LIST_SUBTYPE_TWO_ELEMENT) : b; - return listSubtypeIsEmpty(cx, b); - } - - @Override - public SubtypeData complement(SubtypeData t) { - return streamSubtypeComplement(t); - } - - @Override - public boolean isEmpty(Context cx, SubtypeData t) { - return streamSubtypeIsEmpty(cx, t); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/StringOps.java b/semtypes/src/main/java/io/ballerina/types/typeops/StringOps.java deleted file mode 100644 index fd345ce17d6c..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/StringOps.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.BasicTypeOps; -import io.ballerina.types.Common; -import io.ballerina.types.Context; -import io.ballerina.types.EnumerableCharString; -import io.ballerina.types.EnumerableString; -import io.ballerina.types.EnumerableSubtype; -import io.ballerina.types.SubtypeData; -import io.ballerina.types.subtypedata.AllOrNothingSubtype; -import io.ballerina.types.subtypedata.CharStringSubtype; -import io.ballerina.types.subtypedata.NonCharStringSubtype; -import io.ballerina.types.subtypedata.StringSubtype; - -import java.util.ArrayList; -import java.util.List; - -import static io.ballerina.types.EnumerableSubtype.EQ; -import static io.ballerina.types.EnumerableSubtype.GT; -import static io.ballerina.types.EnumerableSubtype.LT; - -/** - * Basic subtype ops for string type. - * - * @since 2201.8.0 - */ -public class StringOps implements BasicTypeOps { - @Override - public SubtypeData union(SubtypeData d1, SubtypeData d2) { - //List values = new ArrayList<>(); - //boolean allowed = EnumerableSubtype.enumerableSubtypeUnion((StringSubtype) d1, (StringSubtype) d2, values); - //EnumerableString[] valueArray = new EnumerableString[values.size()]; - //return StringSubtype.createStringSubtype(allowed, values.toArray(valueArray)); - StringSubtype sd1 = (StringSubtype) d1; - StringSubtype sd2 = (StringSubtype) d2; - ArrayList chars = new ArrayList<>(); - ArrayList nonChars = new ArrayList<>(); - boolean charsAllowed = EnumerableSubtype.enumerableSubtypeUnion(sd1.getChar(), sd2.getChar(), chars); - boolean nonCharsAllowed = EnumerableSubtype.enumerableSubtypeUnion(sd1.getNonChar(), - sd2.getNonChar(), nonChars); - - return StringSubtype.createStringSubtype(CharStringSubtype.from(charsAllowed, - chars.toArray(new EnumerableCharString[]{})), - NonCharStringSubtype.from(nonCharsAllowed, nonChars.toArray(new EnumerableString[]{}))); - } - - @Override - public SubtypeData intersect(SubtypeData d1, SubtypeData d2) { - if (d1 instanceof AllOrNothingSubtype) { - return ((AllOrNothingSubtype) d1).isAllSubtype() ? d2 : AllOrNothingSubtype.createNothing(); - } - if (d2 instanceof AllOrNothingSubtype) { - return ((AllOrNothingSubtype) d2).isAllSubtype() ? d1 : AllOrNothingSubtype.createNothing(); - } - - StringSubtype sd1 = (StringSubtype) d1; - StringSubtype sd2 = (StringSubtype) d2; - ArrayList chars = new ArrayList<>(); - ArrayList nonChars = new ArrayList<>(); - boolean charsAllowed = EnumerableSubtype.enumerableSubtypeIntersect(sd1.getChar(), sd2.getChar(), chars); - boolean nonCharsAllowed = EnumerableSubtype.enumerableSubtypeIntersect(sd1.getNonChar(), - sd2.getNonChar(), nonChars); - - return StringSubtype.createStringSubtype(CharStringSubtype.from(charsAllowed, - chars.toArray(new EnumerableCharString[]{})), - NonCharStringSubtype.from(nonCharsAllowed, nonChars.toArray(new EnumerableString[]{}))); - } - - @Override - public SubtypeData diff(SubtypeData d1, SubtypeData d2) { - return intersect(d1, complement(d2)); - } - - @Override - public SubtypeData complement(SubtypeData d) { - StringSubtype st = (StringSubtype) d; - if (st.getChar().values.length == 0 && st.getNonChar().values.length == 0) { - if (st.getChar().allowed && st.getNonChar().allowed) { - return AllOrNothingSubtype.createAll(); - } else if (!st.getChar().allowed && !st.getNonChar().allowed) { - return AllOrNothingSubtype.createNothing(); - } - } - - return StringSubtype.createStringSubtype(CharStringSubtype.from(!st.getChar().allowed, st.getChar().values), - NonCharStringSubtype.from(!st.getNonChar().allowed, st.getNonChar().values)); - } - - @Override - public boolean isEmpty(Context cx, SubtypeData t) { - return Common.notIsEmpty(cx, t); - } - - // Returns a description of the relationship between a StringSubtype and a list of strings - // `values` must be ordered. - static StringSubtype.StringSubtypeListCoverage stringSubtypeListCoverage(StringSubtype subtype, String[] values) { - List indices = new ArrayList<>(); - CharStringSubtype ch = subtype.getChar(); - NonCharStringSubtype nonChar = subtype.getNonChar(); - int stringConsts = 0; - if (ch.allowed) { - stringListIntersect(values, toStringArray(ch.values), indices); - stringConsts = ch.values.length; - } else if (ch.values.length == 0) { - for (int i = 0; i < values.length; i++) { - if (values[i].length() == 1) { - indices.add(i); - } - } - } - if (nonChar.allowed) { - stringListIntersect(values, toStringArray(nonChar.values), indices); - stringConsts += nonChar.values.length; - } else if (nonChar.values.length == 0) { - for (int i = 0; i < values.length; i++) { - if (values[i].length() != 1) { - indices.add(i); - } - } - } - int[] inds = indices.stream().mapToInt(i -> i).toArray(); - return StringSubtype.StringSubtypeListCoverage.from(stringConsts == indices.size(), inds); - } - - private static String[] toStringArray(EnumerableCharString[] ar) { - String[] strings = new String[ar.length]; - for (int i = 0; i < ar.length; i++) { - strings[i] = ar[i].value; - } - return strings; - } - - private static String[] toStringArray(EnumerableString[] ar) { - String[] strings = new String[ar.length]; - for (int i = 0; i < ar.length; i++) { - strings[i] = ar[i].value; - } - return strings; - } - - static void stringListIntersect(String[] values, String[] target, List indices) { - int i1 = 0; - int i2 = 0; - int len1 = values.length; - int len2 = target.length; - while (true) { - if (i1 >= len1 || i2 >= len2) { - break; - } else { - int comp = EnumerableSubtype.compareEnumerable(EnumerableString.from(values[i1]), - EnumerableString.from(target[i2])); - switch (comp) { - case EQ: - indices.add(i1); - i1 += 1; - i2 += 1; - break; - case LT: - i1 += 1; - break; - case GT: - i2 += 1; - break; - default: - throw new AssertionError("Invalid comparison value!"); - } - } - } - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/SubtypePair.java b/semtypes/src/main/java/io/ballerina/types/typeops/SubtypePair.java deleted file mode 100644 index fa21b980e681..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/SubtypePair.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.BasicTypeCode; -import io.ballerina.types.ProperSubtypeData; - -/** - * Represent a 3-tuple containing paired-up subtype data. - * - * @since 2201.8.0 - */ -public class SubtypePair { - public final BasicTypeCode basicTypeCode; - public final ProperSubtypeData subtypeData1; - public final ProperSubtypeData subtypeData2; - - private SubtypePair(BasicTypeCode basicTypeCode, ProperSubtypeData subtypeData1, - ProperSubtypeData subtypeData2) { - this.basicTypeCode = basicTypeCode; - this.subtypeData1 = subtypeData1; - this.subtypeData2 = subtypeData2; - } - - public static SubtypePair create(BasicTypeCode basicTypeCode, - ProperSubtypeData subtypeData1, ProperSubtypeData subtypeData2) { - return new SubtypePair(basicTypeCode, subtypeData1, subtypeData2); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/SubtypePairIterator.java b/semtypes/src/main/java/io/ballerina/types/typeops/SubtypePairIterator.java deleted file mode 100644 index 913f1ddc6ee0..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/SubtypePairIterator.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.BasicSubtype; -import io.ballerina.types.BasicTypeBitSet; -import io.ballerina.types.BasicTypeCode; -import io.ballerina.types.ComplexSemType; -import io.ballerina.types.ProperSubtypeData; -import io.ballerina.types.SemType; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; - -/** - * Iteration implementation of `SubtypePairIterator`. - * - * @since 2201.8.0 - */ -public class SubtypePairIterator implements Iterator { - private int i1; - private int i2; - private final List t1; - private final List t2; - private final BasicTypeBitSet bits; - - private boolean doneIteration = false; - private boolean shouldCalculate = true; - private SubtypePair cache = null; - - public SubtypePairIterator(SemType t1, SemType t2, BasicTypeBitSet bits) { - this.i1 = 0; - this.i2 = 0; - this.t1 = unpackToBasicSubtypes(t1); - this.t2 = unpackToBasicSubtypes(t2); - this.bits = bits; - } - - private List unpackToBasicSubtypes(SemType type) { - if (type instanceof BasicTypeBitSet) { - return new ArrayList<>(); - } - return UnpackComplexSemType.unpack((ComplexSemType) type); - } - - private boolean include(BasicTypeCode code) { - return (this.bits.bitset & (1 << code.code)) != 0; - } - - private BasicSubtype get1() { - return this.t1.get(this.i1); - } - - private BasicSubtype get2() { - return this.t2.get(this.i2); - } - - @Override - public boolean hasNext() { - if (this.doneIteration) { - return false; - } - if (this.shouldCalculate) { - SubtypePair cache = internalNext(); - if (cache == null) { - this.doneIteration = true; - } - this.cache = cache; - this.shouldCalculate = false; - } - return !this.doneIteration; - } - - @Override - public SubtypePair next() { - if (this.doneIteration) { - throw new NoSuchElementException("Exhausted iterator"); - } - - if (this.shouldCalculate) { - SubtypePair cache = internalNext(); - if (cache == null) { - // this.doneIteration = true; - throw new IllegalStateException(); - } - this.cache = cache; - } - this.shouldCalculate = true; - return this.cache; - } - - /* - * This method corresponds to `next` method of SubtypePairIteratorImpl. - */ - private SubtypePair internalNext() { - while (true) { - if (this.i1 >= this.t1.size()) { - if (this.i2 >= this.t2.size()) { - break; - } - BasicSubtype t = get2(); - BasicTypeCode code = t.basicTypeCode; - ProperSubtypeData data2 = t.subtypeData; - this.i2 += 1; - if (include(code)) { - return SubtypePair.create(code, null, data2); - } - } else if (this.i2 >= this.t2.size()) { - BasicSubtype t = this.get1(); - this.i1 += 1; - BasicTypeCode code = t.basicTypeCode; - ProperSubtypeData data1 = t.subtypeData; - if (include(code)) { - return SubtypePair.create(code, data1, null); - } - } else { - BasicSubtype t1 = get1(); - BasicTypeCode code1 = t1.basicTypeCode; - ProperSubtypeData data1 = t1.subtypeData; - - BasicSubtype t2 = get2(); - BasicTypeCode code2 = t2.basicTypeCode; - ProperSubtypeData data2 = t2.subtypeData; - - if (code1.code == code2.code) { - this.i1 += 1; - this.i2 += 1; - if (include(code1)) { - return SubtypePair.create(code1, data1, data2); - } - } else if (code1.code < code2.code) { - this.i1 += 1; - if (include(code1)) { - return SubtypePair.create(code1, data1, null); - } - } else { - this.i2 += 1; - if (include(code2)) { - return SubtypePair.create(code2, null, data2); - } - } - } - } - return null; - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/SubtypePairs.java b/semtypes/src/main/java/io/ballerina/types/typeops/SubtypePairs.java deleted file mode 100644 index d703591efafa..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/SubtypePairs.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.BasicTypeBitSet; -import io.ballerina.types.SemType; - -import java.util.Iterator; - -/** - * Ballerina iterator is similar to an iterable in Java. - * This class implements the iterable for `SubtypePairIteratorImpl` - * - * @since 2201.8.0 - */ -public class SubtypePairs implements Iterable { - - private final SemType t1; - private final SemType t2; - private final BasicTypeBitSet bits; - - public SubtypePairs(SemType t1, SemType t2, BasicTypeBitSet bits) { - this.t1 = t1; - this.t2 = t2; - this.bits = bits; - } - - @Override - public Iterator iterator() { - return new SubtypePairIterator(t1, t2, bits); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/TableOps.java b/semtypes/src/main/java/io/ballerina/types/typeops/TableOps.java deleted file mode 100644 index 8d3f3430ad78..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/TableOps.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.BasicTypeOps; -import io.ballerina.types.Bdd; -import io.ballerina.types.Context; -import io.ballerina.types.SubtypeData; - -import static io.ballerina.types.Common.bddPosMaybeEmpty; -import static io.ballerina.types.Common.bddSubtypeDiff; -import static io.ballerina.types.PredefinedType.LIST_SUBTYPE_THREE_ELEMENT; -import static io.ballerina.types.typeops.BddCommonOps.bddIntersect; -import static io.ballerina.types.typeops.ListOps.listSubtypeIsEmpty; - -/** - * Basic type ops for table type. - * - * @since 2201.8.0 - */ -public class TableOps extends CommonOps implements BasicTypeOps { - - private static SubtypeData tableSubtypeComplement(SubtypeData t) { - return bddSubtypeDiff(LIST_SUBTYPE_THREE_ELEMENT, t); - } - - private static boolean tableSubtypeIsEmpty(Context cx, SubtypeData t) { - Bdd b = (Bdd) t; - // The goal of this is to ensure that listSubtypeIsEmpty call beneath does - // not get an empty posList, because it will interpret that - // as `(any|error)[]` rather than `[(map)[], any|error, any|error]`. - b = bddPosMaybeEmpty(b) ? bddIntersect(b, LIST_SUBTYPE_THREE_ELEMENT) : b; - return listSubtypeIsEmpty(cx, b); - } - - @Override - public SubtypeData complement(SubtypeData d) { - return tableSubtypeComplement(d); - } - - @Override - public boolean isEmpty(Context cx, SubtypeData d) { - return tableSubtypeIsEmpty(cx, d); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/TwoTuple.java b/semtypes/src/main/java/io/ballerina/types/typeops/TwoTuple.java deleted file mode 100644 index 4490e3f23ed6..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/TwoTuple.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -/** - * Used to return two values from a method. - * - * @param Type of first item - * @param Type of second item - * @since 2201.8.0 - */ -public final class TwoTuple { - - final E1 item1; - final E2 item2; - - private TwoTuple(E1 item1, E2 item2) { - this.item1 = item1; - this.item2 = item2; - } - - public static TwoTuple from(E1 item1, E2 item2) { - return new TwoTuple<>(item1, item2); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/TypedescOps.java b/semtypes/src/main/java/io/ballerina/types/typeops/TypedescOps.java deleted file mode 100644 index 26f283b35a8f..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/TypedescOps.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.BasicTypeOps; -import io.ballerina.types.Bdd; -import io.ballerina.types.Context; -import io.ballerina.types.SubtypeData; - -import static io.ballerina.types.Common.bddPosMaybeEmpty; -import static io.ballerina.types.Common.bddSubtypeDiff; -import static io.ballerina.types.PredefinedType.BDD_SUBTYPE_RO; -import static io.ballerina.types.typeops.BddCommonOps.bddIntersect; -import static io.ballerina.types.typeops.MappingOps.mappingSubtypeIsEmpty; - -/** - * Basic type ops for typedesc type. - * - * @since 2201.10.0 - */ -public class TypedescOps extends CommonOps implements BasicTypeOps { - - private static SubtypeData typedescSubtypeComplement(SubtypeData t) { - return bddSubtypeDiff(BDD_SUBTYPE_RO, t); - } - - private static boolean typedescSubtypeIsEmpty(Context cx, SubtypeData t) { - Bdd b = (Bdd) t; - // The goal of this is to ensure that mappingSubtypeIsEmpty call beneath does - // not get an empty posList, because it will interpret that - // as `map` rather than `readonly & map)`. - b = bddPosMaybeEmpty(b) ? bddIntersect(b, BDD_SUBTYPE_RO) : b; - return mappingSubtypeIsEmpty(cx, b); - } - - @Override - public SubtypeData complement(SubtypeData d) { - return typedescSubtypeComplement(d); - } - - @Override - public boolean isEmpty(Context cx, SubtypeData d) { - return typedescSubtypeIsEmpty(cx, d); - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/UnpackComplexSemType.java b/semtypes/src/main/java/io/ballerina/types/typeops/UnpackComplexSemType.java deleted file mode 100644 index 7cf850a46540..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/UnpackComplexSemType.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.BasicSubtype; -import io.ballerina.types.BasicTypeCode; -import io.ballerina.types.ComplexSemType; -import io.ballerina.types.ProperSubtypeData; - -import java.util.ArrayList; -import java.util.List; - -/** - * Represent `unpackComplexSemType` function. - * - * @since 2201.8.0 - */ -public class UnpackComplexSemType { - private UnpackComplexSemType() { - } - - public static List unpack(ComplexSemType t) { - int some = t.some(); - List subtypeList = new ArrayList<>(); - for (ProperSubtypeData data : t.subtypeDataList()) { - int code = Integer.numberOfTrailingZeros(some); - subtypeList.add(BasicSubtype.from(BasicTypeCode.from(code), data)); - some ^= (1 << code); - } - return subtypeList; - } -} diff --git a/semtypes/src/main/java/io/ballerina/types/typeops/XmlOps.java b/semtypes/src/main/java/io/ballerina/types/typeops/XmlOps.java deleted file mode 100644 index 4bd166c5a42e..000000000000 --- a/semtypes/src/main/java/io/ballerina/types/typeops/XmlOps.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types.typeops; - -import io.ballerina.types.BasicTypeOps; -import io.ballerina.types.Bdd; -import io.ballerina.types.Common; -import io.ballerina.types.Conjunction; -import io.ballerina.types.Context; -import io.ballerina.types.RecAtom; -import io.ballerina.types.SubtypeData; -import io.ballerina.types.subtypedata.BddAllOrNothing; -import io.ballerina.types.subtypedata.XmlSubtype; - -import static io.ballerina.types.subtypedata.XmlSubtype.XML_PRIMITIVE_ALL_MASK; -import static io.ballerina.types.subtypedata.XmlSubtype.XML_PRIMITIVE_RO_MASK; -import static io.ballerina.types.subtypedata.XmlSubtype.XML_PRIMITIVE_RO_SINGLETON; - -/** - * Basic subtype ops for xml type. - * - * @since 2201.8.0 - */ -public class XmlOps implements BasicTypeOps { - - public static final XmlSubtype XML_SUBTYPE_RO = XmlSubtype.from(XML_PRIMITIVE_RO_MASK, - BddCommonOps.bddAtom(RecAtom.createXMLRecAtom(XML_PRIMITIVE_RO_SINGLETON))); - public static final XmlSubtype XML_SUBTYPE_TOP = XmlSubtype.from(XML_PRIMITIVE_ALL_MASK, BddAllOrNothing.bddAll()); - - @Override - public SubtypeData union(SubtypeData d1, SubtypeData d2) { - XmlSubtype v1 = (XmlSubtype) d1; - XmlSubtype v2 = (XmlSubtype) d2; - int primitives = v1.primitives | v2.primitives; - return XmlSubtype.createXmlSubtype(primitives, BddCommonOps.bddUnion(v1.sequence, v2.sequence)); - } - - @Override - public SubtypeData intersect(SubtypeData d1, SubtypeData d2) { - XmlSubtype v1 = (XmlSubtype) d1; - XmlSubtype v2 = (XmlSubtype) d2; - int primitives = v1.primitives & v2.primitives; - return XmlSubtype.createXmlSubtypeOrEmpty(primitives, BddCommonOps.bddIntersect(v1.sequence, v2.sequence)); - } - - @Override - public SubtypeData diff(SubtypeData d1, SubtypeData d2) { - XmlSubtype v1 = (XmlSubtype) d1; - XmlSubtype v2 = (XmlSubtype) d2; - int primitives = v1.primitives & ~v2.primitives; - return XmlSubtype.createXmlSubtypeOrEmpty(primitives, BddCommonOps.bddDiff(v1.sequence, v2.sequence)); - } - - @Override - public SubtypeData complement(SubtypeData d) { - return diff(XML_SUBTYPE_TOP, d); - } - - @Override - public boolean isEmpty(Context cx, SubtypeData t) { - XmlSubtype sd = (XmlSubtype) t; - if (sd.primitives != 0) { - return false; - } - return xmlBddEmpty(cx, sd.sequence); - } - - boolean xmlBddEmpty(Context cx, Bdd bdd) { - return Common.bddEvery(cx, bdd, null, null, XmlOps::xmlFormulaIsEmpty); - } - - private static boolean xmlFormulaIsEmpty(Context cx, Conjunction pos, Conjunction neg) { - int allPosBits = collectAllPrimitives(pos) & XmlSubtype.XML_PRIMITIVE_ALL_MASK; - return xmlHasTotalNegative(allPosBits, neg); - } - - public static int collectAllPrimitives(Conjunction con) { - int bits = 0; - Conjunction current = con; - while (current != null) { - bits &= getIndex(current); - current = current.next; - } - return bits; - } - - public static boolean xmlHasTotalNegative(int allBits, Conjunction con) { - if (allBits == 0) { - return true; - } - - Conjunction n = con; - while (n != null) { - if ((allBits & ~getIndex(con)) == 0) { - return true; - } - n = n.next; - } - return false; - } - - private static int getIndex(Conjunction con) { - return ((RecAtom) con.atom).index; - } -} diff --git a/semtypes/src/main/java/module-info.java b/semtypes/src/main/java/module-info.java index 40129cf5658d..5ae00697cfae 100644 --- a/semtypes/src/main/java/module-info.java +++ b/semtypes/src/main/java/module-info.java @@ -1,5 +1,3 @@ module io.ballerina.semtype { - exports io.ballerina.types; - exports io.ballerina.types.definition; - exports io.ballerina.types.subtypedata; + } diff --git a/semtypes/src/test/java/io/ballerina/semtype/SemTypeTest.java b/semtypes/src/test/java/io/ballerina/semtype/SemTypeTest.java new file mode 100644 index 000000000000..a4a16c8e6031 --- /dev/null +++ b/semtypes/src/test/java/io/ballerina/semtype/SemTypeTest.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.semtype; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * Tests if placeholder is created. + * + */ +public class SemTypeTest { + + @SuppressWarnings("ConstantValue") + @Test + public void testSemType() { + SemTypeMock s1 = new UniformTypeBitSetMock(0x00); + SemTypeMock s2 = new ComplexSemTypeMock(); + Assert.assertTrue(s1 instanceof UniformTypeBitSetMock); + Assert.assertTrue(s2 instanceof ComplexSemTypeMock); + } +} diff --git a/semtypes/src/test/java/io/ballerina/types/CellTypeTest.java b/semtypes/src/test/java/io/ballerina/types/CellTypeTest.java deleted file mode 100644 index 8da46f516ca3..000000000000 --- a/semtypes/src/test/java/io/ballerina/types/CellTypeTest.java +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import io.ballerina.types.subtypedata.CellSubtype; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import static io.ballerina.types.CellAtomicType.CellMutability.CELL_MUT_LIMITED; -import static io.ballerina.types.CellAtomicType.CellMutability.CELL_MUT_NONE; -import static io.ballerina.types.CellAtomicType.CellMutability.CELL_MUT_UNLIMITED; - -/** - * Tests subtyping rules of cell basic type. - * - * @since 2201.10.0 - */ -public class CellTypeTest { - - Context ctx; - - public enum Relation { - EQUAL("="), - SUBTYPE("<"), - NO_RELATION("<>"); - - final String value; - - Relation(String value) { - this.value = value; - } - } - - @BeforeClass - public void beforeClass() { - ctx = Context.from(new Env()); - } - - private CellSemType cell(SemType ty, CellAtomicType.CellMutability mut) { - return CellSubtype.cellContaining(ctx.env, ty, mut); - } - - private void assertSemTypeRelation(SemType t1, SemType t2, Relation relation) { - Relation actual = getSemTypeRelation(t1, t2); - Assert.assertEquals(actual, relation); - } - - private Relation getSemTypeRelation(SemType t1, SemType t2) { - boolean s1 = Core.isSubtype(ctx, t1, t2); - boolean s2 = Core.isSubtype(ctx, t2, t1); - if (s1 && s2) { - return Relation.EQUAL; - } else if (s1) { - return Relation.SUBTYPE; - } else if (s2) { - throw new IllegalStateException("'>' relation found which can be converted to a '<' relation"); - } else { - return Relation.NO_RELATION; - } - } - - @Test(description = "Test T and cell(T) having no relation", dataProvider = "typeCellDisparityDataProvider") - public void testTypeCellDisparity(SemType t1, SemType t2, Relation relation) { - assertSemTypeRelation(t1, t2, relation); - } - - @DataProvider(name = "typeCellDisparityDataProvider") - public Object[][] createTypeCellDisparityTestData() { - return new Object[][]{ - {PredefinedType.INT, cell(PredefinedType.INT, CELL_MUT_NONE), Relation.NO_RELATION}, - {PredefinedType.INT, cell(PredefinedType.INT, CELL_MUT_LIMITED), Relation.NO_RELATION}, - {PredefinedType.INT, cell(PredefinedType.INT, CELL_MUT_UNLIMITED), Relation.NO_RELATION}, - }; - } - - @Test(description = "Test basic cell subtyping", dataProvider = "basicCellSubtypingDataProvider") - public void testBasicCellSubtyping(SemType t1, SemType t2, Relation[] relations) { - assert relations.length == 3; - Relation[] actual = new Relation[3]; - - CellAtomicType.CellMutability[] values = CellAtomicType.CellMutability.values(); - // Obtaining relation for each mutability kind - for (int i = 0; i < values.length; i++) { - CellAtomicType.CellMutability mut = values[i]; - CellSemType c1 = cell(t1, mut); - CellSemType c2 = cell(t2, mut); - actual[i] = getSemTypeRelation(c1, c2); - } - - Assert.assertEquals(actual, relations); - } - - @DataProvider(name = "basicCellSubtypingDataProvider") - public Object[][] createBasicCellSubtypingTestData() { - // This contains some of nBallerina 'cell-1.typetest' test data - return new Object[][]{ - { - PredefinedType.INT, PredefinedType.INT, - new Relation[]{ - Relation.EQUAL, Relation.EQUAL, Relation.EQUAL - } - }, - { - PredefinedType.BOOLEAN, PredefinedType.BOOLEAN, - new Relation[]{ - Relation.EQUAL, Relation.EQUAL, Relation.EQUAL - } - }, - { - PredefinedType.BYTE, PredefinedType.INT, - new Relation[]{ - Relation.SUBTYPE, Relation.SUBTYPE, Relation.SUBTYPE - } - }, - { - PredefinedType.BOOLEAN, PredefinedType.INT, - new Relation[]{ - Relation.NO_RELATION, Relation.NO_RELATION, Relation.NO_RELATION - } - }, - { - PredefinedType.BOOLEAN, Core.union(PredefinedType.INT, PredefinedType.BOOLEAN), - new Relation[]{ - Relation.SUBTYPE, Relation.SUBTYPE, Relation.SUBTYPE - } - } - }; - } - - @Test(dataProvider = "cellSubtypeDataProvider1") - public void testCellSubtyping1(SemType t1, SemType t2, Relation relation) { - assertSemTypeRelation(t1, t2, relation); - } - - @DataProvider(name = "cellSubtypeDataProvider1") - public Object[][] createCellSubtypeData1() { - // This contains some of nBallerina 'cell-1.typetest' test data - return new Object[][]{ - // Set 1 - { - SemTypes.union( - cell(PredefinedType.INT, CELL_MUT_NONE), - cell(PredefinedType.BOOLEAN, CELL_MUT_NONE) - ), - cell(SemTypes.union(PredefinedType.INT, PredefinedType.BOOLEAN), CELL_MUT_NONE), - Relation.EQUAL - }, - { - SemTypes.union( - cell(PredefinedType.INT, CELL_MUT_LIMITED), - cell(PredefinedType.BOOLEAN, CELL_MUT_LIMITED) - ), - cell(SemTypes.union(PredefinedType.INT, PredefinedType.BOOLEAN), CELL_MUT_LIMITED), - Relation.SUBTYPE - }, - { - SemTypes.union( - cell(PredefinedType.INT, CELL_MUT_UNLIMITED), - cell(PredefinedType.BOOLEAN, CELL_MUT_UNLIMITED) - ), - cell(SemTypes.union(PredefinedType.INT, PredefinedType.BOOLEAN), CELL_MUT_UNLIMITED), - Relation.EQUAL - }, - // Set 2 - { - SemTypes.union( - cell(PredefinedType.INT, CELL_MUT_NONE), - cell(PredefinedType.BOOLEAN, CELL_MUT_NONE), - cell(PredefinedType.STRING, CELL_MUT_NONE) - ), - cell(SemTypes.union(PredefinedType.INT, PredefinedType.BOOLEAN, PredefinedType.STRING), - CELL_MUT_NONE), - Relation.EQUAL - }, - { - SemTypes.union( - cell(PredefinedType.INT, CELL_MUT_LIMITED), - cell(PredefinedType.BOOLEAN, CELL_MUT_LIMITED), - cell(PredefinedType.STRING, CELL_MUT_LIMITED) - ), - cell(SemTypes.union(PredefinedType.INT, PredefinedType.BOOLEAN, PredefinedType.STRING), - CELL_MUT_LIMITED), - Relation.SUBTYPE - }, - { - SemTypes.union( - cell(PredefinedType.INT, CELL_MUT_UNLIMITED), - cell(PredefinedType.BOOLEAN, CELL_MUT_UNLIMITED), - cell(PredefinedType.STRING, CELL_MUT_UNLIMITED) - ), - cell(SemTypes.union(PredefinedType.INT, PredefinedType.BOOLEAN, PredefinedType.STRING), - CELL_MUT_UNLIMITED), - Relation.EQUAL - }, - // Set 3 - { - SemTypes.union( - cell(TypeTestUtils.roTuple(ctx.env, PredefinedType.INT), CELL_MUT_NONE), - cell(TypeTestUtils.roTuple(ctx.env, PredefinedType.BOOLEAN), CELL_MUT_NONE) - ), - cell(TypeTestUtils.roTuple(ctx.env, SemTypes.union(PredefinedType.INT, PredefinedType.BOOLEAN)), - CELL_MUT_NONE), - Relation.EQUAL - }, - { - SemTypes.union( - cell(TypeTestUtils.tuple(ctx.env, PredefinedType.INT), CELL_MUT_LIMITED), - cell(TypeTestUtils.tuple(ctx.env, PredefinedType.BOOLEAN), CELL_MUT_LIMITED) - ), - cell(TypeTestUtils.tuple(ctx.env, SemTypes.union(PredefinedType.INT, PredefinedType.BOOLEAN)), - CELL_MUT_LIMITED), - Relation.SUBTYPE - }, - { - SemTypes.union( - cell(TypeTestUtils.tuple(ctx.env, PredefinedType.INT), CELL_MUT_UNLIMITED), - cell(TypeTestUtils.tuple(ctx.env, PredefinedType.BOOLEAN), CELL_MUT_UNLIMITED) - ), - cell(TypeTestUtils.tuple(ctx.env, SemTypes.union(PredefinedType.INT, PredefinedType.BOOLEAN)), - CELL_MUT_UNLIMITED), - Relation.SUBTYPE - }, - }; - } - - @Test(dataProvider = "cellSubtypeDataProvider2") - public void testCellSubtyping2(SemType t1, SemType t2, Relation relation) { - assertSemTypeRelation(t1, t2, relation); - } - - @DataProvider(name = "cellSubtypeDataProvider2") - public Object[][] createCellSubtypeData2() { - // This contains nBallerina 'cell-2.typetest' test data - return new Object[][]{ - // test 1 - { - SemTypes.union( - cell(PredefinedType.INT, CELL_MUT_NONE), - cell(PredefinedType.BOOLEAN, CELL_MUT_UNLIMITED), - cell(PredefinedType.STRING, CELL_MUT_LIMITED) - ), - cell( - SemTypes.union(PredefinedType.INT, PredefinedType.BOOLEAN, PredefinedType.STRING), - CELL_MUT_UNLIMITED - ), - Relation.SUBTYPE - }, - // test 2 - { - cell( - SemTypes.union(PredefinedType.INT, PredefinedType.BOOLEAN, PredefinedType.STRING), - CELL_MUT_NONE - ), - SemTypes.union( - cell(PredefinedType.INT, CELL_MUT_NONE), - cell(PredefinedType.BOOLEAN, CELL_MUT_UNLIMITED), - cell(PredefinedType.STRING, CELL_MUT_LIMITED) - ), - Relation.SUBTYPE - }, - // test 3 - { - SemTypes.union( - cell(PredefinedType.INT, CELL_MUT_NONE), - cell(PredefinedType.BOOLEAN, CELL_MUT_UNLIMITED), - cell(PredefinedType.STRING, CELL_MUT_LIMITED) - ), - cell( - SemTypes.union(PredefinedType.INT, PredefinedType.BOOLEAN, PredefinedType.STRING), - CELL_MUT_LIMITED - ), - Relation.NO_RELATION - }, - // test 4 - { - SemTypes.union( - cell(PredefinedType.INT, CELL_MUT_NONE), - cell(PredefinedType.INT, CELL_MUT_LIMITED), - cell(PredefinedType.INT, CELL_MUT_UNLIMITED) - ), - cell(PredefinedType.INT, CELL_MUT_UNLIMITED), - Relation.EQUAL - }, - // test 5 - { - SemTypes.intersect( - cell(PredefinedType.INT, CELL_MUT_NONE), - cell(PredefinedType.INT, CELL_MUT_LIMITED), - cell(PredefinedType.INT, CELL_MUT_UNLIMITED) - ), - cell(PredefinedType.INT, CELL_MUT_UNLIMITED), - Relation.SUBTYPE - }, - // test 6 - { - SemTypes.intersect( - cell(PredefinedType.INT, CELL_MUT_NONE), - cell(PredefinedType.INT, CELL_MUT_LIMITED), - cell(PredefinedType.INT, CELL_MUT_UNLIMITED) - ), - cell(PredefinedType.INT, CELL_MUT_LIMITED), - Relation.SUBTYPE - }, - // test 7 - { - SemTypes.intersect( - cell(PredefinedType.INT, CELL_MUT_NONE), - cell(PredefinedType.INT, CELL_MUT_LIMITED), - cell(PredefinedType.INT, CELL_MUT_UNLIMITED) - ), - cell(PredefinedType.INT, CELL_MUT_NONE), - Relation.EQUAL - }, - // test 8 - { - SemTypes.intersect( - cell(PredefinedType.INT, CELL_MUT_NONE), - cell(PredefinedType.INT, CELL_MUT_LIMITED), - cell(PredefinedType.BYTE, CELL_MUT_LIMITED) - ), - cell(PredefinedType.BYTE, CELL_MUT_LIMITED), - Relation.SUBTYPE - }, - // test 9 - { - SemTypes.intersect( - cell(PredefinedType.INT, CELL_MUT_NONE), - SemTypes.union( - cell(PredefinedType.BYTE, CELL_MUT_LIMITED), - cell(PredefinedType.BOOLEAN, CELL_MUT_LIMITED) - ) - ), - cell(PredefinedType.BYTE, CELL_MUT_NONE), - Relation.EQUAL - }, - }; - } - - @AfterClass - public void afterClass() { - ctx = null; - } -} diff --git a/semtypes/src/test/java/io/ballerina/types/EnvInitTest.java b/semtypes/src/test/java/io/ballerina/types/EnvInitTest.java deleted file mode 100644 index 1cf69e55251e..000000000000 --- a/semtypes/src/test/java/io/ballerina/types/EnvInitTest.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import java.lang.ref.Reference; -import java.lang.reflect.Field; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Map; - -import static io.ballerina.types.Core.union; - -/** - * Test class for {@link Env} initialization. - * - * @since 2201.10.0 - */ -public class EnvInitTest { - - @BeforeClass - public void setup() { - // All the types in PredefinedTypeEnv are populated by the loading of PredefinedType class. - try { - Class.forName("io.ballerina.types.PredefinedType"); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - @Test - public void testEnvInitAtomTable() throws NoSuchFieldException, IllegalAccessException { - final Env env = new Env(); - - // Access the private field atomTable using reflection - Field atomTableField = Env.class.getDeclaredField("atomTable"); - atomTableField.setAccessible(true); - Map> atomTable = (Map) atomTableField.get(env); - - // Check that the atomTable contains the expected entries - Assert.assertEquals(atomTable.size(), 19); - - CellAtomicType cellAtomicVal = CellAtomicType.from( - PredefinedType.VAL, CellAtomicType.CellMutability.CELL_MUT_LIMITED - ); - - TypeAtom typeAtom0 = atomTable.get(cellAtomicVal).get(); - Assert.assertNotNull(typeAtom0); - Assert.assertEquals(typeAtom0.atomicType(), cellAtomicVal); - - CellAtomicType cellAtomicNever = CellAtomicType.from( - PredefinedType.NEVER, CellAtomicType.CellMutability.CELL_MUT_LIMITED - ); - - TypeAtom typeAtom1 = atomTable.get(cellAtomicNever).get(); - Assert.assertNotNull(typeAtom1); - Assert.assertEquals(typeAtom1.atomicType(), cellAtomicNever); - - CellAtomicType cellAtomicInner = CellAtomicType.from( - PredefinedType.INNER, CellAtomicType.CellMutability.CELL_MUT_LIMITED - ); - - TypeAtom typeAtom2 = atomTable.get(cellAtomicInner).get(); - Assert.assertNotNull(typeAtom2); - Assert.assertEquals(typeAtom2.atomicType(), cellAtomicInner); - - CellAtomicType cellAtomicInnerMapping = CellAtomicType.from( - union(PredefinedType.MAPPING, PredefinedType.UNDEF), - CellAtomicType.CellMutability.CELL_MUT_LIMITED - ); - - TypeAtom typeAtom3 = atomTable.get(cellAtomicInnerMapping).get(); - Assert.assertNotNull(typeAtom3); - Assert.assertEquals(typeAtom3.atomicType(), cellAtomicInnerMapping); - - ListAtomicType listAtomicMapping = ListAtomicType.from( - FixedLengthArray.empty(), PredefinedType.CELL_SEMTYPE_INNER_MAPPING - ); - - TypeAtom typeAtom4 = atomTable.get(listAtomicMapping).get(); - Assert.assertNotNull(typeAtom4); - Assert.assertEquals(typeAtom4.atomicType(), listAtomicMapping); - - TypeAtom typeAtom5 = atomTable.get(PredefinedType.CELL_ATOMIC_INNER_MAPPING_RO).get(); - Assert.assertNotNull(typeAtom5); - Assert.assertEquals(typeAtom5.atomicType(), PredefinedType.CELL_ATOMIC_INNER_MAPPING_RO); - - ListAtomicType listAtomicMappingRo = ListAtomicType.from( - FixedLengthArray.empty(), PredefinedType.CELL_SEMTYPE_INNER_MAPPING_RO - ); - - TypeAtom typeAtom6 = atomTable.get(listAtomicMappingRo).get(); - Assert.assertNotNull(typeAtom6); - Assert.assertEquals(typeAtom6.atomicType(), listAtomicMappingRo); - - CellAtomicType cellAtomicInnerRo = CellAtomicType.from( - PredefinedType.INNER_READONLY, CellAtomicType.CellMutability.CELL_MUT_NONE - ); - - TypeAtom typeAtom7 = atomTable.get(cellAtomicInnerRo).get(); - Assert.assertNotNull(typeAtom7); - Assert.assertEquals(typeAtom7.atomicType(), cellAtomicInnerRo); - - CellAtomicType cellAtomicUndef = CellAtomicType.from( - PredefinedType.UNDEF, CellAtomicType.CellMutability.CELL_MUT_NONE - ); - - TypeAtom typeAtom8 = atomTable.get(cellAtomicUndef).get(); - Assert.assertNotNull(typeAtom8); - Assert.assertEquals(typeAtom8.atomicType(), cellAtomicUndef); - - ListAtomicType listAtomicTwoElement = ListAtomicType.from( - FixedLengthArray.from(List.of(PredefinedType.CELL_SEMTYPE_VAL), 2), - PredefinedType.CELL_SEMTYPE_UNDEF - ); - - TypeAtom typeAtom9 = atomTable.get(listAtomicTwoElement).get(); - Assert.assertNotNull(typeAtom8); - Assert.assertEquals(typeAtom9.atomicType(), listAtomicTwoElement); - } - - @Test - public void testTypeAtomIndices() throws NoSuchFieldException, IllegalAccessException { - Env env = new Env(); - Field atomTableField = Env.class.getDeclaredField("atomTable"); - atomTableField.setAccessible(true); - Map> recListAtoms = - (Map>) atomTableField.get(env); - Collection indices = new HashSet<>(); - for (var each : recListAtoms.values()) { - Assert.assertTrue(indices.add(each.get().index()), "Duplicate index found: " + each.get().index()); - } - } - - @Test - public void testEnvInitRecAtoms() throws NoSuchFieldException, IllegalAccessException { - Env env = new Env(); - Field recListAtomsField = Env.class.getDeclaredField("recListAtoms"); - recListAtomsField.setAccessible(true); - List recListAtoms = (List) recListAtomsField.get(env); - Assert.assertEquals(recListAtoms.size(), 2); - ListAtomicType listAtomicRo = ListAtomicType.from( - FixedLengthArray.empty(), PredefinedType.CELL_SEMTYPE_INNER_RO - ); - Assert.assertEquals(recListAtoms.get(0), listAtomicRo); - Assert.assertNull(recListAtoms.get(1)); - - Field recMappingAtomsField = Env.class.getDeclaredField("recMappingAtoms"); - recMappingAtomsField.setAccessible(true); - List recMappingAtoms = (List) recMappingAtomsField.get(env); - Assert.assertEquals(recMappingAtoms.size(), 2); - Assert.assertEquals(recMappingAtoms.get(0), PredefinedType.MAPPING_ATOMIC_RO); - Assert.assertEquals(recMappingAtoms.get(1), PredefinedType.MAPPING_ATOMIC_OBJECT_RO); - - Field recFunctionAtomsField = Env.class.getDeclaredField("recFunctionAtoms"); - recFunctionAtomsField.setAccessible(true); - List recFunctionAtoms = (List) recFunctionAtomsField.get(env); - Assert.assertEquals(recFunctionAtoms.size(), 0); - } -} diff --git a/semtypes/src/test/java/io/ballerina/types/SemTypeBddTest.java b/semtypes/src/test/java/io/ballerina/types/SemTypeBddTest.java deleted file mode 100644 index 0653955dd696..000000000000 --- a/semtypes/src/test/java/io/ballerina/types/SemTypeBddTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import io.ballerina.types.subtypedata.BddAllOrNothing; -import io.ballerina.types.typeops.BddCommonOps; -import org.testng.Assert; -import org.testng.annotations.Test; - -/** - * Tests Bdd of Semtypes. - * - * @since 2201.8.0 - */ -public class SemTypeBddTest { - - @Test - public void bddTest() { - Bdd b1 = BddCommonOps.bddAtom(RecAtom.createRecAtom(1)); - Bdd b2 = BddCommonOps.bddAtom(RecAtom.createRecAtom(2)); - Bdd b1and2 = BddCommonOps.bddIntersect(b1, b2); - Bdd r = BddCommonOps.bddDiff(b1and2, b1); - Assert.assertFalse(((BddAllOrNothing) r).isAll()); - } -} diff --git a/semtypes/src/test/java/io/ballerina/types/SemTypeCoreTest.java b/semtypes/src/test/java/io/ballerina/types/SemTypeCoreTest.java deleted file mode 100644 index b9b15d2b1953..000000000000 --- a/semtypes/src/test/java/io/ballerina/types/SemTypeCoreTest.java +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.types; - -import io.ballerina.types.definition.FunctionDefinition; -import io.ballerina.types.definition.FunctionQualifiers; -import io.ballerina.types.definition.ListDefinition; -import io.ballerina.types.subtypedata.AllOrNothingSubtype; -import io.ballerina.types.subtypedata.IntSubtype; -import io.ballerina.types.subtypedata.Range; -import io.ballerina.types.subtypedata.StringSubtype; -import org.testng.Assert; -import org.testng.annotations.Test; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.function.BiFunction; - -import static io.ballerina.types.TypeTestUtils.roTuple; -import static io.ballerina.types.TypeTestUtils.tuple; -import static io.ballerina.types.subtypedata.StringSubtype.stringConst; - -/** - * Tests Core functions of Semtypes. - * - * @since 2201.8.0 - */ -public class SemTypeCoreTest { - - @Test - public void testSubtypeSimple() { - Assert.assertTrue(Core.isSubtypeSimple(PredefinedType.NIL, PredefinedType.ANY)); - Assert.assertTrue(Core.isSubtypeSimple(PredefinedType.INT, PredefinedType.VAL)); - Assert.assertTrue(Core.isSubtypeSimple(PredefinedType.ANY, PredefinedType.VAL)); - Assert.assertFalse(Core.isSubtypeSimple(PredefinedType.INT, PredefinedType.BOOLEAN)); - Assert.assertFalse(Core.isSubtypeSimple(PredefinedType.ERROR, PredefinedType.ANY)); - } - - @Test - public void testSingleNumericType() { - Assert.assertEquals(Core.singleNumericType(PredefinedType.INT), Optional.of(PredefinedType.INT)); - Assert.assertEquals(Core.singleNumericType(PredefinedType.BOOLEAN), Optional.empty()); - Core.singleNumericType(Core.singleton(1L)); - Assert.assertEquals(Core.singleNumericType(Core.singleton(1L)), Optional.of(PredefinedType.INT)); - Assert.assertEquals(Core.singleNumericType(Core.union(PredefinedType.INT, PredefinedType.FLOAT)), - Optional.empty()); - } - - @Test - public void testBitTwiddling() { - Assert.assertEquals(Long.numberOfTrailingZeros(0x10), 4); - Assert.assertEquals(Long.numberOfTrailingZeros(0x100), 8); - Assert.assertEquals(Long.numberOfTrailingZeros(0x1), 0); - Assert.assertEquals(Long.numberOfTrailingZeros(0x0), 64); - Assert.assertEquals(Integer.bitCount(0x10000), 1); - Assert.assertEquals(Integer.bitCount(0), 0); - Assert.assertEquals(Integer.bitCount(1), 1); - Assert.assertEquals(Integer.bitCount(0x10010010), 3); - } - - @Test - public void test1() { - Env env = new Env(); - disjoint(Core.typeCheckContext(env), PredefinedType.STRING, PredefinedType.INT); - disjoint(Core.typeCheckContext(env), PredefinedType.INT, PredefinedType.NIL); - SemType t1 = createTupleType(env, PredefinedType.INT, PredefinedType.INT); - disjoint(Core.typeCheckContext(env), t1, PredefinedType.INT); - SemType t2 = createTupleType(env, PredefinedType.STRING, PredefinedType.STRING); - disjoint(Core.typeCheckContext(env), PredefinedType.NIL, t2); - } - - private void disjoint(Context cx, SemType t1, SemType t2) { - Assert.assertFalse(Core.isSubtype(cx, t1, t2)); - Assert.assertFalse(Core.isSubtype(cx, t2, t1)); - Assert.assertTrue(Core.isEmpty(cx, Core.intersect(t1, t2))); - } - - @Test - public void test2() { - Assert.assertTrue(Core.isSubtype(Core.typeCheckContext(new Env()), PredefinedType.INT, PredefinedType.VAL)); - } - - @Test - public void test3() { - Env env = new Env(); - SemType s = roTuple(env, PredefinedType.INT, Core.union(PredefinedType.INT, - PredefinedType.STRING)); - SemType t = Core.union(roTuple(env, PredefinedType.INT, PredefinedType.INT), - roTuple(env, PredefinedType.INT, PredefinedType.STRING)); - equiv(env, s, t); - } - - private void equiv(Env env, SemType s, SemType t) { - Assert.assertTrue(Core.isSubtype(Core.typeCheckContext(env), s, t)); - Assert.assertTrue(Core.isSubtype(Core.typeCheckContext(env), t, s)); - } - - @Test - public void test4() { - Env env = new Env(); - SemType isT = createTupleType(env, PredefinedType.INT, PredefinedType.STRING); - SemType itT = createTupleType(env, PredefinedType.INT, PredefinedType.VAL); - SemType tsT = createTupleType(env, PredefinedType.VAL, PredefinedType.STRING); - SemType iiT = createTupleType(env, PredefinedType.INT, PredefinedType.INT); - SemType ttT = createTupleType(env, PredefinedType.VAL, PredefinedType.VAL); - Context cx = Core.typeCheckContext(env); - Assert.assertTrue(Core.isSubtype(cx, isT, itT)); - Assert.assertTrue(Core.isSubtype(cx, isT, tsT)); - Assert.assertTrue(Core.isSubtype(cx, iiT, ttT)); - } - - @Test - public void test5() { - Env env = new Env(); - SemType s = roTuple(env, PredefinedType.INT, Core.union(PredefinedType.NIL, - Core.union(PredefinedType.INT, PredefinedType.STRING))); - SemType t = Core.union(roTuple(env, PredefinedType.INT, PredefinedType.INT), - Core.union(roTuple(env, PredefinedType.INT, PredefinedType.NIL), - roTuple(env, PredefinedType.INT, PredefinedType.STRING))); - equiv(env, s, t); - } - - @Test - public void test6() { - Env env = new Env(); - SemType s = tuple(env, PredefinedType.INT, Core.union(PredefinedType.NIL, - Core.union(PredefinedType.INT, PredefinedType.STRING))); - SemType t = Core.union(tuple(env, PredefinedType.INT, PredefinedType.INT), - Core.union(tuple(env, PredefinedType.INT, PredefinedType.NIL), - tuple(env, PredefinedType.INT, PredefinedType.STRING))); - Assert.assertTrue(Core.isSubtype(Core.typeCheckContext(env), t, s)); - Assert.assertFalse(Core.isSubtype(Core.typeCheckContext(env), s, t)); - } - - @Test - public void test7() { - Env env = new Env(); - SemType s = tuple(env, PredefinedType.INT, Core.union(PredefinedType.INT, - PredefinedType.STRING)); - SemType t = Core.union(tuple(env, PredefinedType.INT, PredefinedType.INT), - tuple(env, PredefinedType.INT, PredefinedType.STRING)); - Assert.assertTrue(Core.isSubtype(Core.typeCheckContext(env), t, s)); - Assert.assertFalse(Core.isSubtype(Core.typeCheckContext(env), s, t)); - } - - @Test - public void tupleTest1() { - Env env = new Env(); - SemType s = createTupleType(env, PredefinedType.INT, PredefinedType.STRING, PredefinedType.NIL); - SemType t = createTupleType(env, PredefinedType.VAL, PredefinedType.VAL, PredefinedType.VAL); - Assert.assertTrue(Core.isSubtype(Core.typeCheckContext(env), s, t)); - Assert.assertFalse(Core.isSubtype(Core.typeCheckContext(env), t, s)); - } - - @Test - public void tupleTest2() { - Env env = new Env(); - SemType s = createTupleType(env, PredefinedType.INT, PredefinedType.STRING, PredefinedType.NIL); - SemType t = createTupleType(env, PredefinedType.VAL, PredefinedType.VAL); - Assert.assertFalse(Core.isSubtype(Core.typeCheckContext(env), s, t)); - Assert.assertFalse(Core.isSubtype(Core.typeCheckContext(env), t, s)); - } - - @Test - public void tupleTest3() { - Env env = new Env(); - SemType z1 = createTupleType(env); - SemType z2 = createTupleType(env); - SemType t = createTupleType(env, PredefinedType.INT); - Assert.assertTrue(!Core.isEmpty(Core.typeCheckContext(env), z1)); - Assert.assertTrue(Core.isSubtype(Core.typeCheckContext(env), z1, z2)); - Assert.assertTrue(Core.isEmpty(Core.typeCheckContext(env), Core.diff(z1, z2))); - Assert.assertFalse(Core.isEmpty(Core.typeCheckContext(env), Core.diff(z1, PredefinedType.INT))); - Assert.assertFalse(Core.isEmpty(Core.typeCheckContext(env), Core.diff(PredefinedType.INT, z1))); - } - - @Test - public void tupleTest4() { - Env env = new Env(); - SemType s = createTupleType(env, PredefinedType.INT, PredefinedType.INT); - SemType t = createTupleType(env, PredefinedType.INT, PredefinedType.INT, PredefinedType.INT); - Assert.assertFalse(Core.isEmpty(Core.typeCheckContext(env), s)); - Assert.assertFalse(Core.isEmpty(Core.typeCheckContext(env), t)); - Assert.assertFalse(Core.isSubtype(Core.typeCheckContext(env), s, t)); - Assert.assertFalse(Core.isSubtype(Core.typeCheckContext(env), t, s)); - Assert.assertTrue(Core.isEmpty(Core.typeCheckContext(env), Core.intersect(s, t))); - } - - private SemType func(Env env, SemType args, SemType ret) { - FunctionDefinition def = new FunctionDefinition(); - return def.define(env, args, ret, FunctionQualifiers.from(env, false, false)); - } - - @Test - public void funcTest1() { - Env env = new Env(); - SemType s = func(env, PredefinedType.INT, PredefinedType.INT); - SemType t = func(env, PredefinedType.INT, Core.union(PredefinedType.NIL, PredefinedType.INT)); - Assert.assertTrue(Core.isSubtype(Core.typeCheckContext(env), s, t)); - Assert.assertFalse(Core.isSubtype(Core.typeCheckContext(env), t, s)); - } - - @Test - public void funcTest2() { - Env env = new Env(); - SemType s = func(env, Core.union(PredefinedType.NIL, PredefinedType.INT), PredefinedType.INT); - SemType t = func(env, PredefinedType.INT, PredefinedType.INT); - Assert.assertTrue(Core.isSubtype(Core.typeCheckContext(env), s, t)); - Assert.assertFalse(Core.isSubtype(Core.typeCheckContext(env), t, s)); - } - - @Test - public void funcTest3() { - Env env = new Env(); - SemType s = func(env, createTupleType(env, Core.union(PredefinedType.NIL, PredefinedType.INT)), - PredefinedType.INT); - SemType t = func(env, createTupleType(env, PredefinedType.INT), PredefinedType.INT); - Assert.assertTrue(Core.isSubtype(Core.typeCheckContext(env), s, t)); - Assert.assertFalse(Core.isSubtype(Core.typeCheckContext(env), t, s)); - } - - @Test - public void funcTest4() { - Env env = new Env(); - SemType s = func(env, createTupleType(env, Core.union(PredefinedType.NIL, PredefinedType.INT)), - PredefinedType.INT); - SemType t = func(env, createTupleType(env, PredefinedType.INT), - Core.union(PredefinedType.NIL, PredefinedType.INT)); - Assert.assertTrue(Core.isSubtype(Core.typeCheckContext(env), s, t)); - Assert.assertFalse(Core.isSubtype(Core.typeCheckContext(env), t, s)); - } - - @Test - public void stringTest() { - List result = new ArrayList<>(); - // TODO may have to assert lists by converting the output to a string list - - EnumerableSubtype.enumerableListUnion(new EnumerableString[]{EnumerableString.from("a"), - EnumerableString.from("b"), EnumerableString.from("d")}, - new EnumerableString[]{EnumerableString.from("c")}, result); - Assert.assertEquals(result.get(0).value, "a"); - Assert.assertEquals(result.get(1).value, "b"); - Assert.assertEquals(result.get(2).value, "c"); - Assert.assertEquals(result.get(3).value, "d"); - - result = new ArrayList<>(); - EnumerableSubtype.enumerableListIntersect(new EnumerableString[]{EnumerableString.from("a"), - EnumerableString.from("b"), EnumerableString.from("d")}, - new EnumerableString[]{EnumerableString.from("d")}, result); - Assert.assertEquals(result.get(0).value, "d"); - - result = new ArrayList<>(); - EnumerableSubtype.enumerableListDiff(new EnumerableString[]{EnumerableString.from("a"), - EnumerableString.from("b"), EnumerableString.from("c"), EnumerableString.from("d")}, - new EnumerableString[]{EnumerableString.from("a"), EnumerableString.from("c")}, result); - Assert.assertEquals(result.get(0).value, "b"); - Assert.assertEquals(result.get(1).value, "d"); - } - - @Test - public void roListTest() { - SemType t1 = Core.intersect(PredefinedType.LIST, PredefinedType.VAL_READONLY); - Env env = new Env(); - ListDefinition ld = new ListDefinition(); - SemType t2 = ld.defineListTypeWrapped(env, new ArrayList<>(), 0, PredefinedType.VAL); - SemType t = Core.diff(t1, t2); - Context cx = Core.typeCheckContext(env); - boolean b = Core.isEmpty(cx, t); - Assert.assertTrue(b); - } - - @Test - public void testIntSubtypeWidenUnsigned() { - Assert.assertTrue(((AllOrNothingSubtype) IntSubtype.intSubtypeWidenUnsigned(AllOrNothingSubtype.createAll())) - .isAllSubtype()); - Assert.assertTrue(((AllOrNothingSubtype) IntSubtype.intSubtypeWidenUnsigned( - IntSubtype.createIntSubtype(new Range(-1L, 10L)))).isAllSubtype()); - IntSubtype intType1 = (IntSubtype) IntSubtype.intSubtypeWidenUnsigned( - IntSubtype.createIntSubtype(new Range(0L, 0L))); - Assert.assertEquals(intType1.ranges[0].min, 0L); - Assert.assertEquals(intType1.ranges[0].max, 255L); - IntSubtype intType2 = (IntSubtype) IntSubtype.intSubtypeWidenUnsigned( - IntSubtype.createIntSubtype(new Range(0L, 257L))); - Assert.assertEquals(intType2.ranges[0].min, 0L); - Assert.assertEquals(intType2.ranges[0].max, 65535L); - } - - public SemType recursiveTuple(Env env, BiFunction> f) { - ListDefinition def = new ListDefinition(); - SemType t = def.getSemType(env); - List members = f.apply(env, t); - return def.defineListTypeWrapped(env, members, members.size()); - } - - @Test - public void recTest() { - Env env = new Env(); - SemType t1 = recursiveTuple(env, - (e, t) -> Arrays.asList(PredefinedType.INT, Core.union(t, PredefinedType.NIL))); - SemType t2 = recursiveTuple(env, (e, t) -> Arrays.asList(Core.union(PredefinedType.INT, PredefinedType.STRING), - Core.union(t, PredefinedType.NIL))); - Assert.assertTrue(Core.isSubtype(Core.typeCheckContext(env), t1, t2)); - Assert.assertFalse(Core.isSubtype(Core.typeCheckContext(env), t2, t1)); - } - - @Test - public void recTest2() { - Env env = new Env(); - SemType t1 = Core.union(PredefinedType.NIL, recursiveTuple(env, - (e, t) -> Arrays.asList(PredefinedType.INT, Core.union(t, PredefinedType.NIL)))); - SemType t2 = recursiveTuple(env, - (e, t) -> Arrays.asList(PredefinedType.INT, Core.union(t, PredefinedType.NIL))); - Assert.assertTrue(Core.isSubtype(Core.typeCheckContext(env), t2, t1)); - } - - @Test - public void recTest3() { - Env env = new Env(); - SemType t1 = recursiveTuple(env, - (e, t) -> Arrays.asList(PredefinedType.INT, Core.union(t, PredefinedType.NIL))); - SemType t2 = recursiveTuple(env, (e, t) -> Arrays.asList(PredefinedType.INT, Core.union(PredefinedType.NIL, - createTupleType(e, PredefinedType.INT, Core.union(PredefinedType.NIL, t))))); - Assert.assertTrue(Core.isSubtype(Core.typeCheckContext(env), t1, t2)); - } - - @Test - public void testStringCharSubtype() { - ComplexSemType st = (ComplexSemType) stringConst("a"); - Assert.assertEquals(st.subtypeDataList().length, 1); - StringSubtype subType = (StringSubtype) st.subtypeDataList()[0]; - Assert.assertEquals(subType.getChar().values.length, 1); - Assert.assertEquals(subType.getChar().values[0].value, "a"); - Assert.assertEquals(subType.getChar().allowed, true); - Assert.assertEquals(subType.getNonChar().values.length, 0); - Assert.assertEquals(subType.getNonChar().allowed, true); - } - - @Test - public void testStringNonCharSubtype() { - ComplexSemType st = (ComplexSemType) stringConst("abc"); - Assert.assertEquals(st.subtypeDataList().length, 1); - StringSubtype subType = (StringSubtype) st.subtypeDataList()[0]; - Assert.assertEquals(subType.getChar().values.length, 0); - Assert.assertEquals(subType.getChar().allowed, true); - Assert.assertEquals(subType.getNonChar().values.length, 1); - Assert.assertEquals(subType.getNonChar().values[0].value, "abc"); - Assert.assertEquals(subType.getNonChar().allowed, true); - } - - @Test - public void testStringSubtypeSingleValue() { - ComplexSemType abc = (ComplexSemType) stringConst("abc"); - StringSubtype abcSD = (StringSubtype) abc.subtypeDataList()[0]; - Assert.assertEquals(StringSubtype.stringSubtypeSingleValue(abcSD).get(), "abc"); - - ComplexSemType a = (ComplexSemType) stringConst("a"); - StringSubtype aSD = (StringSubtype) a.subtypeDataList()[0]; - Assert.assertEquals(StringSubtype.stringSubtypeSingleValue(aSD).get(), "a"); - - ComplexSemType aAndAbc = (ComplexSemType) Core.union(a, abc); - Assert.assertEquals(StringSubtype.stringSubtypeSingleValue(aAndAbc.subtypeDataList()[0]), - Optional.empty()); - - ComplexSemType intersect1 = (ComplexSemType) Core.intersect(aAndAbc, a); - Assert.assertEquals(StringSubtype.stringSubtypeSingleValue(intersect1.subtypeDataList()[0]).get(), "a"); - ComplexSemType intersect2 = (ComplexSemType) Core.intersect(aAndAbc, abc); - Assert.assertEquals(StringSubtype.stringSubtypeSingleValue(intersect2.subtypeDataList()[0]).get(), "abc"); - SemType intersect3 = Core.intersect(a, abc); - Assert.assertEquals(intersect3.toString(), PredefinedType.NEVER.toString()); - } - - private static SemType createTupleType(Env env, SemType... members) { - ListDefinition ld = new ListDefinition(); - return ld.tupleTypeWrapped(env, members); - } -} diff --git a/semtypes/src/test/java/io/ballerina/types/TypeTestUtils.java b/semtypes/src/test/java/io/ballerina/types/TypeTestUtils.java deleted file mode 100644 index 09b3161140e4..000000000000 --- a/semtypes/src/test/java/io/ballerina/types/TypeTestUtils.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.types; - -import io.ballerina.types.definition.ListDefinition; - -enum TypeTestUtils { - ; - - static SemType tuple(Env env, SemType... ty) { - ListDefinition ld = new ListDefinition(); - return ld.tupleTypeWrapped(env, ty); - } - - static SemType roTuple(Env env, SemType... ty) { - ListDefinition ld = new ListDefinition(); - return ld.tupleTypeWrappedRo(env, ty); - } -} diff --git a/semtypes/src/test/resources/testng.xml b/semtypes/src/test/resources/testng.xml deleted file mode 100644 index 018c612564da..000000000000 --- a/semtypes/src/test/resources/testng.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - diff --git a/settings.gradle b/settings.gradle index 1e0010e5f193..21d05ef00350 100644 --- a/settings.gradle +++ b/settings.gradle @@ -51,7 +51,6 @@ include(':ballerina-bindgen') include(':maven-resolver') include(':jballerina-unit-test') include(':jballerina-semtype-test') -include(':jballerina-semtype-port-test') include(':jballerina-benchmark-test') include(':ballerina-compiler-plugin-test') include(':ballerina-cli') @@ -217,7 +216,6 @@ project(':maven-resolver').projectDir = file('misc/maven-resolver') project(':jballerina-unit-test').projectDir = file('tests/jballerina-unit-test') project(':jballerina-semtype-test').projectDir = file('tests/jballerina-semtype-test') project(':jballerina-benchmark-test').projectDir = file('tests/jballerina-benchmark-test') -project(':jballerina-semtype-port-test').projectDir = file('tests/jballerina-semtype-port-test') project(':ballerina-compiler-plugin-test').projectDir = file('tests/ballerina-compiler-plugin-test') project(':central-client').projectDir = file('cli/central-client') project(':ballerina-cli').projectDir = file('cli/ballerina-cli') diff --git a/tests/ballerina-compiler-api-test/src/test/java/io/ballerina/semantic/api/test/TypedescriptorTest.java b/tests/ballerina-compiler-api-test/src/test/java/io/ballerina/semantic/api/test/TypedescriptorTest.java index e88942c82171..3ff673aa836f 100644 --- a/tests/ballerina-compiler-api-test/src/test/java/io/ballerina/semantic/api/test/TypedescriptorTest.java +++ b/tests/ballerina-compiler-api-test/src/test/java/io/ballerina/semantic/api/test/TypedescriptorTest.java @@ -1128,10 +1128,10 @@ private Object[][] getSingletonType() { {353, 10, STRING, "\"abc\""}, {354, 8, FLOAT, "1.2"}, {355, 9, FLOAT, "3.4"}, - {356, 8, INT, "10"}, + {356, 8, BYTE, "10"}, {357, 11, INT, "46575"}, - {358, 12, FLOAT, "161.70703125"}, - {359, 14, FLOAT, "357.1171875"}, + {358, 12, FLOAT, "0xA1.B5p0"}, + {359, 14, FLOAT, "0xB2.8Fp1"}, {360, 8, STRING, "\"a\""}, {361, 8, STRING, "\"RED\""}, }; diff --git a/tests/ballerina-test-utils/build.gradle b/tests/ballerina-test-utils/build.gradle index 9647982c1d06..366be3b9ec98 100644 --- a/tests/ballerina-test-utils/build.gradle +++ b/tests/ballerina-test-utils/build.gradle @@ -22,7 +22,6 @@ plugins { dependencies { implementation project(':ballerina-tools-api') - implementation project(':ballerina-parser') implementation project(':ballerina-lang') implementation project(':ballerina-runtime') implementation project(':ballerina-cli') diff --git a/tests/ballerina-test-utils/src/main/java/org/ballerinalang/test/BCompileUtil.java b/tests/ballerina-test-utils/src/main/java/org/ballerinalang/test/BCompileUtil.java index 3cf4bd961375..ba140c78fc3f 100644 --- a/tests/ballerina-test-utils/src/main/java/org/ballerinalang/test/BCompileUtil.java +++ b/tests/ballerina-test-utils/src/main/java/org/ballerinalang/test/BCompileUtil.java @@ -17,12 +17,9 @@ */ package org.ballerinalang.test; -import io.ballerina.compiler.syntax.tree.SyntaxTree; import io.ballerina.projects.BuildOptions; -import io.ballerina.projects.DocumentId; import io.ballerina.projects.JBallerinaBackend; import io.ballerina.projects.JvmTarget; -import io.ballerina.projects.Module; import io.ballerina.projects.NullBackend; import io.ballerina.projects.Package; import io.ballerina.projects.PackageCompilation; @@ -39,7 +36,6 @@ import org.slf4j.LoggerFactory; import org.wso2.ballerinalang.compiler.bir.model.BIRNode; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BPackageSymbol; -import org.wso2.ballerinalang.compiler.tree.BLangPackage; import org.wso2.ballerinalang.programfile.CompiledBinaryFile; import java.io.IOException; @@ -122,15 +118,6 @@ public static CompileResult compileOffline(String sourceFilePath) { return compileResult; } - public static PackageSyntaxTreePair compileSemType(String sourceFilePath) { - Project project = loadProject(sourceFilePath); - Package currentPackage = project.currentPackage(); - Module module = currentPackage.getDefaultModule(); - DocumentId docId = module.documentIds().iterator().next(); - return new PackageSyntaxTreePair(currentPackage.getCompilation().defaultModuleBLangPackage(), - module.document(docId).syntaxTree()); - } - public static BIRCompileResult generateBIR(String sourceFilePath) { Project project = loadProject(sourceFilePath); NullBackend nullBackend = NullBackend.from(project.currentPackage().getCompilation()); @@ -336,20 +323,4 @@ public byte[] getActualBIR() { public static String getPlatformFromBala(String balaName, String packageName, String version) { return balaName.split(packageName + "-")[1].split("-" + version)[0]; } - - /** - * Contain compiled {@code BLangPackage} and Syntax tree. - * This result is used to test sem-type relationships. - * - * @since 3.0.0 - */ - public static class PackageSyntaxTreePair { - public final BLangPackage bLangPackage; - public final SyntaxTree syntaxTree; - - public PackageSyntaxTreePair(BLangPackage bLangPackage, SyntaxTree syntaxTree) { - this.bLangPackage = bLangPackage; - this.syntaxTree = syntaxTree; - } - } } diff --git a/tests/ballerina-test-utils/src/main/java/org/ballerinalang/test/context/BServerInstance.java b/tests/ballerina-test-utils/src/main/java/org/ballerinalang/test/context/BServerInstance.java index 91e5d95ac2fc..dcc709041ed0 100644 --- a/tests/ballerina-test-utils/src/main/java/org/ballerinalang/test/context/BServerInstance.java +++ b/tests/ballerina-test-utils/src/main/java/org/ballerinalang/test/context/BServerInstance.java @@ -387,7 +387,7 @@ private void runBuildTool(String command, String[] args, Map env env.put(entry.getKey(), entry.getValue()); } } - Process process = processBuilder.start(); + process = processBuilder.start(); serverInfoLogReader = new ServerLogReader("inputStream", process.getInputStream()); tmpInfoLeechers.forEach(leecher -> serverInfoLogReader.addLeecher(leecher)); @@ -503,7 +503,7 @@ private void executeJarFile(String jarPath, String[] args, Map e for (Map.Entry entry : envProperties.entrySet()) { env.put(entry.getKey(), entry.getValue()); } - Process process = processBuilder.start(); + process = processBuilder.start(); serverInfoLogReader = new ServerLogReader("inputStream", process.getInputStream()); tmpInfoLeechers.forEach(leecher -> serverInfoLogReader.addLeecher(leecher)); diff --git a/tests/ballerina-test-utils/src/main/java/org/ballerinalang/test/context/ServerLogReader.java b/tests/ballerina-test-utils/src/main/java/org/ballerinalang/test/context/ServerLogReader.java index b9a1eb6399ac..dd18161b5a1d 100644 --- a/tests/ballerina-test-utils/src/main/java/org/ballerinalang/test/context/ServerLogReader.java +++ b/tests/ballerina-test-utils/src/main/java/org/ballerinalang/test/context/ServerLogReader.java @@ -55,8 +55,7 @@ public ServerLogReader(String name, InputStream inputStream) { * Start reading the stream. */ public void start() { - Thread thread = new Thread(this); - thread.start(); + Thread.startVirtualThread(this); } /** @@ -125,7 +124,7 @@ public void run() { } feedAndPrint(s); } else { - TimeUnit.MICROSECONDS.sleep(1); + TimeUnit.MILLISECONDS.sleep(1); } } String s = bufferedReader.readLine(); diff --git a/tests/jballerina-debugger-integration-test/src/test/java/org/ballerinalang/debugger/test/adapter/variables/VariableVisibilityTest.java b/tests/jballerina-debugger-integration-test/src/test/java/org/ballerinalang/debugger/test/adapter/variables/VariableVisibilityTest.java index df0fdbaee897..ac8e2cedd79a 100644 --- a/tests/jballerina-debugger-integration-test/src/test/java/org/ballerinalang/debugger/test/adapter/variables/VariableVisibilityTest.java +++ b/tests/jballerina-debugger-integration-test/src/test/java/org/ballerinalang/debugger/test/adapter/variables/VariableVisibilityTest.java @@ -35,7 +35,6 @@ import java.util.Map; import static org.ballerinalang.debugger.test.utils.DebugTestRunner.VariableScope; - /** * Test class for variable visibility. */ @@ -49,14 +48,13 @@ public class VariableVisibilityTest extends BaseTestCase { @Override @BeforeClass public void setup() { - } - - @Test(description = "Variable visibility test at the beginning(first line) of the main() method") - public void initialVariableVisibilityTest() throws BallerinaTestException { String testProjectName = "variable-tests"; String testModuleFileName = "main.bal"; debugTestRunner = new DebugTestRunner(testProjectName, testModuleFileName, true); + } + @Test(description = "Variable visibility test at the beginning(first line) of the main() method") + public void initialVariableVisibilityTest() throws BallerinaTestException { debugTestRunner.addBreakPoint(new BallerinaTestDebugPoint(debugTestRunner.testEntryFilePath, 123)); debugTestRunner.initDebugSession(DebugUtils.DebuggeeExecutionKind.RUN); debugHitInfo = debugTestRunner.waitForDebugHit(25000); @@ -72,10 +70,6 @@ public void initialVariableVisibilityTest() throws BallerinaTestException { @Test(description = "Variable visibility test in the middle of the main() method for a new variable") public void newVariableVisibilityTest() throws BallerinaTestException { - String testProjectName = "variable-tests"; - String testModuleFileName = "main.bal"; - debugTestRunner = new DebugTestRunner(testProjectName, testModuleFileName, true); - debugTestRunner.addBreakPoint(new BallerinaTestDebugPoint(debugTestRunner.testEntryFilePath, 245)); debugTestRunner.addBreakPoint(new BallerinaTestDebugPoint(debugTestRunner.testEntryFilePath, 316)); debugTestRunner.initDebugSession(DebugUtils.DebuggeeExecutionKind.RUN); @@ -111,10 +105,6 @@ public void newVariableVisibilityTest() throws BallerinaTestException { @Test(description = "Variable visibility test in control flows") public void controlFlowVariableVisibilityTest() throws BallerinaTestException { - String testProjectName = "variable-tests"; - String testModuleFileName = "main.bal"; - debugTestRunner = new DebugTestRunner(testProjectName, testModuleFileName, true); - debugTestRunner.addBreakPoint(new BallerinaTestDebugPoint(debugTestRunner.testEntryFilePath, 266)); debugTestRunner.addBreakPoint(new BallerinaTestDebugPoint(debugTestRunner.testEntryFilePath, 270)); debugTestRunner.addBreakPoint(new BallerinaTestDebugPoint(debugTestRunner.testEntryFilePath, 277)); @@ -187,10 +177,6 @@ public void controlFlowVariableVisibilityTest() throws BallerinaTestException { @Test(description = "Variable visibility test for global variables") public void globalVariableVisibilityTest() throws BallerinaTestException { - String testProjectName = "variable-tests"; - String testModuleFileName = "main.bal"; - debugTestRunner = new DebugTestRunner(testProjectName, testModuleFileName, true); - debugTestRunner.addBreakPoint(new BallerinaTestDebugPoint(debugTestRunner.testEntryFilePath, 352)); debugTestRunner.addBreakPoint(new BallerinaTestDebugPoint(debugTestRunner.testEntryFilePath, 327)); debugTestRunner.initDebugSession(DebugUtils.DebuggeeExecutionKind.RUN); @@ -229,10 +215,6 @@ public void globalVariableVisibilityTest() throws BallerinaTestException { @Test(description = "Variable visibility test for local variables at the last line of main() method") public void localVariableVisibilityTest() throws BallerinaTestException { - String testProjectName = "variable-tests"; - String testModuleFileName = "main.bal"; - debugTestRunner = new DebugTestRunner(testProjectName, testModuleFileName, true); - debugTestRunner.addBreakPoint(new BallerinaTestDebugPoint(debugTestRunner.testEntryFilePath, 327)); debugTestRunner.addBreakPoint(new BallerinaTestDebugPoint(debugTestRunner.testEntryFilePath, 360)); debugTestRunner.initDebugSession(DebugUtils.DebuggeeExecutionKind.RUN); @@ -357,10 +339,6 @@ public void localVariableVisibilityTest() throws BallerinaTestException { @Test(enabled = false, description = "Child variable visibility test for local variables at the last line of main" + "() method") public void localVariableChildrenVisibilityTest() throws BallerinaTestException { - String testProjectName = "variable-tests"; - String testModuleFileName = "main.bal"; - debugTestRunner = new DebugTestRunner(testProjectName, testModuleFileName, true); - debugTestRunner.addBreakPoint(new BallerinaTestDebugPoint(debugTestRunner.testEntryFilePath, 327)); debugTestRunner.initDebugSession(DebugUtils.DebuggeeExecutionKind.RUN); debugHitInfo = debugTestRunner.waitForDebugHit(25000); @@ -374,18 +352,18 @@ public void localVariableChildrenVisibilityTest() throws BallerinaTestException // xml attributes child variable visibility test Map xmlAttributesChildVariables = - debugTestRunner.fetchChildVariables(xmlChildVariables.get("attributes")); + debugTestRunner.fetchChildVariables(xmlChildVariables.get("attributes")); debugTestRunner.assertVariable(xmlAttributesChildVariables, "gender", "\"male\"", "string"); // xml children variable visibility test Map xmlChildrenVariables = - debugTestRunner.fetchChildVariables(xmlChildVariables.get("children")); + debugTestRunner.fetchChildVariables(xmlChildVariables.get("children")); debugTestRunner.assertVariable(xmlChildrenVariables, "[0]", "XMLElement", "xml"); debugTestRunner.assertVariable(xmlChildrenVariables, "[1]", "XMLElement", "xml"); // xml grand children variable visibility test Map xmlGrandChildrenVariables = - debugTestRunner.fetchChildVariables(xmlChildrenVariables.get("[0]")); + debugTestRunner.fetchChildVariables(xmlChildrenVariables.get("[0]")); debugTestRunner.assertVariable(xmlGrandChildrenVariables, "children", "XMLSequence (size = 1)", "xml"); // array child variable visibility test @@ -413,7 +391,7 @@ public void localVariableChildrenVisibilityTest() throws BallerinaTestException // record child variable visibility test (Student record) Map studentRecordChildVariables = - debugTestRunner.fetchChildVariables(localVariables.get("recordVar")); + debugTestRunner.fetchChildVariables(localVariables.get("recordVar")); debugTestRunner.assertVariable(studentRecordChildVariables, "1st_name", "\"John Doe\"", "string"); debugTestRunner.assertVariable(studentRecordChildVariables, "grades", "Grades", "record"); debugTestRunner.assertVariable(studentRecordChildVariables, "Ȧɢέ_ /:@[`{~π", "20", "int"); @@ -421,7 +399,7 @@ public void localVariableChildrenVisibilityTest() throws BallerinaTestException // record child variable visibility test (Grades record) Map gradesChildVariables = - debugTestRunner.fetchChildVariables(studentRecordChildVariables.get("grades")); + debugTestRunner.fetchChildVariables(studentRecordChildVariables.get("grades")); debugTestRunner.assertVariable(gradesChildVariables, "chemistry", "65", "int"); debugTestRunner.assertVariable(gradesChildVariables, "maths", "80", "int"); debugTestRunner.assertVariable(gradesChildVariables, "physics", "75", "int"); @@ -429,7 +407,7 @@ public void localVariableChildrenVisibilityTest() throws BallerinaTestException // anonymous record child variable visibility test Map recordChildVariables = - debugTestRunner.fetchChildVariables(localVariables.get("anonRecord")); + debugTestRunner.fetchChildVariables(localVariables.get("anonRecord")); debugTestRunner.assertVariable(recordChildVariables, "city", "\"London\"", "string"); debugTestRunner.assertVariable(recordChildVariables, "country", "\"UK\"", "string"); @@ -440,18 +418,18 @@ public void localVariableChildrenVisibilityTest() throws BallerinaTestException // error details child variable visibility test Map errorDetailsChildVariables = - debugTestRunner.fetchChildVariables(errorChildVariables.get("details")); + debugTestRunner.fetchChildVariables(errorChildVariables.get("details")); debugTestRunner.assertVariable(errorDetailsChildVariables, "message", "\"Simple error occurred\"", "string"); // future child variable visibility test Map futureChildVariables = - debugTestRunner.fetchChildVariables(localVariables.get("futureVar")); + debugTestRunner.fetchChildVariables(localVariables.get("futureVar")); debugTestRunner.assertVariable(futureChildVariables, "isDone", "true", "boolean"); debugTestRunner.assertVariable(futureChildVariables, "result", "90", "int"); // object child variable visibility test (Person object) Map personObjectChildVariables = - debugTestRunner.fetchChildVariables(localVariables.get("objectVar")); + debugTestRunner.fetchChildVariables(localVariables.get("objectVar")); debugTestRunner.assertVariable(personObjectChildVariables, "1st_name", "\"John\"", "string"); debugTestRunner.assertVariable(personObjectChildVariables, "address", "\"No 20, Palm grove\"", "string"); debugTestRunner.assertVariable(personObjectChildVariables, "parent", "()", "nil"); @@ -460,7 +438,7 @@ public void localVariableChildrenVisibilityTest() throws BallerinaTestException // anonymous object child variable visibility test (AnonPerson object) Map anonObjectChildVariables = - debugTestRunner.fetchChildVariables(localVariables.get("anonObjectVar")); + debugTestRunner.fetchChildVariables(localVariables.get("anonObjectVar")); debugTestRunner.assertVariable(anonObjectChildVariables, "1st_name", "\"John\"", "string"); debugTestRunner.assertVariable(anonObjectChildVariables, "address", "\"No 20, Palm grove\"", "string"); debugTestRunner.assertVariable(anonObjectChildVariables, "parent", "()", "nil"); @@ -481,21 +459,21 @@ public void localVariableChildrenVisibilityTest() throws BallerinaTestException // table with key child variable visibility test Map tableWithKeyChildVariables = - debugTestRunner.fetchChildVariables(localVariables.get("tableWithKeyVar")); + debugTestRunner.fetchChildVariables(localVariables.get("tableWithKeyVar")); debugTestRunner.assertVariable(tableWithKeyChildVariables, "[0]", "Employee", "record"); debugTestRunner.assertVariable(tableWithKeyChildVariables, "[1]", "Employee", "record"); debugTestRunner.assertVariable(tableWithKeyChildVariables, "[2]", "Employee", "record"); // table without key child variable visibility test Map tableWithoutKeyChildVariables = - debugTestRunner.fetchChildVariables(localVariables.get("tableWithoutKeyVar")); + debugTestRunner.fetchChildVariables(localVariables.get("tableWithoutKeyVar")); debugTestRunner.assertVariable(tableWithoutKeyChildVariables, "[0]", "Employee", "record"); debugTestRunner.assertVariable(tableWithoutKeyChildVariables, "[1]", "Employee", "record"); debugTestRunner.assertVariable(tableWithoutKeyChildVariables, "[2]", "Employee", "record"); // service child variable visibility test Map serviceChildVariables = - debugTestRunner.fetchChildVariables(localVariables.get("serviceVar")); + debugTestRunner.fetchChildVariables(localVariables.get("serviceVar")); debugTestRunner.assertVariable(serviceChildVariables, "i", "5", "int"); } @@ -573,68 +551,6 @@ public void workerVariableVisibilityTest() throws BallerinaTestException { } } - @Test(description = "Binding pattern variables related visibility test") - public void bindingPatternVariableVisibilityTest() throws BallerinaTestException { - String testProjectName = "variable-tests-2"; - String testModuleFileName = "main.bal"; - debugTestRunner = new DebugTestRunner(testProjectName, testModuleFileName, true); - - debugTestRunner.addBreakPoint(new BallerinaTestDebugPoint(debugTestRunner.testEntryFilePath, 35)); - debugTestRunner.addBreakPoint(new BallerinaTestDebugPoint(debugTestRunner.testEntryFilePath, 40)); - debugTestRunner.addBreakPoint(new BallerinaTestDebugPoint(debugTestRunner.testEntryFilePath, 43)); - debugTestRunner.addBreakPoint(new BallerinaTestDebugPoint(debugTestRunner.testEntryFilePath, 46)); - debugTestRunner.addBreakPoint(new BallerinaTestDebugPoint(debugTestRunner.testEntryFilePath, 49)); - debugTestRunner.addBreakPoint(new BallerinaTestDebugPoint(debugTestRunner.testEntryFilePath, 80)); - - debugTestRunner.initDebugSession(DebugUtils.DebuggeeExecutionKind.RUN); - Pair debugHitInfo = debugTestRunner.waitForDebugHit(25000); - - // simple binding pattern variables - localVariables = debugTestRunner.fetchVariables(debugHitInfo.getRight(), DebugTestRunner.VariableScope.LOCAL); - debugTestRunner.assertVariable(localVariables, "profession", "\"Software Engineer\"", "string"); - - // list binding pattern variables - debugTestRunner.resumeProgram(debugHitInfo.getRight(), DebugTestRunner.DebugResumeKind.NEXT_BREAKPOINT); - debugHitInfo = debugTestRunner.waitForDebugHit(10000); - // TODO: enable after fixing runtime issue https://github.com/ballerina-platform/ballerina-lang/issues/43623 -// localVariables = debugTestRunner.fetchVariables(debugHitInfo.getRight(), DebugTestRunner.VariableScope.LOCAL); -// debugTestRunner.assertVariable(localVariables, "id", "1234", "int"); -// debugTestRunner.assertVariable(localVariables, "firstName", "\"John Doe\"", "string"); - - // mapping binding pattern variables - debugTestRunner.resumeProgram(debugHitInfo.getRight(), DebugTestRunner.DebugResumeKind.NEXT_BREAKPOINT); - debugHitInfo = debugTestRunner.waitForDebugHit(10000); - // TODO: enable after fixing runtime issue https://github.com/ballerina-platform/ballerina-lang/issues/43623 -// localVariables = debugTestRunner.fetchVariables(debugHitInfo.getRight(), DebugTestRunner.VariableScope.LOCAL); -// debugTestRunner.assertVariable(localVariables, "givenName", "\"Anne\"", "string"); -// debugTestRunner.assertVariable(localVariables, "surName", "\"Frank\"", "string"); - - // error binding pattern variables - debugTestRunner.resumeProgram(debugHitInfo.getRight(), DebugTestRunner.DebugResumeKind.NEXT_BREAKPOINT); - debugHitInfo = debugTestRunner.waitForDebugHit(10000); - // TODO: enable after fixing runtime issue https://github.com/ballerina-platform/ballerina-lang/issues/43623 -// localVariables = debugTestRunner.fetchVariables(debugHitInfo.getRight(), DebugTestRunner.VariableScope.LOCAL); -// debugTestRunner.assertVariable(localVariables, "cause", "\"Database Error\"", "error"); -// debugTestRunner.assertVariable(localVariables, "code", "20", "int"); -// debugTestRunner.assertVariable(localVariables, "reason", "\"deadlock condition\"", "string"); - - // list binding pattern inside foreach statement - debugTestRunner.resumeProgram(debugHitInfo.getRight(), DebugTestRunner.DebugResumeKind.NEXT_BREAKPOINT); - debugHitInfo = debugTestRunner.waitForDebugHit(10000); - localVariables = debugTestRunner.fetchVariables(debugHitInfo.getRight(), DebugTestRunner.VariableScope.LOCAL); - debugTestRunner.assertVariable(localVariables, "name", "\"John\"", "string"); - debugTestRunner.assertVariable(localVariables, "age", "30", "int"); - - // list binding patterns inside match statement - debugTestRunner.resumeProgram(debugHitInfo.getRight(), DebugTestRunner.DebugResumeKind.NEXT_BREAKPOINT); - debugHitInfo = debugTestRunner.waitForDebugHit(10000); - // TODO: enable after fixing runtime issue https://github.com/ballerina-platform/ballerina-lang/issues/43623 -// localVariables = debugTestRunner.fetchVariables(debugHitInfo.getRight(), DebugTestRunner.VariableScope.LOCAL); -// debugTestRunner.assertVariable(localVariables, "remove", "Remove", "string"); -// debugTestRunner.assertVariable(localVariables, "all", "*", "string"); -// debugTestRunner.assertVariable(localVariables, "isDir", "true", "boolean"); - } - @Override @AfterMethod(alwaysRun = true) public void cleanUp() { diff --git a/tests/jballerina-debugger-integration-test/src/test/resources/project-based-tests/variable-tests-2/Ballerina.toml b/tests/jballerina-debugger-integration-test/src/test/resources/project-based-tests/variable-tests-2/Ballerina.toml deleted file mode 100644 index 7352e4440b5f..000000000000 --- a/tests/jballerina-debugger-integration-test/src/test/resources/project-based-tests/variable-tests-2/Ballerina.toml +++ /dev/null @@ -1,4 +0,0 @@ -[package] -org = "debug_test_resources" -name = "variable_tests_2" -version = "0.1.0" diff --git a/tests/jballerina-debugger-integration-test/src/test/resources/project-based-tests/variable-tests-2/main.bal b/tests/jballerina-debugger-integration-test/src/test/resources/project-based-tests/variable-tests-2/main.bal deleted file mode 100644 index 12fefe845eb4..000000000000 --- a/tests/jballerina-debugger-integration-test/src/test/resources/project-based-tests/variable-tests-2/main.bal +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) 2024 WSO2 LLC. (http://www.wso2.org). -// -// WSO2 LLC. licenses this file to you under the Apache License, -// Version 2.0 (the "License"); you may not use this file except -// in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -type Person record {| - int id; - string fname; - string lname; -|}; - -type SampleErrorData record {| - int code; - string reason; -|}; - -type SampleError error; - -public function main() { - // 1. simple binding pattern - var profession = "Software Engineer"; - - // 2. list binding pattern - [int, [string, string]] [id, [firstName, _]] = getDetails(); - - // 3. mapping binding pattern - string givenName; - string surname; - {fname: givenName, lname: surname} = getPerson(); - - // 4. error binding pattern - var error(_, cause, code = code, reason = reason) = getSampleError(); - - // 5. binding patterns inside a foreach statement - string names = ""; - [string, int][] personInfoList = getPersonInfo(); - foreach [string, int] [name, age] in personInfoList { - names += " " + name; - } - - // 6. binding patterns inside a match statement - matchCommand(["Remove", "*", true]); -} - -function getDetails() returns [int, [string, string]] { - return [ - 1234, - ["John", "Doe"] - ]; -} - -function getPerson() returns Person { - Person person = {id: 1001, fname: "Anne", lname: "Frank"}; - return person; -} - -function getSampleError() returns SampleError { - return error("Transaction Failure", error("Database Error"), code = 20, reason = "deadlock condition"); -} - -function matchCommand(any commands) { - match commands { - var [show] => { - string name = "show"; - } - // The list binding pattern below binds lists that contain three list items - // where the third element in the list is the boolean value `true`. - var [remove, all, isDir] if isDir is true => { - string name = "remove"; - } - // The list binding pattern below binds lists that contain three list items. - var [remove, all, _] => { - string name = "remove"; - } - // The list binding pattern below binds lists that contain two list items, - // in which the second list item is also a list of two items. - var [copy, [file1, file2]] => { - string name = "copy"; - } - _ => { - string name = "unknown"; - } - } -} - -function getPersonInfo() returns [string, int][] { - return [["John", 30]]; -} diff --git a/tests/jballerina-integration-test/src/test/resources/testng.xml b/tests/jballerina-integration-test/src/test/resources/testng.xml index dffc5fb44a00..323d222cd163 100644 --- a/tests/jballerina-integration-test/src/test/resources/testng.xml +++ b/tests/jballerina-integration-test/src/test/resources/testng.xml @@ -20,7 +20,7 @@ - + diff --git a/tests/jballerina-semtype-port-test/build.gradle b/tests/jballerina-semtype-port-test/build.gradle deleted file mode 100644 index 983e476c2b7d..000000000000 --- a/tests/jballerina-semtype-port-test/build.gradle +++ /dev/null @@ -1,28 +0,0 @@ -plugins { - id 'javaProject' - id 'ballerinaLangLibLoad' -} -dependencies { - implementation 'org.slf4j:slf4j-api' - implementation project(':ballerina-lang') - implementation project(':testerina:testerina-core') - implementation project(':ballerina-cli') - implementation project(':ballerina-lang:jballerina.java') - implementation project(':ballerina-lang-test') - implementation project(':ballerina-runtime') - implementation project(':docerina') - - testImplementation 'org.testng:testng' - testImplementation project(path: ':ballerina-test-utils', configuration: 'shadow') -} - -description = 'JBallerina Semtyp port - Unit Test Module' - -test { - // Add additional system property to distinguish tests requiring all basic types - systemProperty "ballerina.semtype.all.types.test", "true" - - useTestNG() { - suites 'src/test/resources/testng.xml' - } -} diff --git a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/CompilerSemTypeResolver.java b/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/CompilerSemTypeResolver.java deleted file mode 100644 index ec8f4641d79b..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/CompilerSemTypeResolver.java +++ /dev/null @@ -1,779 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.semtype.port.test; - -import io.ballerina.types.CellAtomicType; -import io.ballerina.types.Context; -import io.ballerina.types.Core; -import io.ballerina.types.Definition; -import io.ballerina.types.Env; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypes; -import io.ballerina.types.definition.Field; -import io.ballerina.types.definition.FunctionDefinition; -import io.ballerina.types.definition.FunctionQualifiers; -import io.ballerina.types.definition.ListDefinition; -import io.ballerina.types.definition.MappingDefinition; -import io.ballerina.types.definition.Member; -import io.ballerina.types.definition.ObjectDefinition; -import io.ballerina.types.definition.ObjectQualifiers; -import io.ballerina.types.definition.StreamDefinition; -import io.ballerina.types.subtypedata.FloatSubtype; -import io.ballerina.types.subtypedata.TableSubtype; -import org.ballerinalang.model.elements.Flag; -import org.ballerinalang.model.tree.IdentifierNode; -import org.ballerinalang.model.tree.NodeKind; -import org.ballerinalang.model.tree.types.ArrayTypeNode; -import org.ballerinalang.model.tree.types.TypeNode; -import org.ballerinalang.model.types.TypeKind; -import org.jetbrains.annotations.NotNull; -import org.wso2.ballerinalang.compiler.tree.BLangFunction; -import org.wso2.ballerinalang.compiler.tree.BLangNode; -import org.wso2.ballerinalang.compiler.tree.BLangResourceFunction; -import org.wso2.ballerinalang.compiler.tree.BLangSimpleVariable; -import org.wso2.ballerinalang.compiler.tree.BLangTypeDefinition; -import org.wso2.ballerinalang.compiler.tree.BLangVariable; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangExpression; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral; -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.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 java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Stream; - -import static org.ballerinalang.model.tree.NodeKind.CONSTANT; -import static org.wso2.ballerinalang.compiler.semantics.analyzer.SymbolEnter.getTypeOrClassName; - -/** - * Resolves sem-types for module definitions using compiler side semtype implementation. - * - * @since 2201.11.0 - */ -public class CompilerSemTypeResolver extends SemTypeResolver { - - private final Map attachedDefinitions = new HashMap<>(); - - public void defineSemTypes(List moduleDefs, TypeTestContext cx) { - Map modTable = new LinkedHashMap<>(); - for (BLangNode typeAndClassDef : moduleDefs) { - modTable.put(getTypeOrClassName(typeAndClassDef), typeAndClassDef); - } - modTable = Collections.unmodifiableMap(modTable); - - for (BLangNode def : moduleDefs) { - if (def.getKind() == NodeKind.CLASS_DEFN) { - throw new UnsupportedOperationException("Semtype are not supported for class definitions yet"); - } else if (def.getKind() == CONSTANT) { - resolveConstant(cx, modTable, (BLangConstant) def); - } else { - BLangTypeDefinition typeDefinition = (BLangTypeDefinition) def; - resolveTypeDefn(cx, modTable, typeDefinition, 0); - } - } - } - - @Override - protected void resolveConstant(TypeTestContext cx, Map modTable, - BLangConstant constant) { - SemType semtype = evaluateConst(constant); - addSemTypeBType(constant.getTypeNode(), semtype); - cx.getEnv().addTypeDef(constant.name.value, semtype); - } - - private SemType evaluateConst(BLangConstant constant) { - switch (constant.symbol.value.type.getKind()) { - case INT: - return SemTypes.intConst((long) constant.symbol.value.value); - case BOOLEAN: - return SemTypes.booleanConst((boolean) constant.symbol.value.value); - case STRING: - return SemTypes.stringConst((String) constant.symbol.value.value); - case FLOAT: - return SemTypes.floatConst((double) constant.symbol.value.value); - default: - throw new UnsupportedOperationException("Expression type not implemented for const semtype"); - } - } - - @Override - protected void resolveTypeDefn(TypeTestContext cx, Map mod, - BLangTypeDefinition defn) { - resolveTypeDefn(cx, mod, defn, 0); - } - - private SemType resolveTypeDefn(TypeTestContext cx, Map mod, BLangTypeDefinition defn, - int depth) { - if (defn.semType != null) { - return defn.semType; - } - - if (depth == defn.semCycleDepth) { - throw new IllegalStateException("cyclic type definition: " + defn.name.value); - } - defn.semCycleDepth = depth; - SemType s = resolveTypeDesc(cx, mod, defn, depth, defn.typeNode); - addSemTypeBType(defn.getTypeNode(), s); - if (defn.semType == null) { - defn.semType = s; - defn.semCycleDepth = -1; - cx.getEnv().addTypeDef(defn.name.value, s); - return s; - } else { - return s; - } - } - - private void addSemTypeBType(BLangType typeNode, SemType semType) { - if (typeNode != null) { - typeNode.getBType().semType(semType); - } - } - - public SemType resolveTypeDesc(TypeTestContext cx, Map mod, BLangTypeDefinition defn, - int depth, TypeNode td) { - if (td == null) { - return null; - } - switch (td.getKind()) { - case VALUE_TYPE: - return resolveTypeDesc(cx, (BLangValueType) td); - case BUILT_IN_REF_TYPE: - return resolveTypeDesc(cx, (BLangBuiltInRefTypeNode) td); - case RECORD_TYPE: - return resolveTypeDesc(cx, (BLangRecordTypeNode) td, mod, depth, defn); - case CONSTRAINED_TYPE: // map and typedesc - return resolveTypeDesc(cx, (BLangConstrainedType) td, mod, depth, defn); - case UNION_TYPE_NODE: - return resolveTypeDesc(cx, (BLangUnionTypeNode) td, mod, depth, defn); - case INTERSECTION_TYPE_NODE: - return resolveTypeDesc(cx, (BLangIntersectionTypeNode) td, mod, depth, defn); - case USER_DEFINED_TYPE: - return resolveTypeDesc(cx, (BLangUserDefinedType) td, mod, depth); - case FINITE_TYPE_NODE: - return resolveSingletonType((BLangFiniteTypeNode) td); - case ARRAY_TYPE: - return resolveTypeDesc(cx, mod, defn, depth, (BLangArrayType) td); - case TUPLE_TYPE_NODE: - return resolveTypeDesc(cx, mod, defn, depth, (BLangTupleTypeNode) td); - case FUNCTION_TYPE: - return resolveTypeDesc(cx, mod, defn, depth, (BLangFunctionTypeNode) td); - case TABLE_TYPE: - return resolveTypeDesc(cx, mod, defn, depth, (BLangTableTypeNode) td); - case ERROR_TYPE: - return resolveTypeDesc(cx, mod, defn, depth, (BLangErrorType) td); - case OBJECT_TYPE: - return resolveTypeDesc(cx, mod, defn, depth, (BLangObjectTypeNode) td); - case STREAM_TYPE: - return resolveTypeDesc(cx, mod, defn, depth, (BLangStreamType) td); - default: - throw new UnsupportedOperationException("type not implemented: " + td.getKind()); - } - } - - private SemType resolveTypeDesc(TypeTestContext cx, Map mod, BLangTypeDefinition defn, - int depth, BLangObjectTypeNode td) { - SemType innerType = resolveNonDistinctObject(cx, mod, defn, depth, td); - if (td.flagSet.contains(Flag.DISTINCT)) { - return getDistinctObjectType((Env) cx.getInnerEnv(), innerType); - } - return innerType; - } - - private static SemType getDistinctObjectType(Env env, SemType innerType) { - return Core.intersect(SemTypes.objectDistinct(env.distinctAtomCountGetAndIncrement()), innerType); - } - - private SemType resolveNonDistinctObject(TypeTestContext cx, Map mod, - BLangTypeDefinition defn, - int depth, BLangObjectTypeNode td) { - Env env = (Env) cx.getInnerEnv(); - if (td.defn != null) { - return td.defn.getSemType(env); - } - ObjectDefinition od = new ObjectDefinition(); - Stream fieldStream = td.fields.stream().map(field -> { - Set flags = field.flagSet; - Member.Visibility visibility = flags.contains(Flag.PUBLIC) ? Member.Visibility.Public : - Member.Visibility.Private; - SemType ty = resolveTypeDesc(cx, mod, defn, depth + 1, field.typeNode); - return new Member(field.name.value, ty, Member.Kind.Field, visibility, flags.contains(Flag.READONLY)); - }); - Stream methodStream = td.getFunctions().stream().map(method -> { - Member.Visibility visibility = method.flagSet.contains(Flag.PUBLIC) ? Member.Visibility.Public : - Member.Visibility.Private; - SemType ty = resolveTypeDesc(cx, mod, defn, depth + 1, method); - return new Member(method.name.value, ty, Member.Kind.Method, visibility, true); - }); - td.defn = od; - List members = Stream.concat(fieldStream, methodStream).toList(); - ObjectQualifiers qualifiers = getQualifiers(td); - return od.define(env, qualifiers, members); - } - - private static ObjectQualifiers getQualifiers(BLangObjectTypeNode td) { - Set flags = td.symbol.getFlags(); - ObjectQualifiers.NetworkQualifier networkQualifier; - assert !(flags.contains(Flag.CLIENT) && flags.contains(Flag.SERVICE)) : - "object can't be both client and service"; - if (flags.contains(Flag.CLIENT)) { - networkQualifier = ObjectQualifiers.NetworkQualifier.Client; - } else if (flags.contains(Flag.SERVICE)) { - networkQualifier = ObjectQualifiers.NetworkQualifier.Service; - } else { - networkQualifier = ObjectQualifiers.NetworkQualifier.None; - } - return new ObjectQualifiers(flags.contains(Flag.ISOLATED), flags.contains(Flag.READONLY), networkQualifier); - } - - // TODO: should we make definition part of BLangFunction as well? - private SemType resolveTypeDesc(TypeTestContext cx, Map mod, BLangTypeDefinition defn, - int depth, BLangFunction functionType) { - Definition attached = attachedDefinitions.get(functionType); - Env env = (Env) cx.getInnerEnv(); - if (attached != null) { - return attached.getSemType(env); - } - FunctionDefinition fd = new FunctionDefinition(); - attachedDefinitions.put(functionType, fd); - Map paramScope = new HashMap<>(); - List params = getParameters(cx, mod, paramScope, defn, depth, functionType); - SemType rest; - if (functionType.getRestParameters() == null) { - rest = PredefinedType.NEVER; - } else { - ArrayTypeNode arrayType = (ArrayTypeNode) functionType.getRestParameters().getTypeNode(); - rest = resolveTypeDesc(cx, mod, defn, depth + 1, arrayType.getElementType()); - } - SemType returnType = resolveReturnType(cx, mod, paramScope, defn, depth + 1, functionType.getReturnTypeNode()); - ListDefinition paramListDefinition = new ListDefinition(); - FunctionQualifiers qualifiers = FunctionQualifiers.from(env, functionType.flagSet.contains(Flag.ISOLATED), - functionType.flagSet.contains(Flag.TRANSACTIONAL)); - return fd.define(env, paramListDefinition.defineListTypeWrapped(env, params, params.size(), rest, - CellAtomicType.CellMutability.CELL_MUT_NONE), returnType, qualifiers); - } - - @NotNull - private List getParameters(TypeTestContext cx, Map mod, - Map paramScope, BLangTypeDefinition defn, int depth, - BLangFunction functionType) { - List params = new ArrayList<>(); - if (functionType instanceof BLangResourceFunction resourceFunctionType) { - params.add(SemTypes.stringConst(resourceFunctionType.methodName.value)); - for (var each : resourceFunctionType.resourcePathSegments) { - params.add(resolveTypeDesc(cx, mod, defn, depth + 1, each.typeNode)); - } - } - for (BLangSimpleVariable paramVar : functionType.getParameters()) { - SemType semType = resolveTypeDesc(cx, mod, defn, depth + 1, paramVar.typeNode); - if (Core.isSubtypeSimple(semType, PredefinedType.TYPEDESC)) { - paramScope.put(paramVar.name.value, paramVar); - } - params.add(semType); - } - return params; - } - - private SemType resolveTypeDesc(TypeTestContext cx, Map mod, BLangTypeDefinition defn, - int depth, BLangFunctionTypeNode td) { - Env env = (Env) cx.getInnerEnv(); - if (isFunctionTop(td)) { - if (td.flagSet.contains(Flag.ISOLATED) || td.flagSet.contains(Flag.TRANSACTIONAL)) { - FunctionQualifiers qualifiers = FunctionQualifiers.from(env, td.flagSet.contains(Flag.ISOLATED), - td.flagSet.contains(Flag.TRANSACTIONAL)); - // I think param type here is wrong. It should be the intersection of all list types, but I think - // never is close enough - return new FunctionDefinition().define(env, PredefinedType.NEVER, PredefinedType.VAL, qualifiers); - } - return PredefinedType.FUNCTION; - } - if (td.defn != null) { - return td.defn.getSemType((Env) cx.getInnerEnv()); - } - FunctionDefinition fd = new FunctionDefinition(); - td.defn = fd; - Map tdScope = new HashMap<>(); - List params = new ArrayList<>(td.params.size()); - for (BLangSimpleVariable param : td.params) { - SemType paramType = resolveTypeDesc(cx, mod, defn, depth + 1, param.typeNode); - params.add(paramType); - if (Core.isSubtypeSimple(paramType, PredefinedType.TYPEDESC)) { - tdScope.put(param.name.value, param); - } - } - SemType rest; - if (td.restParam == null) { - rest = PredefinedType.NEVER; - } else { - BLangArrayType restArrayType = (BLangArrayType) td.restParam.typeNode; - rest = resolveTypeDesc(cx, mod, defn, depth + 1, restArrayType.elemtype); - } - SemType returnType = resolveReturnType(cx, mod, tdScope, defn, depth + 1, td.returnTypeNode); - ListDefinition paramListDefinition = new ListDefinition(); - FunctionQualifiers qualifiers = FunctionQualifiers.from(env, td.flagSet.contains(Flag.ISOLATED), - td.flagSet.contains(Flag.TRANSACTIONAL)); - return fd.define(env, paramListDefinition.defineListTypeWrapped(env, params, params.size(), rest, - CellAtomicType.CellMutability.CELL_MUT_NONE), returnType, qualifiers); - } - - private SemType resolveReturnType(TypeTestContext cx, Map mod, - Map mayBeDependentlyTypeNodes, BLangTypeDefinition defn, - int depth, BLangType returnTypeNode) { - if (returnTypeNode == null) { - return PredefinedType.NIL; - } - SemType innerType; - // Dependently typed function are quite rare so doing it via exception handling should be faster than actually - // checking if it is a dependently typed one. - boolean isDependentlyType; - try { - innerType = resolveTypeDesc(cx, mod, defn, depth + 1, returnTypeNode); - isDependentlyType = false; - } catch (IndexOutOfBoundsException err) { - innerType = - resolveDependentlyTypedReturnType(cx, mod, mayBeDependentlyTypeNodes, defn, depth, returnTypeNode); - isDependentlyType = true; - } - ListDefinition ld = new ListDefinition(); - return ld.tupleTypeWrapped((Env) cx.getInnerEnv(), - !isDependentlyType ? PredefinedType.BOOLEAN : SemTypes.booleanConst(true), innerType); - } - - private SemType resolveDependentlyTypedReturnType(TypeTestContext cx, Map mod, - Map mayBeDependentlyTypeNodes, - BLangTypeDefinition defn, int depth, - TypeNode returnTypeNode) { - Map combined = new HashMap<>(mod); - combined.putAll(mayBeDependentlyTypeNodes); - return resolveTypeDesc(cx, combined, defn, depth + 1, returnTypeNode); - } - - private boolean isFunctionTop(BLangFunctionTypeNode td) { - return td.params.isEmpty() && td.restParam == null && td.returnTypeNode == null; - } - - private SemType resolveTypeDesc(TypeTestContext cx, Map mod, BLangTypeDefinition defn, - int depth, BLangArrayType td) { - if (td.defn != null) { - return td.defn.getSemType((Env) cx.getInnerEnv()); - } - ListDefinition ld = new ListDefinition(); - td.defn = ld; - - int dimensions = td.dimensions; - SemType accum = resolveTypeDesc(cx, mod, defn, depth + 1, td.elemtype); - for (int i = 0; i < dimensions; i++) { - int size = from(mod, td.sizes.get(i)); - if (i == dimensions - 1) { - accum = resolveListInner(cx, ld, size, accum); - } else { - accum = resolveListInner(cx, size, accum); - } - } - return accum; - } - - private SemType resolveListInner(TypeTestContext cx, int size, SemType eType) { - ListDefinition ld = new ListDefinition(); - return resolveListInner(cx, ld, size, eType); - } - - private static SemType resolveListInner(TypeTestContext cx, ListDefinition ld, int size, SemType eType) { - Env env = (Env) cx.getInnerEnv(); - if (size != -1) { - return ld.defineListTypeWrapped(env, List.of(eType), Math.abs(size), PredefinedType.NEVER, - CellAtomicType.CellMutability.CELL_MUT_LIMITED); - } else { - return ld.defineListTypeWrapped(env, List.of(), 0, eType, - CellAtomicType.CellMutability.CELL_MUT_LIMITED); - } - } - - private SemType resolveTypeDesc(TypeTestContext cx, Map mod, BLangTypeDefinition defn, - int depth, - BLangTupleTypeNode td) { - Env env = (Env) cx.getInnerEnv(); - if (td.defn != null) { - return td.defn.getSemType(env); - } - ListDefinition ld = new ListDefinition(); - td.defn = ld; - List memberSemTypes = - td.members.stream().map(member -> resolveTypeDesc(cx, mod, defn, depth + 1, member.typeNode)) - .toList(); - SemType rest = td.restParamType != null ? resolveTypeDesc(cx, mod, defn, depth + 1, td.restParamType) : - PredefinedType.NEVER; - return ld.defineListTypeWrapped(env, memberSemTypes, memberSemTypes.size(), rest); - } - - private SemType resolveTypeDesc(TypeTestContext cx, BLangValueType td) { - Context innerContext = (Context) cx.getInnerContext(); - switch (td.typeKind) { - case NIL: - return PredefinedType.NIL; - case BOOLEAN: - return PredefinedType.BOOLEAN; - case BYTE: - return PredefinedType.BYTE; - case INT: - return PredefinedType.INT; - case FLOAT: - return PredefinedType.FLOAT; - case DECIMAL: - return PredefinedType.DECIMAL; - case STRING: - return PredefinedType.STRING; - case TYPEDESC: - return PredefinedType.TYPEDESC; - case ERROR: - return PredefinedType.ERROR; - case HANDLE: - return PredefinedType.HANDLE; - case XML: - return PredefinedType.XML; - case ANY: - return PredefinedType.ANY; - case READONLY: - return PredefinedType.VAL_READONLY; - case ANYDATA: - return Core.createAnydata(innerContext); - case JSON: - return Core.createJson(innerContext); - default: - throw new IllegalStateException("Unknown type: " + td); - } - } - - private SemType resolveTypeDesc(TypeTestContext cx, BLangBuiltInRefTypeNode td) { - return switch (td.typeKind) { - case NEVER -> PredefinedType.NEVER; - case XML -> PredefinedType.XML; - case JSON -> Core.createJson((Context) cx.getInnerContext()); - case FUTURE -> PredefinedType.FUTURE; - default -> throw new UnsupportedOperationException("Built-in ref type not implemented: " + td.typeKind); - }; - } - - private SemType resolveTypeDesc(TypeTestContext cx, BLangConstrainedType td, Map mod, - int depth, BLangTypeDefinition defn) { - TypeKind typeKind = ((BLangBuiltInRefTypeNode) td.getType()).getTypeKind(); - return switch (typeKind) { - case MAP -> resolveMapTypeDesc(td, cx, mod, depth, defn); - case XML -> resolveXmlTypeDesc(td, cx, mod, depth, defn); - case FUTURE -> resolveFutureTypeDesc(td, cx, mod, depth, defn); - case TYPEDESC -> resolveTypedescTypeDesc(td, cx, mod, depth, defn); - default -> throw new IllegalStateException("Unexpected constrained type: " + typeKind); - }; - } - - private SemType resolveMapTypeDesc(BLangConstrainedType td, TypeTestContext cx, Map mod, - int depth, BLangTypeDefinition typeDefinition) { - Env env = (Env) cx.getInnerEnv(); - if (td.defn != null) { - return td.defn.getSemType(env); - } - - MappingDefinition d = new MappingDefinition(); - td.defn = d; - - SemType rest = resolveTypeDesc(cx, mod, typeDefinition, depth + 1, td.constraint); - return d.defineMappingTypeWrapped(env, Collections.emptyList(), rest == null ? PredefinedType.NEVER : rest); - } - - private SemType resolveXmlTypeDesc(BLangConstrainedType td, TypeTestContext cx, Map mod, - int depth, - BLangTypeDefinition defn) { - SemType constraint = resolveTypeDesc(cx, mod, defn, depth + 1, td.constraint); - return SemTypes.xmlSequence(constraint); - } - - private SemType resolveFutureTypeDesc(BLangConstrainedType td, TypeTestContext cx, - Map mod, int depth, - BLangTypeDefinition defn) { - SemType constraint = resolveTypeDesc(cx, mod, defn, depth + 1, td.constraint); - return SemTypes.futureContaining((Env) cx.getInnerEnv(), constraint); - } - - private SemType resolveTypedescTypeDesc(BLangConstrainedType td, TypeTestContext cx, - Map mod, int depth, - BLangTypeDefinition defn) { - SemType constraint = resolveTypeDesc(cx, mod, defn, depth + 1, td.constraint); - return SemTypes.typedescContaining((Env) cx.getInnerEnv(), constraint); - } - - private SemType resolveTypeDesc(TypeTestContext cx, BLangRecordTypeNode td, Map mod, - int depth, BLangTypeDefinition typeDefinition) { - if (td.defn != null) { - return td.defn.getSemType((Env) cx.getInnerEnv()); - } - - MappingDefinition d = new MappingDefinition(); - td.defn = d; - - List fields = new ArrayList<>(); - for (BLangSimpleVariable field : td.fields) { - SemType ty = resolveTypeDesc(cx, mod, typeDefinition, depth + 1, field.typeNode); - if (Core.isNever(ty)) { - throw new IllegalStateException("record field can't be never"); - } - fields.add(Field.from(field.name.value, ty, false, field.flagSet.contains(Flag.OPTIONAL))); - } - - SemType rest; - if (!td.isSealed() && td.getRestFieldType() == null) { - rest = Core.createAnydata((Context) cx.getInnerContext()); - } else { - rest = resolveTypeDesc(cx, mod, typeDefinition, depth + 1, td.restFieldType); - } - - return d.defineMappingTypeWrapped((Env) cx.getInnerEnv(), fields, rest == null ? PredefinedType.NEVER : rest); - } - - private SemType resolveTypeDesc(TypeTestContext cx, BLangUnionTypeNode td, Map mod, - int depth, - BLangTypeDefinition defn) { - Iterator iterator = td.memberTypeNodes.iterator(); - SemType u = resolveTypeDesc(cx, mod, defn, depth, iterator.next()); - while (iterator.hasNext()) { - u = Core.union(u, resolveTypeDesc(cx, mod, defn, depth, iterator.next())); - } - return u; - } - - private SemType resolveTypeDesc(TypeTestContext cx, BLangIntersectionTypeNode td, - Map mod, int depth, - BLangTypeDefinition defn) { - Iterator iterator = td.constituentTypeNodes.iterator(); - SemType i = resolveTypeDesc(cx, mod, defn, depth, iterator.next()); - while (iterator.hasNext()) { - i = Core.intersect(i, resolveTypeDesc(cx, mod, defn, depth, iterator.next())); - } - return i; - } - - private SemType resolveTypeDesc(TypeTestContext cx, BLangUserDefinedType td, Map mod, - int depth) { - String name = td.typeName.value; - // Need to replace this with a real package lookup - if (td.pkgAlias.value.equals("int")) { - return resolveIntSubtype(name); - } else if (td.pkgAlias.value.equals("string") && name.equals("Char")) { - return SemTypes.CHAR; - } else if (td.pkgAlias.value.equals("xml")) { - return resolveXmlSubtype(name); - } else if (td.pkgAlias.value.equals("regexp") && name.equals("RegExp")) { - return PredefinedType.REGEXP; - } - - BLangNode moduleLevelDef = mod.get(name); - if (moduleLevelDef == null) { - throw new IndexOutOfBoundsException("unknown type " + name); - } - - switch (moduleLevelDef.getKind()) { - case TYPE_DEFINITION -> { - SemType ty = resolveTypeDefn(cx, mod, (BLangTypeDefinition) moduleLevelDef, depth); - if (td.flagSet.contains(Flag.DISTINCT)) { - return getDistinctSemType(cx, ty); - } - return ty; - } - case CONSTANT -> { - BLangConstant constant = (BLangConstant) moduleLevelDef; - return resolveTypeDefn(cx, mod, constant.getAssociatedTypeDefinition(), depth); - } - case VARIABLE -> { - // This happens when the type is a parameter of a dependently typed function - BLangVariable variable = (BLangVariable) moduleLevelDef; - BLangConstrainedType typeDescType = (BLangConstrainedType) variable.getTypeNode(); - return resolveTypeDesc(cx, mod, null, depth, typeDescType.constraint); - } - default -> throw new UnsupportedOperationException("class defns not implemented"); - } - } - - private SemType getDistinctSemType(TypeTestContext cx, SemType innerType) { - Env env = (Env) cx.getInnerEnv(); - if (Core.isSubtypeSimple(innerType, PredefinedType.OBJECT)) { - return CompilerSemTypeResolver.getDistinctObjectType(env, innerType); - } else if (Core.isSubtypeSimple(innerType, PredefinedType.ERROR)) { - return getDistinctErrorType(env, innerType); - } - throw new IllegalArgumentException("Distinct type not supported for: " + innerType); - } - - private SemType resolveIntSubtype(String name) { - // TODO: support MAX_VALUE - return switch (name) { - case "Signed8" -> SemTypes.SINT8; - case "Signed16" -> SemTypes.SINT16; - case "Signed32" -> SemTypes.SINT32; - case "Unsigned8" -> SemTypes.UINT8; - case "Unsigned16" -> SemTypes.UINT16; - case "Unsigned32" -> SemTypes.UINT32; - default -> throw new UnsupportedOperationException("Unknown int subtype: " + name); - }; - } - - private SemType resolveXmlSubtype(String name) { - return switch (name) { - case "Element" -> SemTypes.XML_ELEMENT; - case "Comment" -> SemTypes.XML_COMMENT; - case "Text" -> SemTypes.XML_TEXT; - case "ProcessingInstruction" -> SemTypes.XML_PI; - default -> throw new IllegalStateException("Unknown XML subtype: " + name); - }; - } - - private SemType resolveSingletonType(BLangFiniteTypeNode td) { - return resolveSingletonType(td.valueSpace); - } - - private SemType resolveSingletonType(List valueSpace) { - List types = new ArrayList<>(); - for (BLangExpression bLangExpression : valueSpace) { - types.add(resolveSingletonType((BLangLiteral) bLangExpression)); - } - - Iterator iter = types.iterator(); - SemType u = iter.next(); - while (iter.hasNext()) { - u = SemTypes.union(u, iter.next()); - } - return u; - } - - private SemType resolveSingletonType(BLangLiteral literal) { - return resolveSingletonType(literal.value, literal.getDeterminedType().getKind()); - } - - private SemType resolveSingletonType(Object value, TypeKind targetTypeKind) { - return switch (targetTypeKind) { - case NIL -> PredefinedType.NIL; - case BOOLEAN -> SemTypes.booleanConst((Boolean) value); - case INT, BYTE -> { - assert !(value instanceof Byte); - yield SemTypes.intConst(((Number) value).longValue()); - } - case FLOAT -> { - double doubleVal; - if (value instanceof Long longValue) { - doubleVal = longValue.doubleValue(); - } else if (value instanceof Double doubleValue) { - doubleVal = doubleValue; - } else { - // literal value will be a string if it wasn't within the bounds of what is supported by Java Long - // or Double when it was parsed in BLangNodeBuilder. - try { - doubleVal = Double.parseDouble((String) value); - } catch (NumberFormatException e) { - // We reach here when there is a syntax error. Mock the flow with default float value. - yield FloatSubtype.floatConst(0); - } - } - yield SemTypes.floatConst(doubleVal); - // literal value will be a string if it wasn't within the bounds of what is supported by Java Long - // or Double when it was parsed in BLangNodeBuilder. - // We reach here when there is a syntax error. Mock the flow with default float value. - } - case DECIMAL -> SemTypes.decimalConst((String) value); - case STRING -> SemTypes.stringConst((String) value); - default -> throw new UnsupportedOperationException("Finite type not implemented for: " + targetTypeKind); - }; - } - - private SemType resolveTypeDesc(TypeTestContext cx, Map mod, BLangTypeDefinition defn, - int depth, BLangTableTypeNode td) { - SemType tableConstraint = resolveTypeDesc(cx, mod, defn, depth, td.constraint); - Context context = (Context) cx.getInnerContext(); - if (td.tableKeySpecifier != null) { - List fieldNameIdentifierList = td.tableKeySpecifier.fieldNameIdentifierList; - String[] fieldNames = fieldNameIdentifierList.stream().map(IdentifierNode::getValue).toArray(String[]::new); - return TableSubtype.tableContainingKeySpecifier(context, tableConstraint, fieldNames); - } - - if (td.tableKeyTypeConstraint != null) { - SemType keyConstraint = resolveTypeDesc(cx, mod, defn, depth, td.tableKeyTypeConstraint.keyType); - return TableSubtype.tableContainingKeyConstraint(context, tableConstraint, keyConstraint); - } - - return TableSubtype.tableContaining(context.env, tableConstraint); - } - - private SemType resolveTypeDesc(TypeTestContext cx, Map mod, BLangTypeDefinition defn, - int depth, - BLangErrorType td) { - SemType err; - if (td.detailType == null) { - err = PredefinedType.ERROR; - } else { - SemType detail = resolveTypeDesc(cx, mod, defn, depth, td.detailType); - err = SemTypes.errorDetail(detail); - } - - if (td.flagSet.contains(Flag.DISTINCT)) { - Env env = (Env) cx.getInnerEnv(); - err = getDistinctErrorType(env, err); - } - return err; - } - - private static SemType getDistinctErrorType(Env env, SemType err) { - return Core.intersect(SemTypes.errorDistinct(env.distinctAtomCountGetAndIncrement()), err); - } - - private SemType resolveTypeDesc(TypeTestContext cx, Map mod, BLangTypeDefinition defn, - int depth, BLangStreamType td) { - if (td.constraint == null) { - return PredefinedType.STREAM; - } - Env env = (Env) cx.getInnerEnv(); - if (td.defn != null) { - return td.defn.getSemType(env); - } - StreamDefinition d = new StreamDefinition(); - td.defn = d; - - SemType valueType = resolveTypeDesc(cx, mod, defn, depth + 1, td.constraint); - SemType completionType = td.error == null ? - PredefinedType.NIL : resolveTypeDesc(cx, mod, defn, depth + 1, td.error); - return d.define(env, valueType, completionType); - } -} diff --git a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/CompilerTypeTestAPI.java b/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/CompilerTypeTestAPI.java deleted file mode 100644 index 71870e480870..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/CompilerTypeTestAPI.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.semtype.port.test; - -import io.ballerina.types.BasicTypeBitSet; -import io.ballerina.types.Context; -import io.ballerina.types.PredefinedType; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypes; - -public final class CompilerTypeTestAPI implements TypeTestAPI { - - private static final CompilerTypeTestAPI INSTANCE = new CompilerTypeTestAPI(); - - private CompilerTypeTestAPI() { - } - - public static CompilerTypeTestAPI getInstance() { - return INSTANCE; - } - - @Override - public boolean isSubtype(TypeTestContext cx, SemType t1, SemType t2) { - return SemTypes.isSubtype(form(cx), t1, t2); - } - - private static Context form(TypeTestContext cx) { - return (Context) cx.getInnerContext(); - } - - @Override - public boolean isSubtypeSimple(SemType t1, SemType t2) { - return SemTypes.isSubtypeSimple(t1, (BasicTypeBitSet) t2); - } - - @Override - public boolean isListType(SemType t) { - return SemTypes.isSubtypeSimple(t, PredefinedType.LIST); - } - - @Override - public boolean isMapType(SemType t) { - return SemTypes.isSubtypeSimple(t, PredefinedType.MAPPING); - } - - @Override - public SemType intConst(long l) { - return SemTypes.intConst(l); - } - - @Override - public SemType mappingMemberTypeInnerVal(TypeTestContext context, SemType semType, SemType m) { - return SemTypes.mappingMemberTypeInnerVal((Context) context.getInnerContext(), semType, m); - } - - @Override - public SemType listProj(TypeTestContext context, SemType t, SemType key) { - return SemTypes.listProj((Context) context.getInnerContext(), t, key); - } - - @Override - public SemType listMemberType(TypeTestContext context, SemType t, SemType key) { - return SemTypes.listMemberType((Context) context.getInnerContext(), t, key); - } -} diff --git a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/CompilerTypeTestEnv.java b/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/CompilerTypeTestEnv.java deleted file mode 100644 index 116d114445be..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/CompilerTypeTestEnv.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.semtype.port.test; - -import io.ballerina.types.Env; -import io.ballerina.types.SemType; - -import java.util.Map; - -public class CompilerTypeTestEnv implements TypeTestEnv { - - private final Env env; - - private CompilerTypeTestEnv(Env env) { - this.env = env; - } - - public static synchronized CompilerTypeTestEnv from(Env env) { - return new CompilerTypeTestEnv(env); - } - - @Override - public Map getTypeNameSemTypeMap() { - return env.getTypeNameSemTypeMap(); - } - - @Override - public void addTypeDef(String value, SemType semtype) { - env.addTypeDef(value, semtype); - } - - @Override - public Object getInnerEnv() { - return env; - } -} diff --git a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/ComplierTypeTestContext.java b/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/ComplierTypeTestContext.java deleted file mode 100644 index ceafd5eddba1..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/ComplierTypeTestContext.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.semtype.port.test; - -import io.ballerina.types.Context; -import io.ballerina.types.SemType; - -public class ComplierTypeTestContext implements TypeTestContext { - - private final Context context; - private final TypeTestEnv env; - - private ComplierTypeTestContext(Context context) { - this.context = context; - env = CompilerTypeTestEnv.from(context.env); - } - - public static synchronized ComplierTypeTestContext from(Context context) { - return new ComplierTypeTestContext(context); - } - - @Override - public TypeTestEnv getEnv() { - return env; - } - - @Override - public Object getInnerEnv() { - return context.env; - } - - @Override - public Object getInnerContext() { - return context; - } -} diff --git a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/RuntimeSemTypeResolver.java b/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/RuntimeSemTypeResolver.java deleted file mode 100644 index 14644cc3e289..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/RuntimeSemTypeResolver.java +++ /dev/null @@ -1,738 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.semtype.port.test; - -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.Definition; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.SemType; -import io.ballerina.runtime.internal.types.semtype.CellAtomicType; -import io.ballerina.runtime.internal.types.semtype.ErrorUtils; -import io.ballerina.runtime.internal.types.semtype.FunctionDefinition; -import io.ballerina.runtime.internal.types.semtype.FunctionQualifiers; -import io.ballerina.runtime.internal.types.semtype.FutureUtils; -import io.ballerina.runtime.internal.types.semtype.ListDefinition; -import io.ballerina.runtime.internal.types.semtype.MappingDefinition; -import io.ballerina.runtime.internal.types.semtype.Member; -import io.ballerina.runtime.internal.types.semtype.ObjectDefinition; -import io.ballerina.runtime.internal.types.semtype.ObjectQualifiers; -import io.ballerina.runtime.internal.types.semtype.StreamDefinition; -import io.ballerina.runtime.internal.types.semtype.TableUtils; -import io.ballerina.runtime.internal.types.semtype.TypedescUtils; -import io.ballerina.runtime.internal.types.semtype.XmlUtils; -import org.ballerinalang.model.elements.Flag; -import org.ballerinalang.model.tree.IdentifierNode; -import org.ballerinalang.model.tree.types.ArrayTypeNode; -import org.ballerinalang.model.tree.types.TypeNode; -import org.ballerinalang.model.types.TypeKind; -import org.wso2.ballerinalang.compiler.tree.BLangFunction; -import org.wso2.ballerinalang.compiler.tree.BLangNode; -import org.wso2.ballerinalang.compiler.tree.BLangResourceFunction; -import org.wso2.ballerinalang.compiler.tree.BLangSimpleVariable; -import org.wso2.ballerinalang.compiler.tree.BLangTypeDefinition; -import org.wso2.ballerinalang.compiler.tree.BLangVariable; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral; -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.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 java.math.BigDecimal; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Stream; - -import static io.ballerina.runtime.api.constants.RuntimeConstants.SIGNED16_MAX_VALUE; -import static io.ballerina.runtime.api.constants.RuntimeConstants.SIGNED16_MIN_VALUE; -import static io.ballerina.runtime.api.constants.RuntimeConstants.SIGNED32_MAX_VALUE; -import static io.ballerina.runtime.api.constants.RuntimeConstants.SIGNED32_MIN_VALUE; -import static io.ballerina.runtime.api.constants.RuntimeConstants.SIGNED8_MAX_VALUE; -import static io.ballerina.runtime.api.constants.RuntimeConstants.SIGNED8_MIN_VALUE; -import static io.ballerina.runtime.api.constants.RuntimeConstants.UNSIGNED16_MAX_VALUE; -import static io.ballerina.runtime.api.constants.RuntimeConstants.UNSIGNED32_MAX_VALUE; -import static io.ballerina.runtime.api.constants.RuntimeConstants.UNSIGNED8_MAX_VALUE; -import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_LIMITED; -import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_NONE; - -/** - * Resolves sem-types for module definitions using runtime side semtype implementation. - * - * @since 2201.11.0 - */ -class RuntimeSemTypeResolver extends SemTypeResolver { - - private static final SemType[] EMPTY_SEMTYPE_ARR = {}; - Map attachedSemType = new HashMap<>(); - Map semTypeMemo = new HashMap<>(); - Map attachedDefinitions = new HashMap<>(); - - @Override - public void resolveTypeDefn(TypeTestContext cx, Map modTable, - BLangTypeDefinition typeDefinition) { - resolveTypeDefnRec(cx, modTable, typeDefinition, 0); - } - - @Override - public void resolveConstant(TypeTestContext cx, Map modTable, BLangConstant constant) { - SemType semtype = evaluateConst(constant); - attachToBType(constant.typeNode, semtype); - cx.getEnv().addTypeDef(constant.name.value, semtype); - } - - private SemType resolveTypeDefnRec(TypeTestContext cx, Map mod, - BLangTypeDefinition defn, int depth) { - SemType memo = semTypeMemo.get(defn); - if (memo != null) { - return memo; - } - if (depth == defn.semCycleDepth) { - throw new IllegalStateException("cyclic type definition: " + defn.name.value); - } - - defn.semCycleDepth = depth; - SemType s = resolveTypeDesc(cx, mod, defn, depth, defn.typeNode); - attachToBType(defn.getTypeNode(), s); - if (!semTypeMemo.containsKey(defn)) { - semTypeMemo.put(defn, s); - defn.semCycleDepth = -1; - cx.getEnv().addTypeDef(defn.name.value, s); - return s; - } else { - return s; - } - } - - private SemType resolveTypeDesc(TypeTestContext cx, Map mod, BLangTypeDefinition defn, - int depth, TypeNode td) { - if (td == null) { - return null; - } - return switch (td.getKind()) { - case VALUE_TYPE -> resolveTypeDesc(cx, (BLangValueType) td); - case BUILT_IN_REF_TYPE -> resolveTypeDesc((BLangBuiltInRefTypeNode) td); - case INTERSECTION_TYPE_NODE -> resolveTypeDesc(cx, (BLangIntersectionTypeNode) td, mod, depth, defn); - case UNION_TYPE_NODE -> resolveTypeDesc(cx, (BLangUnionTypeNode) td, mod, depth, defn); - case USER_DEFINED_TYPE -> resolveTypeDesc(cx, (BLangUserDefinedType) td, mod, depth); - case FINITE_TYPE_NODE -> resolveSingletonType((BLangFiniteTypeNode) td); - case ARRAY_TYPE -> resolveArrayTypeDesc(cx, mod, defn, depth, (BLangArrayType) td); - case TUPLE_TYPE_NODE -> resolveTupleTypeDesc(cx, mod, defn, depth, (BLangTupleTypeNode) td); - case CONSTRAINED_TYPE -> resolveConstrainedTypeDesc(cx, mod, defn, depth, (BLangConstrainedType) td); - case RECORD_TYPE -> resolveRecordTypeDesc(cx, mod, defn, depth, (BLangRecordTypeNode) td); - case FUNCTION_TYPE -> resolveFunctionTypeDesc(cx, mod, defn, depth, (BLangFunctionTypeNode) td); - case OBJECT_TYPE -> resolveObjectTypeDesc(cx, mod, defn, depth, (BLangObjectTypeNode) td); - case ERROR_TYPE -> resolveErrorTypeDesc(cx, mod, defn, depth, (BLangErrorType) td); - case TABLE_TYPE -> resolveTableTypeDesc(cx, mod, defn, depth, (BLangTableTypeNode) td); - case STREAM_TYPE -> resolveStreamTypeDesc(cx, mod, defn, depth, (BLangStreamType) td); - default -> throw new UnsupportedOperationException("type not implemented: " + td.getKind()); - }; - } - - private SemType resolveStreamTypeDesc(TypeTestContext cx, Map mod, - BLangTypeDefinition defn, int depth, BLangStreamType td) { - if (td.constraint == null) { - return Builder.getStreamType(); - } - Env env = (Env) cx.getInnerEnv(); - Definition attachedDefinition = attachedDefinitions.get(td); - if (attachedDefinition != null) { - return attachedDefinition.getSemType(env); - } - StreamDefinition sd = new StreamDefinition(); - attachedDefinitions.put(td, sd); - - SemType valueType = resolveTypeDesc(cx, mod, defn, depth + 1, td.constraint); - SemType completionType = td.error == null ? Builder.getNilType() : - resolveTypeDesc(cx, mod, defn, depth + 1, td.error); - return sd.define(env, valueType, completionType); - } - - private SemType resolveTableTypeDesc(TypeTestContext cx, - Map mod, BLangTypeDefinition defn, - int depth, BLangTableTypeNode td) { - SemType tableConstraint = resolveTypeDesc(cx, mod, defn, depth + 1, td.constraint); - Context context = (Context) cx.getInnerContext(); - if (td.tableKeySpecifier != null) { - List fieldNameIdentifierList = td.tableKeySpecifier.fieldNameIdentifierList; - String[] fieldNames = fieldNameIdentifierList.stream().map(IdentifierNode::getValue).toArray(String[]::new); - return TableUtils.tableContainingKeySpecifier(context, tableConstraint, fieldNames); - } - if (td.tableKeyTypeConstraint != null) { - SemType keyConstraint = resolveTypeDesc(cx, mod, defn, depth + 1, td.tableKeyTypeConstraint.keyType); - return TableUtils.tableContainingKeyConstraint(context, tableConstraint, keyConstraint); - } - return TableUtils.tableContaining(context.env, tableConstraint); - } - - - private SemType resolveErrorTypeDesc(TypeTestContext cx, Map mod, - BLangTypeDefinition defn, int depth, BLangErrorType td) { - SemType innerType = createErrorType(cx, mod, defn, depth, td); - if (td.flagSet.contains(Flag.DISTINCT)) { - Env env = (Env) cx.getInnerEnv(); - return getDistinctErrorType(env, innerType); - } - return innerType; - } - - private static SemType getDistinctErrorType(Env env, SemType innerType) { - return Core.intersect(ErrorUtils.errorDistinct(env.distinctAtomCountGetAndIncrement()), innerType); - } - - private SemType createErrorType(TypeTestContext cx, Map mod, BLangTypeDefinition defn, - int depth, BLangErrorType td) { - if (td.detailType == null) { - return Builder.getErrorType(); - } else { - SemType detailType = resolveTypeDesc(cx, mod, defn, depth + 1, td.detailType); - return ErrorUtils.errorDetail(detailType); - } - } - - private SemType resolveObjectTypeDesc(TypeTestContext cx, Map mod, - BLangTypeDefinition defn, int depth, BLangObjectTypeNode td) { - SemType innerType = resolveNonDistinctObject(cx, mod, defn, depth, td); - if (td.flagSet.contains(Flag.DISTINCT)) { - return getDistinctObjectType((Env) cx.getInnerEnv(), innerType); - } - return innerType; - } - - private SemType resolveNonDistinctObject(TypeTestContext cx, Map mod, - BLangTypeDefinition defn, int depth, BLangObjectTypeNode td) { - Env env = (Env) cx.getInnerEnv(); - Definition attachedDefinition = attachedDefinitions.get(td); - if (attachedDefinition != null) { - return attachedDefinition.getSemType(env); - } - ObjectDefinition od = new ObjectDefinition(); - attachedDefinitions.put(td, od); - Stream fieldStream = td.fields.stream().map(field -> { - Set flags = field.flagSet; - Member.Visibility visibility = flags.contains(Flag.PUBLIC) ? Member.Visibility.Public : - Member.Visibility.Private; - SemType ty = resolveTypeDesc(cx, mod, defn, depth + 1, field.typeNode); - return new Member(field.name.value, ty, Member.Kind.Field, visibility, flags.contains(Flag.READONLY)); - }); - Stream methodStream = td.getFunctions().stream().map(method -> { - Member.Visibility visibility = method.flagSet.contains(Flag.PUBLIC) ? Member.Visibility.Public : - Member.Visibility.Private; - SemType ty = resolveFunctionType(cx, mod, defn, depth + 1, method); - return new Member(method.name.value, ty, Member.Kind.Method, visibility, true); - }); - List members = Stream.concat(fieldStream, methodStream).toList(); - ObjectQualifiers qualifiers = getQualifiers(td); - return od.define(env, qualifiers, members, qualifiers.readonly() ? CELL_MUT_NONE : - CELL_MUT_LIMITED); - } - - private ObjectQualifiers getQualifiers(BLangObjectTypeNode td) { - Set flags = td.symbol.getFlags(); - ObjectQualifiers.NetworkQualifier networkQualifier; - assert !(flags.contains(Flag.CLIENT) && flags.contains(Flag.SERVICE)) : - "object can't be both client and service"; - if (flags.contains(Flag.CLIENT)) { - networkQualifier = ObjectQualifiers.NetworkQualifier.Client; - } else if (flags.contains(Flag.SERVICE)) { - networkQualifier = ObjectQualifiers.NetworkQualifier.Service; - } else { - networkQualifier = ObjectQualifiers.NetworkQualifier.None; - } - return new ObjectQualifiers(flags.contains(Flag.ISOLATED), flags.contains(Flag.READONLY), networkQualifier); - } - - private SemType resolveFunctionType(TypeTestContext cx, Map mod, - BLangTypeDefinition defn, - int depth, BLangFunction functionType) { - Env env = (Env) cx.getInnerEnv(); - Definition attached = attachedDefinitions.get(functionType); - if (attached != null) { - return attached.getSemType(env); - } - FunctionDefinition fd = new FunctionDefinition(); - attachedDefinitions.put(functionType, fd); - Map paramScope = new HashMap<>(); - SemType[] params = getParameters(cx, mod, paramScope, defn, depth, functionType); - SemType rest; - if (functionType.getRestParameters() == null) { - rest = Builder.getNeverType(); - } else { - ArrayTypeNode arrayType = (ArrayTypeNode) functionType.getRestParameters().getTypeNode(); - rest = resolveTypeDesc(cx, mod, defn, depth + 1, arrayType.getElementType()); - } - SemType returnType = resolveReturnType(cx, mod, paramScope, defn, depth + 1, functionType.getReturnTypeNode()); - ListDefinition paramListDefinition = new ListDefinition(); - FunctionQualifiers qualifiers = FunctionQualifiers.create(functionType.flagSet.contains(Flag.ISOLATED), - functionType.flagSet.contains(Flag.TRANSACTIONAL)); - return fd.define(env, paramListDefinition.defineListTypeWrapped(env, params, params.length, rest, - CellAtomicType.CellMutability.CELL_MUT_NONE), returnType, qualifiers); - } - - private SemType[] getParameters(TypeTestContext cx, Map mod, - Map paramScope, BLangTypeDefinition defn, int depth, - BLangFunction functionType) { - List params = new ArrayList<>(); - if (functionType instanceof BLangResourceFunction resourceFunctionType) { - params.add(Builder.getStringConst(resourceFunctionType.methodName.value)); - for (var each : resourceFunctionType.resourcePathSegments) { - params.add(resolveTypeDesc(cx, mod, defn, depth + 1, each.typeNode)); - } - } - for (BLangSimpleVariable paramVar : functionType.getParameters()) { - SemType semType = resolveTypeDesc(cx, mod, defn, depth + 1, paramVar.typeNode); - if (Core.isSubtypeSimple(semType, Builder.getTypeDescType())) { - paramScope.put(paramVar.name.value, paramVar); - } - params.add(semType); - } - return params.toArray(SemType[]::new); - } - - private SemType getDistinctObjectType(Env env, SemType innerType) { - return Core.intersect(ObjectDefinition.distinct(env.distinctAtomCountGetAndIncrement()), innerType); - } - - private SemType resolveFunctionTypeDesc(TypeTestContext cx, Map mod, - BLangTypeDefinition defn, int depth, BLangFunctionTypeNode td) { - Env env = (Env) cx.getInnerEnv(); - if (isFunctionTop(td)) { - if (td.flagSet.contains(Flag.ISOLATED) || td.flagSet.contains(Flag.TRANSACTIONAL)) { - FunctionDefinition fd = new FunctionDefinition(); - return fd.define(env, Builder.getNeverType(), Builder.getValType(), - FunctionQualifiers.create( - td.flagSet.contains(Flag.ISOLATED), - td.flagSet.contains(Flag.TRANSACTIONAL))); - } - return Builder.getFunctionType(); - } - Definition attachedDefinition = attachedDefinitions.get(td); - if (attachedDefinition != null) { - return attachedDefinition.getSemType(env); - } - FunctionDefinition fd = new FunctionDefinition(); - attachedDefinitions.put(td, fd); - - Map tdScope = new HashMap<>(); - List params = new ArrayList<>(td.params.size()); - for (BLangSimpleVariable param : td.params) { - SemType paramType = resolveTypeDesc(cx, mod, defn, depth + 1, param.typeNode); - params.add(paramType); - if (Core.isSubtypeSimple(paramType, Builder.getTypeDescType())) { - tdScope.put(param.name.value, param); - } - } - SemType rest; - if (td.restParam == null) { - rest = Builder.getNeverType(); - } else { - BLangArrayType restArrayType = (BLangArrayType) td.restParam.typeNode; - rest = resolveTypeDesc(cx, mod, defn, depth + 1, restArrayType.elemtype); - } - SemType returnType = resolveReturnType(cx, mod, tdScope, defn, depth + 1, td.returnTypeNode); - ListDefinition paramListDefinition = new ListDefinition(); - return fd.define(env, - paramListDefinition.defineListTypeWrapped(env, params.toArray(SemType[]::new), params.size(), rest, - CELL_MUT_NONE), - returnType, - FunctionQualifiers.create(td.flagSet.contains(Flag.ISOLATED), td.flagSet.contains(Flag.TRANSACTIONAL))); - } - - private SemType resolveReturnType(TypeTestContext cx, - Map mod, - Map mayBeDependentlyTypeNodes, - BLangTypeDefinition defn, - int depth, BLangType returnTypeNode) { - if (returnTypeNode == null) { - return Builder.getNilType(); - } - SemType innerType; - // Dependently typed function are quite rare so doing it via exception handling should be faster than actually - // checking if it is a dependently typed one. - boolean isDependentlyType; - try { - innerType = resolveTypeDesc(cx, mod, defn, depth + 1, returnTypeNode); - isDependentlyType = false; - } catch (IndexOutOfBoundsException err) { - innerType = - resolveDependentlyTypedReturnType(cx, mod, mayBeDependentlyTypeNodes, defn, depth, returnTypeNode); - isDependentlyType = true; - } - ListDefinition ld = new ListDefinition(); - return ld.defineListTypeWrapped((Env) cx.getInnerEnv(), - new SemType[]{!isDependentlyType ? Builder.getBooleanType() : Builder.getBooleanConst(true), - innerType}, 2, Builder.getNeverType(), - CELL_MUT_LIMITED); - } - - private SemType resolveDependentlyTypedReturnType(TypeTestContext cx, - Map mod, - Map mayBeDependentlyTypeNodes, - BLangTypeDefinition defn, int depth, - TypeNode returnTypeNode) { - Map combined = new HashMap<>(mod); - combined.putAll(mayBeDependentlyTypeNodes); - return resolveTypeDesc(cx, combined, defn, depth + 1, returnTypeNode); - } - - private boolean isFunctionTop(BLangFunctionTypeNode td) { - return td.params.isEmpty() && td.restParam == null && td.returnTypeNode == null; - } - - private SemType resolveRecordTypeDesc(TypeTestContext cx, Map mod, - BLangTypeDefinition defn, int depth, BLangRecordTypeNode td) { - Env env = (Env) cx.getInnerEnv(); - Definition attachedDefinition = attachedDefinitions.get(td); - if (attachedDefinition != null) { - return attachedDefinition.getSemType(env); - } - - MappingDefinition md = new MappingDefinition(); - attachedDefinitions.put(td, md); - - MappingDefinition.Field[] fields = new MappingDefinition.Field[td.fields.size()]; - for (int i = 0; i < td.fields.size(); i++) { - BLangSimpleVariable field = td.fields.get(i); - SemType type = resolveTypeDesc(cx, mod, defn, depth + 1, field.typeNode); - if (Core.isNever(type)) { - throw new IllegalStateException("record field can't be never"); - } - fields[i] = - new MappingDefinition.Field(field.name.value, type, field.flagSet.contains(Flag.READONLY), - field.flagSet.contains(Flag.OPTIONAL)); - } - - SemType rest; - if (!td.isSealed() && td.getRestFieldType() == null) { - rest = Builder.getAnyDataType(); - } else { - rest = resolveTypeDesc(cx, mod, defn, depth + 1, td.getRestFieldType()); - } - if (rest == null) { - rest = Builder.getNeverType(); - } - return md.defineMappingTypeWrapped((Env) cx.getInnerEnv(), fields, rest, CELL_MUT_LIMITED); - } - - private SemType resolveConstrainedTypeDesc(TypeTestContext cx, Map mod, - BLangTypeDefinition defn, int depth, BLangConstrainedType td) { - BLangBuiltInRefTypeNode refTypeNode = (BLangBuiltInRefTypeNode) td.getType(); - return switch (refTypeNode.typeKind) { - case MAP -> resolveMapTypeDesc(cx, mod, defn, depth, td); - case FUTURE -> resolveFutureTypeDesc(cx, mod, defn, depth, td); - case XML -> resolveXmlTypeDesc(cx, mod, defn, depth, td); - case TYPEDESC -> resolveTypedescTypeDesc(cx, mod, defn, depth, td); - default -> throw new UnsupportedOperationException( - "Constrained type not implemented: " + refTypeNode.typeKind); - }; - } - - private SemType resolveTypedescTypeDesc(TypeTestContext cx, Map mod, - BLangTypeDefinition defn, int depth, BLangConstrainedType td) { - SemType constraint = resolveTypeDesc(cx, mod, defn, depth + 1, td.constraint); - return TypedescUtils.typedescContaining((Env) cx.getInnerEnv(), constraint); - } - - private SemType resolveFutureTypeDesc(TypeTestContext cx, Map mod, - BLangTypeDefinition defn, int depth, BLangConstrainedType td) { - SemType constraint = resolveTypeDesc(cx, mod, defn, depth + 1, td.constraint); - return FutureUtils.futureContaining((Env) cx.getInnerEnv(), constraint); - } - - private SemType resolveXmlTypeDesc(TypeTestContext cx, Map mod, - BLangTypeDefinition defn, int depth, BLangConstrainedType td) { - SemType constraint = resolveTypeDesc(cx, mod, defn, depth + 1, td.constraint); - return XmlUtils.xmlSequence(constraint); - } - - private SemType resolveMapTypeDesc(TypeTestContext cx, Map mod, - BLangTypeDefinition defn, int depth, BLangConstrainedType td) { - Env env = (Env) cx.getInnerEnv(); - Definition attachedDefinition = attachedDefinitions.get(td); - if (attachedDefinition != null) { - return attachedDefinition.getSemType(env); - } - - MappingDefinition md = new MappingDefinition(); - attachedDefinitions.put(td, md); - - SemType rest = resolveTypeDesc(cx, mod, defn, depth + 1, td.constraint); - - return md.defineMappingTypeWrapped(env, new MappingDefinition.Field[0], rest, CELL_MUT_LIMITED); - } - - private SemType resolveTupleTypeDesc(TypeTestContext cx, Map mod, - BLangTypeDefinition defn, int depth, BLangTupleTypeNode td) { - Env env = (Env) cx.getInnerEnv(); - Definition attachedDefinition = attachedDefinitions.get(td); - if (attachedDefinition != null) { - return attachedDefinition.getSemType(env); - } - ListDefinition ld = new ListDefinition(); - attachedDefinitions.put(td, ld); - SemType[] memberSemTypes = td.members.stream() - .map(member -> resolveTypeDesc(cx, mod, defn, depth + 1, member.typeNode)) - .toArray(SemType[]::new); - SemType rest = - td.restParamType != null ? resolveTypeDesc(cx, mod, defn, depth + 1, td.restParamType) : - Builder.getNeverType(); - return ld.defineListTypeWrapped(env, memberSemTypes, memberSemTypes.length, rest, CELL_MUT_LIMITED); - } - - private SemType resolveArrayTypeDesc(TypeTestContext cx, Map mod, - BLangTypeDefinition defn, int depth, BLangArrayType td) { - Definition attachedDefinition = attachedDefinitions.get(td); - if (attachedDefinition != null) { - return attachedDefinition.getSemType((Env) cx.getInnerEnv()); - } - - ListDefinition ld = new ListDefinition(); - attachedDefinitions.put(td, ld); - - int dimensions = td.dimensions; - SemType accum = resolveTypeDesc(cx, mod, defn, depth + 1, td.elemtype); - for (int i = 0; i < dimensions; i++) { - int size = from(mod, td.sizes.get(i)); - if (i == dimensions - 1) { - accum = resolveListInner(cx, ld, size, accum); - } else { - accum = resolveListInner(cx, size, accum); - } - } - return accum; - } - - private SemType resolveListInner(TypeTestContext cx, int size, SemType eType) { - ListDefinition ld = new ListDefinition(); - return resolveListInner(cx, ld, size, eType); - } - - private static SemType resolveListInner(TypeTestContext cx, ListDefinition ld, int size, SemType eType) { - Env env = (Env) cx.getInnerEnv(); - if (size != -1) { - SemType[] members = {eType}; - return ld.defineListTypeWrapped(env, members, Math.abs(size), Builder.getNeverType(), CELL_MUT_LIMITED); - } else { - return ld.defineListTypeWrapped(env, EMPTY_SEMTYPE_ARR, 0, eType, CELL_MUT_LIMITED); - } - } - - - private SemType resolveSingletonType(BLangFiniteTypeNode td) { - return td.valueSpace.stream().map(each -> (BLangLiteral) each) - .map(literal -> resolveSingletonType(literal.value, literal.getDeterminedType().getKind()).get()) - .reduce(Builder.getNeverType(), Core::union); - } - - private Optional resolveSingletonType(Object value, TypeKind targetTypeKind) { - return switch (targetTypeKind) { - case NIL -> Optional.of(Builder.getNilType()); - case BOOLEAN -> Optional.of(Builder.getBooleanConst((Boolean) value)); - case INT, BYTE -> { - assert !(value instanceof Byte); - yield Optional.of(Builder.getIntConst(((Number) value).longValue())); - } - case FLOAT -> { - double doubleVal; - if (value instanceof Long longValue) { - doubleVal = longValue.doubleValue(); - } else if (value instanceof Double doubleValue) { - doubleVal = doubleValue; - } else { - // literal value will be a string if it wasn't within the bounds of what is supported by Java Long - // or Double when it was parsed in BLangNodeBuilder. - try { - doubleVal = Double.parseDouble((String) value); - } catch (NumberFormatException e) { - yield Optional.empty(); - } - } - yield Optional.of(Builder.getFloatConst(doubleVal)); - } - case DECIMAL -> { - String repr = (String) value; - if (repr.contains("d") || repr.contains("D")) { - repr = repr.substring(0, repr.length() - 1); - } - yield Optional.of(Builder.getDecimalConst(new BigDecimal(repr))); - } - case STRING -> Optional.of(Builder.getStringConst((String) value)); - case HANDLE -> Optional.of(Builder.getHandleType()); - default -> Optional.empty(); - }; - } - - private SemType resolveTypeDesc(TypeTestContext cx, BLangUnionTypeNode td, Map mod, - int depth, BLangTypeDefinition defn) { - - Iterator iterator = td.memberTypeNodes.iterator(); - SemType res = resolveTypeDesc(cx, mod, defn, depth, iterator.next()); - while (iterator.hasNext()) { - res = Core.union(res, resolveTypeDesc(cx, mod, defn, depth, iterator.next())); - } - return res; - } - - private SemType resolveTypeDesc(TypeTestContext cx, BLangUserDefinedType td, Map mod, - int depth) { - String name = td.typeName.value; - // Need to replace this with a real package lookup - if (td.pkgAlias.value.equals("int")) { - return resolveIntSubtype(name); - } else if (td.pkgAlias.value.equals("string") && name.equals("Char")) { - return Builder.getCharType(); - } else if (td.pkgAlias.value.equals("xml")) { - return resolveXmlSubType(name); - } else if (td.pkgAlias.value.equals("regexp") && name.equals("RegExp")) { - return Builder.getRegexType(); - } - - BLangNode moduleLevelDef = mod.get(name); - if (moduleLevelDef == null) { - throw new IndexOutOfBoundsException("unknown type " + name); - } - - switch (moduleLevelDef.getKind()) { - case TYPE_DEFINITION -> { - SemType ty = resolveTypeDefnRec(cx, mod, (BLangTypeDefinition) moduleLevelDef, depth); - if (td.flagSet.contains(Flag.DISTINCT)) { - return getDistinctSemType(cx, ty); - } - return ty; - } - case CONSTANT -> { - BLangConstant constant = (BLangConstant) moduleLevelDef; - return resolveTypeDefnRec(cx, mod, constant.getAssociatedTypeDefinition(), depth); - } - case VARIABLE -> { - // This happens when the type is a parameter of a dependently typed function - BLangVariable variable = (BLangVariable) moduleLevelDef; - BLangConstrainedType typeDescType = (BLangConstrainedType) variable.getTypeNode(); - return resolveTypeDesc(cx, mod, null, depth, typeDescType.constraint); - } - default -> throw new UnsupportedOperationException("class defns not implemented"); - } - } - - private SemType resolveXmlSubType(String name) { - return switch (name) { - case "Element" -> Builder.getXmlElementType(); - case "Comment" -> Builder.getXmlCommentType(); - case "Text" -> Builder.getXmlTextType(); - case "ProcessingInstruction" -> Builder.getXmlPIType(); - default -> throw new IllegalStateException("Unknown XML subtype: " + name); - }; - } - - private SemType getDistinctSemType(TypeTestContext cx, SemType innerType) { - Env env = (Env) cx.getInnerEnv(); - if (Core.isSubtypeSimple(innerType, Builder.getObjectType())) { - return getDistinctObjectType(env, innerType); - } else if (Core.isSubtypeSimple(innerType, Builder.getErrorType())) { - return getDistinctErrorType(env, innerType); - } - throw new IllegalArgumentException("Distinct type not supported for: " + innerType); - } - - private SemType resolveIntSubtype(String name) { - // TODO: support MAX_VALUE - return switch (name) { - case "Signed8" -> Builder.createIntRange(SIGNED8_MIN_VALUE, SIGNED8_MAX_VALUE); - case "Signed16" -> Builder.createIntRange(SIGNED16_MIN_VALUE, SIGNED16_MAX_VALUE); - case "Signed32" -> Builder.createIntRange(SIGNED32_MIN_VALUE, SIGNED32_MAX_VALUE); - case "Unsigned8" -> Builder.createIntRange(0, UNSIGNED8_MAX_VALUE); - case "Unsigned16" -> Builder.createIntRange(0, UNSIGNED16_MAX_VALUE); - case "Unsigned32" -> Builder.createIntRange(0, UNSIGNED32_MAX_VALUE); - default -> throw new UnsupportedOperationException("Unknown int subtype: " + name); - }; - } - - private SemType resolveTypeDesc(TypeTestContext cx, BLangIntersectionTypeNode td, - Map mod, int depth, BLangTypeDefinition defn) { - Iterator iterator = td.constituentTypeNodes.iterator(); - SemType res = resolveTypeDesc(cx, mod, defn, depth, iterator.next()); - while (iterator.hasNext()) { - res = Core.intersect(res, resolveTypeDesc(cx, mod, defn, depth, iterator.next())); - } - return res; - } - - private SemType resolveTypeDesc(BLangBuiltInRefTypeNode td) { - return switch (td.typeKind) { - case NEVER -> Builder.getNeverType(); - case XML -> Builder.getXmlType(); - case FUTURE -> Builder.getFutureType(); - // TODO: implement json type - - default -> throw new UnsupportedOperationException("Built-in ref type not implemented: " + td.typeKind); - }; - } - - private SemType resolveTypeDesc(TypeTestContext cx, BLangValueType td) { - return switch (td.typeKind) { - case NIL -> Builder.getNilType(); - case BOOLEAN -> Builder.getBooleanType(); - case BYTE -> Builder.createIntRange(0, UNSIGNED8_MAX_VALUE); - case INT -> Builder.getIntType(); - case FLOAT -> Builder.getFloatType(); - case DECIMAL -> Builder.getDecimalType(); - case STRING -> Builder.getStringType(); - case READONLY -> Builder.getReadonlyType(); - case ANY -> Builder.getAnyType(); - case ANYDATA -> Builder.getAnyDataType(); - case ERROR -> Builder.getErrorType(); - case XML -> Builder.getXmlType(); - case HANDLE -> Builder.getHandleType(); - case TYPEDESC -> Builder.getTypeDescType(); - default -> throw new IllegalStateException("Unknown type: " + td); - }; - } - - private SemType evaluateConst(BLangConstant constant) { - return switch (constant.symbol.value.type.getKind()) { - case INT -> Builder.getIntConst((long) constant.symbol.value.value); - case BOOLEAN -> Builder.getBooleanConst((boolean) constant.symbol.value.value); - case STRING -> Builder.getStringConst((String) constant.symbol.value.value); - case FLOAT -> Builder.getFloatConst((double) constant.symbol.value.value); - default -> throw new UnsupportedOperationException("Expression type not implemented for const semtype"); - }; - } - - private void attachToBType(BLangType bType, SemType semType) { - attachedSemType.put(bType, semType); - } -} diff --git a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/RuntimeTypeTestAPI.java b/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/RuntimeTypeTestAPI.java deleted file mode 100644 index cd2d6e0671ae..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/RuntimeTypeTestAPI.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.semtype.port.test; - -import io.ballerina.runtime.api.types.semtype.Builder; -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Core; -import io.ballerina.runtime.api.types.semtype.ListProj; -import io.ballerina.runtime.api.types.semtype.MappingProj; -import io.ballerina.runtime.api.types.semtype.SemType; - -public class RuntimeTypeTestAPI implements TypeTestAPI { - - private static final RuntimeTypeTestAPI INSTANCE = new RuntimeTypeTestAPI(); - - private RuntimeTypeTestAPI() { - } - - public static RuntimeTypeTestAPI getInstance() { - return INSTANCE; - } - - @Override - public boolean isSubtype(TypeTestContext cx, SemType t1, SemType t2) { - return Core.isSubType(from(cx), t1, t2); - } - - private static Context from(TypeTestContext cx) { - return (Context) cx.getInnerContext(); - } - - @Override - public boolean isSubtypeSimple(SemType t1, SemType t2) { - return Core.isSubtypeSimple(t1, t2); - } - - @Override - public boolean isListType(SemType t) { - return Core.isSubtypeSimple(t, Builder.getListType()); - } - - @Override - public boolean isMapType(SemType t) { - return Core.isSubtypeSimple(t, Builder.getMappingType()); - } - - @Override - public SemType intConst(long l) { - return Builder.getIntConst(l); - } - - @Override - public SemType mappingMemberTypeInnerVal(TypeTestContext context, SemType t, SemType key) { - return MappingProj.mappingMemberTypeInnerVal(from(context), t, key); - } - - @Override - public SemType listProj(TypeTestContext context, SemType t, SemType key) { - return ListProj.listProjInnerVal(from(context), t, key); - } - - @Override - public SemType listMemberType(TypeTestContext context, SemType t, SemType key) { - return Core.listMemberTypeInnerVal(from(context), t, key); - } -} diff --git a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/RuntimeTypeTestContext.java b/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/RuntimeTypeTestContext.java deleted file mode 100644 index add06c8db8c5..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/RuntimeTypeTestContext.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.semtype.port.test; - -import io.ballerina.runtime.api.types.semtype.Context; -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.SemType; - -public final class RuntimeTypeTestContext implements TypeTestContext { - - private final TypeTestEnv env; - private final Context cx; - - private RuntimeTypeTestContext(TypeTestEnv env) { - this.env = env; - this.cx = Context.from((Env) env.getInnerEnv()); - } - - public static synchronized RuntimeTypeTestContext from(TypeTestEnv env) { - return new RuntimeTypeTestContext(env); - } - - @Override - public TypeTestEnv getEnv() { - return env; - } - - @Override - public Object getInnerEnv() { - return env.getInnerEnv(); - } - - @Override - public Object getInnerContext() { - return cx; - } -} diff --git a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/RuntimeTypeTestEnv.java b/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/RuntimeTypeTestEnv.java deleted file mode 100644 index 2592d6ba5565..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/RuntimeTypeTestEnv.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.semtype.port.test; - -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.types.semtype.SemType; - -import java.util.HashMap; -import java.util.Map; - -class RuntimeTypeTestEnv implements TypeTestEnv { - - private final Map typeMap = new HashMap<>(); - private final Env env; - - private RuntimeTypeTestEnv(Env env) { - this.env = env; - } - - public static synchronized RuntimeTypeTestEnv from(Env env) { - return new RuntimeTypeTestEnv(env); - } - - @Override - public Map getTypeNameSemTypeMap() { - return typeMap; - } - - @Override - public void addTypeDef(String value, SemType semtype) { - typeMap.put(value, semtype); - } - - @Override - public Object getInnerEnv() { - return env; - } -} diff --git a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/SemTypeAssertionTransformer.java b/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/SemTypeAssertionTransformer.java deleted file mode 100644 index b43a4fa84f33..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/SemTypeAssertionTransformer.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.semtype.port.test; - -import io.ballerina.compiler.syntax.tree.Minutiae; -import io.ballerina.compiler.syntax.tree.MinutiaeList; -import io.ballerina.compiler.syntax.tree.ModuleMemberDeclarationNode; -import io.ballerina.compiler.syntax.tree.ModulePartNode; -import io.ballerina.compiler.syntax.tree.Node; -import io.ballerina.compiler.syntax.tree.NodeVisitor; -import io.ballerina.compiler.syntax.tree.SyntaxKind; -import io.ballerina.compiler.syntax.tree.SyntaxTree; -import io.ballerina.compiler.syntax.tree.Token; -import org.testng.Assert; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Map; - -/** - * Extract semtype assertions in the below form. - * @param which semtype (runtime or compiler) used in the assertions. - * // @type A < B - * // @type B = C - * // @type c <> D - * @param Actual semtype definition on which assertion is defined on (runtime or compile time) - * @since 3.0.0 - */ -public final class SemTypeAssertionTransformer extends NodeVisitor { - - private final String fileName; - private final SyntaxTree syntaxTree; - private final TypeTestEnv semtypeEnv; - private final TypeTestContext context; - private final List list; - private final TypeTestAPI semtypeAPI; - - private SemTypeAssertionTransformer(String fileName, SyntaxTree syntaxTree, TypeTestEnv semtypeEnv, - TypeTestContext context, TypeTestAPI semtypeAPI) { - this.fileName = fileName; - this.syntaxTree = syntaxTree; - this.semtypeEnv = semtypeEnv; - this.context = context; - list = new ArrayList<>(); - this.semtypeAPI = semtypeAPI; - } - - public static List> getTypeAssertionsFrom(String fileName, - SyntaxTree syntaxTree, - TypeTestEnv semtypeEnv, - TypeTestContext context, - TypeTestAPI api) { - final SemTypeAssertionTransformer t = - new SemTypeAssertionTransformer<>(fileName, syntaxTree, semtypeEnv, context, api); - return t.getTypeAssertions(); - } - - private List> getTypeAssertions() { - syntaxTree.rootNode().accept(this); - List> assertions = new ArrayList<>(); - for (String str : list) { - String[] parts = splitAssertion(str); - if (parts == null) { - continue; - } - SemType lhs = toSemType(parts[0]); - RelKind kind = RelKind.fromString(parts[1], str); - SemType rhs = toSemType(parts[2]); - String text = parts[0] + " " + parts[1] + " " + parts[2]; - assertions.add(new TypeAssertion<>(this.context, this.fileName, lhs, rhs, kind, text)); - } - return assertions; - } - - private SemType toSemType(String typeExpr) { - // Simple type reference - int leftBracketPos = typeExpr.indexOf('['); - final Map typeNameSemTypeMap = semtypeEnv.getTypeNameSemTypeMap(); - if (leftBracketPos == -1) { - SemType referredType = typeNameSemTypeMap.get(typeExpr); - if (referredType == null) { - throw new IllegalArgumentException("No such type: " + typeExpr); - } - return referredType; - } - int rightBracketPos = typeExpr.indexOf(']'); - String typeRef = typeExpr.substring(0, leftBracketPos); - String memberAccessExpr = typeExpr.substring(leftBracketPos + 1, rightBracketPos); - - SemType type = typeNameSemTypeMap.get(typeRef); - if (semtypeAPI.isListType(type)) { - SemType m; - try { - long l = Long.parseLong(memberAccessExpr); - m = semtypeAPI.intConst(l); - } catch (Exception e) { - // parsing number failed, access must be a type-reference - m = typeNameSemTypeMap.get(memberAccessExpr); - } - return listProj(context, type, m); - } else if (semtypeAPI.isMapType(type)) { - SemType m = typeNameSemTypeMap.get(memberAccessExpr); - return semtypeAPI.mappingMemberTypeInnerVal(context, type, m); - } - throw new IllegalStateException("Unsupported type test: " + typeExpr); - } - - private SemType listProj(TypeTestContext context, SemType t, SemType m) { - SemType s1 = semtypeAPI.listProj(context, t, m); - SemType s2 = semtypeAPI.listMemberType(context, t, m); - if (!semtypeAPI.isSubtype(context, s1, s2)) { - Assert.fail("listProj result is not a subtype of listMemberType"); - } - return s1; - } - - private String[] splitAssertion(String str) { - if (ignoredCommentSet().contains(str)) { - return null; - } - String[] parts = str.split(" "); - - if (parts[1].equals("-@type")) { - // TODO: remove this check once diff operator is supported - return null; - } - - // Only accept the form: `//` `@type` T1 REL T2 - if (!parts[1].equals("@type") || parts.length != 5) { - throw new IllegalStateException("Invalid type assertion '" + str + - "', expected in form: '// @type T1 REL T2'"); - } - return Arrays.copyOfRange(parts, 2, 5); - } - - /** - * Returns a set of comments that are to be ignored during the processing. - * These comments include non-essential information or comments that do not conform to the expected format. - * - * @return Set of comments to be ignored. - */ - public final HashSet ignoredCommentSet() { - HashSet hashSet = new HashSet<>(); - hashSet.add("// the order of type defns are intentional"); - return hashSet; - } - - @Override - protected void visitSyntaxNode(Node node) { - addComments(node.leadingMinutiae()); - addComments(node.trailingMinutiae()); - } - - @Override - public void visit(Token token) { - addComments(token.leadingMinutiae()); - addComments(token.trailingMinutiae()); - } - - private void addComments(MinutiaeList minutiaes) { - for (Minutiae minutiae : minutiaes) { - if (minutiae.kind() == SyntaxKind.COMMENT_MINUTIAE) { - String text = minutiae.text(); - if (text.length() > 2) { - list.add(text); - } - } - } - } - - @Override - public void visit(ModulePartNode modulePartNode) { - for (ModuleMemberDeclarationNode member : modulePartNode.members()) { - member.accept(this); - } - modulePartNode.eofToken().accept(this); - } - - /** - * Relationship to be asserted. - * - * @since 3.0.0 - */ - public enum RelKind { - SUB, SAME, NON; - - static RelKind fromString(String rel, String assertion) { - switch (rel) { - case "<": - return SUB; - case "=": - return SAME; - case "<>": - return NON; - default: - throw new AssertionError("Unknown type relationship in assertion: " + rel + "in: " + assertion); - } - } - } -} diff --git a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/SemTypeResolver.java b/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/SemTypeResolver.java deleted file mode 100644 index 288983862e21..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/SemTypeResolver.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.semtype.port.test; - -import org.ballerinalang.model.tree.NodeKind; -import org.wso2.ballerinalang.compiler.tree.BLangNode; -import org.wso2.ballerinalang.compiler.tree.BLangTypeDefinition; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangSimpleVarRef; - -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import static org.wso2.ballerinalang.compiler.semantics.analyzer.SymbolEnter.getTypeOrClassName; - -/** - * Abstract implementation of a type resolver that can be used for type tests. - * - * @param SemType implementation used - * @since 2201.11.0 - */ -public abstract class SemTypeResolver { - - protected static int from(Map mod, BLangNode expr) { - if (expr instanceof BLangLiteral literal) { - return SemTypeResolver.listSize((Number) literal.value); - } else if (expr instanceof BLangSimpleVarRef varRef) { - String varName = varRef.variableName.value; - return SemTypeResolver.from(mod, mod.get(varName)); - } else if (expr instanceof BLangConstant constant) { - return SemTypeResolver.listSize((Number) constant.symbol.value.value); - } - throw new UnsupportedOperationException("Unsupported expr kind " + expr.getKind()); - } - - private static int listSize(Number size) { - if (size.longValue() > Integer.MAX_VALUE) { - throw new IllegalArgumentException("list sizes greater than " + Integer.MAX_VALUE + " not yet supported"); - } - return size.intValue(); - } - - public void defineSemTypes(List moduleDefs, TypeTestContext cx) { - Map modTable = new LinkedHashMap<>(); - for (BLangNode typeAndClassDef : moduleDefs) { - modTable.put(getTypeOrClassName(typeAndClassDef), typeAndClassDef); - } - modTable = Collections.unmodifiableMap(modTable); - - for (BLangNode def : moduleDefs) { - if (def.getKind() == NodeKind.CLASS_DEFN) { - throw new UnsupportedOperationException("Semtype are not supported for class definitions yet"); - } else if (def.getKind() == NodeKind.CONSTANT) { - resolveConstant(cx, modTable, (BLangConstant) def); - } else { - BLangTypeDefinition typeDefinition = (BLangTypeDefinition) def; - resolveTypeDefn(cx, modTable, typeDefinition); - } - } - } - - protected abstract void resolveConstant(TypeTestContext cx, - Map modTable, BLangConstant constant); - - protected abstract void resolveTypeDefn(TypeTestContext cx, - Map mod, BLangTypeDefinition defn); -} diff --git a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/SemTypeTest.java b/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/SemTypeTest.java deleted file mode 100644 index 9ee71aaffbc9..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/SemTypeTest.java +++ /dev/null @@ -1,441 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.semtype.port.test; - -import io.ballerina.runtime.api.types.semtype.Env; -import io.ballerina.runtime.api.utils.StringUtils; -import io.ballerina.runtime.internal.utils.ValueComparisonUtils; -import io.ballerina.tools.diagnostics.Diagnostic; -import io.ballerina.tools.diagnostics.DiagnosticSeverity; -import io.ballerina.types.Context; -import io.ballerina.types.SemType; -import io.ballerina.types.SemTypes; -import org.ballerinalang.test.BCompileUtil; -import org.jetbrains.annotations.NotNull; -import org.testng.Assert; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import org.wso2.ballerinalang.compiler.semantics.model.Scope; -import org.wso2.ballerinalang.compiler.tree.BLangNode; -import org.wso2.ballerinalang.compiler.tree.BLangPackage; -import org.wso2.ballerinalang.compiler.util.Name; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.StringJoiner; -import java.util.function.Predicate; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * Test semtypes using compiler front-end for parsing. - * - * @since 2201.10.0 - */ -public class SemTypeTest { - - @DataProvider(name = "dataDirFileNameProvider") - public Object[] dataDirFileNameProvider() { - File dataDir = resolvePath("test-src/data").toFile(); - List testFiles = Arrays.stream(dataDir.listFiles()) - .map(File::getAbsolutePath) - .filter(name -> name.endsWith(".bal") && - !dataDirSkipList().contains(name.substring(name.lastIndexOf(File.separator) + 1))) - .collect(Collectors.toList()); - - include(testFiles, - "test-src/simple-type/float-altered.bal", - "test-src/simple-type/function-altered.bal", - "test-src/simple-type/int-singleton-altered.bal", - "test-src/simple-type/list-type-test.bal", - "test-src/simple-type/map-type-test.bal", - "test-src/simple-type/type-test.bal" - ); - - return testFiles.toArray(String[]::new); - //return new Object[]{"test-src/data/error2.bal"}; - } - - public final HashSet dataDirSkipList() { - HashSet hashSet = new HashSet<>(); - return hashSet; - } - - @DataProvider(name = "fileNameProviderFunc") - public Object[] fileNameProviderFunc() { - File dataDir = resolvePath("test-src/localVar").toFile(); - List testFiles = Arrays.stream(dataDir.listFiles()) - .map(File::getAbsolutePath) - .filter(name -> name.endsWith(".bal")) - .toList(); - - return testFiles.toArray(new String[0]); - } - - @DataProvider(name = "type-rel-provider") - public Object[] typeRelTestFileNameProvider() { - File dataDir = resolvePath("test-src/type-rel").toFile(); - List balFiles = new ArrayList<>(); - listAllBalFiles(dataDir, balFiles); - Collections.sort(balFiles); - - Collection> tests = new ArrayList<>(); - for (File file : balFiles) { - TypeCheckData utils = compilerTypeResolverUtilsFromFile(file); - List> assertions = - getTypeAssertions(file, utils.resolver(), utils.context(), utils.env(), - CompilerTypeTestAPI.getInstance(), utils.pair()); - tests.addAll(assertions); - } - return tests.toArray(); - } - - @NotNull - private static List> getTypeAssertions(File file, - SemTypeResolver typeResolver, - TypeTestContext typeCheckContext, - TypeTestEnv typeTestEnv, - TypeTestAPI api, - BCompileUtil.PackageSyntaxTreePair pair) { - String fileName = file.getAbsolutePath(); - BLangPackage pkgNode = pair.bLangPackage; - - List typeAndClassDefs = new ArrayList<>(); - typeAndClassDefs.addAll(pkgNode.constants); - typeAndClassDefs.addAll(pkgNode.typeDefinitions); - - try { - typeResolver.defineSemTypes(typeAndClassDefs, typeCheckContext); - return SemTypeAssertionTransformer.getTypeAssertionsFrom(fileName, pair.syntaxTree, typeTestEnv, - typeCheckContext, api); - } catch (Exception e) { - return List.of(new TypeAssertion<>( - null, fileName, null, null, null, e.getMessage() - )); - } - } - - public void listAllBalFiles(File file, List balFiles) { - if (file.isFile()) { - return; - } - for (File f : file.listFiles()) { - if (f.isDirectory()) { - listAllBalFiles(f, balFiles); - } - String fileName = f.getName(); - if (fileName.endsWith(".bal") && !typeRelDirSkipList().contains(fileName)) { - balFiles.add(f); - } - } - } - - public final HashSet typeRelDirSkipList() { - HashSet hashSet = new HashSet<>(); - // intersection with negative (!) atom - hashSet.add("proj7-tv.bal"); - hashSet.add("proj8-tv.bal"); - hashSet.add("proj9-tv.bal"); - hashSet.add("proj10-tv.bal"); - - // Not a type test. This is an error test - hashSet.add("xml-te.bal"); - return hashSet; - } - - private void include(List testFiles, String... fileNames) { - for (int i = 0; i < fileNames.length; i++) { - testFiles.add(i, fileNames[i]); - } - } - - @Test(dataProvider = "dataDirFileNameProvider") - public void verifyAllSubtypeRelationships(String fileName) { - List subtypeRels = getSubtypeRels(fileName); - List expectedRels = extractSubtypeRelations(fileName); - // Commented code will get expected content for this test to pass. - // Useful for taking a diff. - // String text = toText(subtypeRels); - Assert.assertEquals(subtypeRels, expectedRels); - } - - @Test(dataProvider = "fileNameProviderFunc") - public void funcTest(String fileName) { - BCompileUtil.PackageSyntaxTreePair packageSyntaxTreePair = BCompileUtil.compileSemType(fileName); - BLangPackage bLangPackage = packageSyntaxTreePair.bLangPackage; - ensureNoErrors(bLangPackage); - List vars = extractVarTypes(fileName); - Context tc = Context.from(bLangPackage.semtypeEnv); - Scope globalScope = bLangPackage.symbol.scope; - bLangPackage.functions.forEach(func -> { - Scope scope = func.getBody().scope; - vars.forEach(v -> { - if (v.length != 2) { - Assert.fail("test structure should be `variable = Type`"); - } - SemType t1 = scope.lookup(new Name(v[0])).symbol.type.semType(); - SemType t2 = globalScope.lookup(new Name(v[1])).symbol.type.semType(); - - String msg = "semtype in local scope is different from global scope"; - Assert.assertTrue(SemTypes.isSubtype(tc, t1, t2), msg); - Assert.assertTrue(SemTypes.isSubtype(tc, t2, t1), msg); - }); - }); - } - - @Test(expectedExceptions = AssertionError.class) - public void shouldFailForIncorrectTestStructure() { - File wrongAssertionFile = resolvePath("test-src/type-rel-wrong.bal").toFile(); - TypeCheckData utils = compilerTypeResolverUtilsFromFile(wrongAssertionFile); - List> typeAssertions = getTypeAssertions(wrongAssertionFile, - utils.resolver(), utils.context(), utils.env(), CompilerTypeTestAPI.getInstance(), utils.pair() - ); - testSemTypeAssertions(typeAssertions.get(0)); - } - - @DataProvider(name = "runtimeFileNameProviderFunc") - public Object[] runtimeFileNameProviderFunc() { - File dataDir = resolvePath("test-src/type-rel").toFile(); - List balFiles = new ArrayList<>(); - listAllBalFiles(dataDir, balFiles); - Collections.sort(balFiles); - return balFiles.stream() - .map(File::getAbsolutePath).toArray(); - } - - private static Predicate createRuntimeFileNameFilter(Set skipList) { - return file -> file.getName().endsWith(".bal") && !skipList.contains(file.getName()); - } - - @Test(dataProvider = "runtimeFileNameProviderFunc") - public void testRuntimeSemTypes(String fileName) { - File file = resolvePath(fileName).toFile(); - var utils = runtimeTypeResolverUtilsFromFile(file); - RuntimeTypeTestAPI api = RuntimeTypeTestAPI.getInstance(); - getTypeAssertions(file, - utils.resolver(), utils.context(), utils.env(), api, utils.pair()) - .forEach(a -> testAssertion(a, api)); - } - - private static TypeCheckData compilerTypeResolverUtilsFromFile(File file) { - String fileName = file.getAbsolutePath(); - BCompileUtil.PackageSyntaxTreePair pair = BCompileUtil.compileSemType(fileName); - BLangPackage pkgNode = pair.bLangPackage; - TypeTestContext context = ComplierTypeTestContext.from(Context.from(pkgNode.semtypeEnv)); - TypeTestEnv env = CompilerTypeTestEnv.from(pkgNode.semtypeEnv); - SemTypeResolver resolver = new CompilerSemTypeResolver(); - return new TypeCheckData<>(pair, context, env, resolver); - } - - private static TypeCheckData runtimeTypeResolverUtilsFromFile( - File file) { - String fileName = file.getAbsolutePath(); - BCompileUtil.PackageSyntaxTreePair pair = BCompileUtil.compileSemType(fileName); - TypeTestEnv env = RuntimeTypeTestEnv.from(Env.getInstance()); - TypeTestContext context = RuntimeTypeTestContext.from(env); - SemTypeResolver resolver = new RuntimeSemTypeResolver(); - return new TypeCheckData<>(pair, context, env, resolver); - } - - private record TypeCheckData(BCompileUtil.PackageSyntaxTreePair pair, TypeTestContext context, - TypeTestEnv env, SemTypeResolver resolver) { - - } - - @Test(expectedExceptions = AssertionError.class) - public void shouldFailForTooLargeLists() { - File wrongAssertionFile = resolvePath("test-src/fixed-length-array-too-large-te.bal").toFile(); - TypeCheckData utils = compilerTypeResolverUtilsFromFile(wrongAssertionFile); - List> typeAssertions = getTypeAssertions(wrongAssertionFile, - utils.resolver(), utils.context(), utils.env(), CompilerTypeTestAPI.getInstance(), utils.pair() - ); - testSemTypeAssertions(typeAssertions.get(0)); - } - - @Test(dataProvider = "type-rel-provider") - public void testSemTypeAssertions(TypeAssertion typeAssertion) { - if (typeAssertion.kind() == null) { - Assert.fail( - "Exception thrown in " + typeAssertion.fileName() + System.lineSeparator() + typeAssertion.text()); - } - testAssertion(typeAssertion, CompilerTypeTestAPI.getInstance()); - } - - private void testAssertion(TypeAssertion typeAssertion, - TypeTestAPI semTypes) { - switch (typeAssertion.kind()) { - case NON: - Assert.assertFalse( - semTypes.isSubtype(typeAssertion.context(), typeAssertion.lhs(), typeAssertion.rhs()), - formatFailingAssertionDescription(typeAssertion)); - Assert.assertFalse( - semTypes.isSubtype(typeAssertion.context(), typeAssertion.rhs(), typeAssertion.lhs()), - formatFailingAssertionDescription(typeAssertion)); - break; - case SUB: - Assert.assertTrue(semTypes.isSubtype(typeAssertion.context(), typeAssertion.lhs(), typeAssertion.rhs()), - formatFailingAssertionDescription(typeAssertion)); - Assert.assertFalse( - semTypes.isSubtype(typeAssertion.context(), typeAssertion.rhs(), typeAssertion.lhs()), - formatFailingAssertionDescription(typeAssertion)); - break; - case SAME: - Assert.assertTrue(semTypes.isSubtype(typeAssertion.context(), typeAssertion.lhs(), typeAssertion.rhs()), - formatFailingAssertionDescription(typeAssertion)); - Assert.assertTrue(semTypes.isSubtype(typeAssertion.context(), typeAssertion.rhs(), typeAssertion.lhs()), - formatFailingAssertionDescription(typeAssertion)); - } - } - - @NotNull - private String formatFailingAssertionDescription(TypeAssertion typeAssertion) { - return typeAssertion.text() + "\n in: " + typeAssertion.fileName(); - } - - - private String toText(List expectedRels) { - StringJoiner joiner = new StringJoiner("\n// ", "// ", ""); - for (String rel : expectedRels) { - joiner.add(rel); - } - return joiner.toString(); - } - - private List getSubtypeRels(String sourceFilePath) { - BLangPackage pkgNode = BCompileUtil.compileSemType(sourceFilePath).bLangPackage; - // xxxx-e.bal pattern is used to test bal files where jBallerina type checking doesn't support type operations - // such as intersection. Make sure not to use nBallerina type negation (!) with this as jBallerina compiler - // front end doesn't generate AST from those. - if (!sourceFilePath.endsWith("-e.bal")) { - ensureNoErrors(pkgNode); - } - - List typeAndClassDefs = new ArrayList<>(); - typeAndClassDefs.addAll(pkgNode.constants); - typeAndClassDefs.addAll(pkgNode.typeDefinitions); - - SemTypeResolver typeResolver = new CompilerSemTypeResolver(); - TypeTestContext typeCheckContext = - ComplierTypeTestContext.from(Context.from(pkgNode.semtypeEnv)); - typeResolver.defineSemTypes(typeAndClassDefs, typeCheckContext); - Map typeMap = pkgNode.semtypeEnv.getTypeNameSemTypeMap(); - TypeTestAPI api = CompilerTypeTestAPI.getInstance(); - List subtypeRelations = new ArrayList<>(); - List typeNameList = typeMap.keySet().stream() - .filter(n -> !n.startsWith("$anon")) - .sorted(SemTypeTest::ballerinaStringCompare) - .toList(); - int size = typeNameList.size(); - for (int i = 0; i < size; i++) { - for (int j = i + 1; j < size; j++) { - String name1 = typeNameList.get(i); - String name2 = typeNameList.get(j); - - SemType t1 = typeMap.get(name1); - SemType t2 = typeMap.get(name2); - if (api.isSubtype(typeCheckContext, t1, t2)) { - subtypeRelations.add(TypeRel.rel(name1, name2)); - } - if (api.isSubtype(typeCheckContext, t2, t1)) { - subtypeRelations.add(TypeRel.rel(name2, name1)); - } - } - } - - return subtypeRelations.stream() - .map(TypeRel::toString) - .sorted(SemTypeTest::ballerinaStringCompare) - .collect(Collectors.toList()); - } - - private void ensureNoErrors(BLangPackage bLangPackage) { - List errors = bLangPackage.getDiagnostics().stream() - .filter(d -> d.diagnosticInfo().severity() == DiagnosticSeverity.ERROR) - .toList(); - if (!errors.isEmpty()) { - Assert.fail(errors.stream() - .map(Diagnostic::toString) - .reduce("", (a, b) -> a + "\n" + b)); - } - } - - private static int ballerinaStringCompare(String o1, String o2) { - return ValueComparisonUtils.compareValues(StringUtils.fromString(o1), StringUtils.fromString(o2), ""); - } - - List extractSubtypeRelations(String fileName) { - try { - Path path = resolvePath(fileName); - Stream lines = Files.lines(Path.of(path.toString())); - return lines.filter(s -> s.startsWith("// ") && s.contains("<:")) - .map(s -> s.substring(3).strip()) - .sorted() - .collect(Collectors.toList()); - } catch (IOException e) { - Assert.fail(e.toString()); - } - return null; - } - - List extractVarTypes(String fileName) { - try { - Path path = resolvePath(fileName); - Stream lines = Files.lines(Path.of(path.toString())); - return lines.filter(s -> s.startsWith("// ")) - .map(s -> s.substring(3).replaceAll("\\s", "").split("=")) - .collect(Collectors.toList()); - } catch (IOException e) { - Assert.fail(e.toString()); - } - return null; - } - - private Path resolvePath(String fileName) { - return Paths.get("src/test/resources").resolve(fileName); - } - - /** - * Represent subtype relationship. - * - * @param subType subtype name - * @param superType super type name - * @since 2201.10.0 - */ - private record TypeRel(String subType, String superType) { - - public static TypeRel rel(String sub, String sup) { - return new TypeRel(sub, sup); - } - - @Override - public String toString() { - return subType + "<:" + superType; - } - } -} diff --git a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/TypeAssertion.java b/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/TypeAssertion.java deleted file mode 100644 index e4452711b6c1..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/TypeAssertion.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.semtype.port.test; - -import java.nio.file.Paths; - -/** - * Subtype test. - * - * @param Which semtype (runtime or compiler) is used for type assertion. - * @param context Type context under which {@code SemTypes} were defined. - * @param fileName Name of the file in which types were defined in. - * @param lhs Resolved {@code SemType} for the Left-hand side of the subtype test. - * @param rhs Resolved {@code SemType} for the Right-hand side of the subtype test. - * @param kind Relationship between the two types. - * @param text Text that will be shown in case of assertion failure. - * @since 3.0.0 - */ -public record TypeAssertion(TypeTestContext context, String fileName, SemType lhs, SemType rhs, - SemTypeAssertionTransformer.RelKind kind, String text) { - - public TypeAssertion { - if (kind != null) { - assert lhs != null; - assert rhs != null; - } - } - - @Override - public String toString() { - return Paths.get(fileName).getFileName().toString() + ": " + text; - } -} diff --git a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/TypeTestAPI.java b/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/TypeTestAPI.java deleted file mode 100644 index 60dc1190abfb..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/java/io/ballerina/semtype/port/test/TypeTestAPI.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package io.ballerina.semtype.port.test; - -public interface TypeTestAPI { - - boolean isSubtype(TypeTestContext cx, SemType t1, SemType t2); - - boolean isSubtypeSimple(SemType t1, SemType t2); - - boolean isListType(SemType t); - - boolean isMapType(SemType t); - - SemType intConst(long l); - - SemType mappingMemberTypeInnerVal(TypeTestContext context, SemType type, SemType m); - - SemType listProj(TypeTestContext context, SemType t, SemType key); - - SemType listMemberType(TypeTestContext context, SemType t, SemType key); -} diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/README.md b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/README.md deleted file mode 100644 index 1a832baa8cd3..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/README.md +++ /dev/null @@ -1,6 +0,0 @@ -Note: -===== -`-e.bal` files in this test folder does not mean what it means in nBallerina repo. In this folder it means the -tests should run even though jBallerina compiler frontend emit errors. -This was necessary as jBallerina emit errors for some valid type constructs such as empty tuple. -We need to make sure that type negation operator (!) is not used in these `-e.bal` tests. \ No newline at end of file diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/anydata.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/anydata.bal deleted file mode 100644 index d80f571250bb..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/anydata.bal +++ /dev/null @@ -1,8 +0,0 @@ -import ballerina/lang.regexp; - -// DataType<:Anydata -// Anydata<:DataType - -type Anydata anydata; - -type DataType ()|boolean|int|float|decimal|string|xml|regexp:RegExp|DataType[]|map|table>; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/basic.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/basic.bal deleted file mode 100644 index 147ee10e2db9..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/basic.bal +++ /dev/null @@ -1,19 +0,0 @@ -// Boolean<:Any -// Decimal<:Any -// Float<:Any -// Handle<:Any -// Int<:Any -// Nil<:Any -// String<:Any -type Nil (); -type String string; -type Boolean boolean; -type Int int; -type Float float; -type Decimal decimal; -type Error error; -type Handle handle; -type Any any; - - - diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/bdddiff1.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/bdddiff1.bal deleted file mode 100644 index 48ee7543c899..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/bdddiff1.bal +++ /dev/null @@ -1,9 +0,0 @@ -// IA<:INA -// IA<:U - -// INA<:U -// U<:INA - -type INA int?[]; -type IA int[]; -type U IA|INA; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/boolean-subtype.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/boolean-subtype.bal deleted file mode 100644 index 438c2f94a61b..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/boolean-subtype.bal +++ /dev/null @@ -1,10 +0,0 @@ -// B<:TF -// F<:B -// F<:TF -// T<:B -// T<:TF -// TF<:B -type T true; -type F false; -type TF true|false; -type B boolean; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/contextual.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/contextual.bal deleted file mode 100644 index 7782b2311a75..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/contextual.bal +++ /dev/null @@ -1,14 +0,0 @@ -// F<:F_TY -// F_TY<:F -// I<:I_TY -// I<:ZERO_OR_ONE -// I_TY<:I -// I_TY<:ZERO_OR_ONE - -const int I_TY = 1; -const float F_TY = 1; - -const I = 1; -const F = 1f; - -type ZERO_OR_ONE 0|1; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/decimal-singleton.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/decimal-singleton.bal deleted file mode 100644 index 9ca8da408cbe..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/decimal-singleton.bal +++ /dev/null @@ -1,18 +0,0 @@ -// Zero<:DECIMAL -// One<:DECIMAL -// Minus<:DECIMAL -// ZO<:DECIMAL -// ZOM<:DECIMAL -// ZO<:ZOM -// Zero<:ZO -// One<:ZO -// Zero<:ZOM -// One<:ZOM -// Minus<:ZOM - -type Zero 0d; -type One 1d; -type Minus -1d; -type ZO Zero|One; -type ZOM Zero|One|Minus; -type DECIMAL decimal; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/decimal-singleton2.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/decimal-singleton2.bal deleted file mode 100644 index a80c04032552..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/decimal-singleton2.bal +++ /dev/null @@ -1,14 +0,0 @@ -// Zero<:DECIMAL -// MinusZero<:DECIMAL -// One<:DECIMAL -// FpOne<:DECIMAL -// Zero<:MinusZero -// MinusZero<:Zero -// One<:FpOne -// FpOne<:One - -type Zero 0d; -type MinusZero -0d; -type One 1d; -type FpOne 1.0d; -type DECIMAL decimal; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/distinct-error.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/distinct-error.bal deleted file mode 100644 index aa40d551a92f..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/distinct-error.bal +++ /dev/null @@ -1,21 +0,0 @@ -// E1<:E -// E2<:E -// E2<:E4 -// E3<:E -// E3<:E1 -// E3<:E2 -// E3<:E4 -// E4<:E -// E4<:E2 - -type E error; - -type E1 distinct error; - -type E2 error; - -type E3 E1 & E2; - -type E4 error; - -type R1 record {}; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/error1.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/error1.bal deleted file mode 100644 index 5ae9ffb96d91..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/error1.bal +++ /dev/null @@ -1,9 +0,0 @@ -// EL<:E -// ER1<:E -// ER1<:ER2 -// ER2<:E -// ER2<:ER1 -type EL error; -type ER1 error; -type ER2 error; -type E error; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/error2.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/error2.bal deleted file mode 100644 index 3cd76b901d0c..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/error2.bal +++ /dev/null @@ -1,14 +0,0 @@ -// E<:Cloneable -// E<:EM -// E<:ER -// EM<:Cloneable -// EM<:E -// EM<:ER -// ER<:Cloneable -// ER<:E -// ER<:EM -type E error; -type ER error>; -type Cloneable readonly|xml|Cloneable[]|map; -type EM error>; - diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/fixed-length-array-2-2-e.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/fixed-length-array-2-2-e.bal deleted file mode 100644 index 54d71b2f1e78..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/fixed-length-array-2-2-e.bal +++ /dev/null @@ -1,15 +0,0 @@ -// EMPTY<:ALL -// EMPTY<:IntArray -// IS1<:ALL -// IS2<:ALL -// IS3<:ALL -// IntArray<:ALL - -type IntArray int[]; -type IS int|string; -type EMPTY []; -type IS1 IS[1]; -type IS2 IS[2]; -type IS3 IS[3]; - -type ALL EMPTY|IS1|IS2|IS3|[IS, IS, IS, IS, IS...]; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/fixed-length-array-2-3-e.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/fixed-length-array-2-3-e.bal deleted file mode 100644 index 3a468cf411e8..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/fixed-length-array-2-3-e.bal +++ /dev/null @@ -1,42 +0,0 @@ -// EMPTY<:ISArray -// EMPTY<:U -// EMPTY<:V -// EMPTY<:W -// EMPTY<:X -// EMPTY<:Y -// EMPTY<:Z -// ISArray<:U -// ISArray<:V -// ISArray<:W -// ISArray<:X -// ISArray<:Y -// ISArray<:Z -// X<:Y -// X<:Z -// Y<:X -// Y<:Z -// Z<:X -// Z<:Y - - -type IS int|string; -type EMPTY []; -type ISArray IS[]; - -// @type ISArray < U -type U EMPTY|[IS|float, IS...]; - -// @type ISArray < V -type V EMPTY|[IS]|[IS, IS|float, IS...]; - -// @type ISArray < W -type W EMPTY|[IS]|[IS, IS|float]|[IS, IS, IS|float, IS...]; - -// @type ISArray < X -type X EMPTY|[IS]|[IS, IS|float]|[IS, IS, IS|float]|[IS, IS, IS, IS|float, IS...]; - -// @type ISArray < Y -type Y EMPTY|[IS, IS, IS, IS|float, IS...]|[IS, IS, IS|float]|[IS, IS|float]|[IS]; - -// @type ISArray < Z -type Z [IS, IS, IS, IS|float, IS...]|[IS, IS, IS|float]|[IS, IS|float]|[IS]|EMPTY; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/fixed-length-array-2-4-e.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/fixed-length-array-2-4-e.bal deleted file mode 100644 index 02c4649d8958..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/fixed-length-array-2-4-e.bal +++ /dev/null @@ -1,44 +0,0 @@ -// EMPTY<:IntArray -// EMPTY<:P -// EMPTY<:Q -// EMPTY<:R -// EMPTY<:S -// EMPTY<:T -// EMPTY<:T1 -// IntArray<:P -// IntArray<:Q -// IntArray<:R -// IntArray<:S -// IntArray<:T -// IntArray<:T1 -// P<:Q -// P<:T -// P<:T1 -// R<:Q -// S<:Q -// S<:R -// S<:T1 -// T1<:Q -// T<:Q - -type IntArray int[]; -type IS int|string; -type EMPTY []; - -// @type IntArray < P -type P EMPTY|[int]|[IS, int]|[IS, IS, IS, IS...]; - -// @type IntArray < Q -type Q EMPTY|[int]|[IS, IS]|[IS, IS, IS|float, IS...]; - -// @type IntArray < R -type R EMPTY|[int]|[IS, IS]|[int, int, IS|float, IS...]; - -// @type IntArray < S -type S EMPTY|[int]|[IS, IS]|[int, int, int, IS...]; - -// @type IntArray < T -type T EMPTY|[int]|[IS, int]|[IS, IS, IS|float, IS...]; - -// @type IntArray < T1 -type T1 EMPTY|[int]|[IS, IS, string...]|[IS, IS, IS, IS...]; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/fixed-length-array-2.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/fixed-length-array-2.bal deleted file mode 100644 index 8cf15c770a8f..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/fixed-length-array-2.bal +++ /dev/null @@ -1,17 +0,0 @@ -// LargeArray<:IntArray -// LargeArray2<:IntArray - -public const int MAX_VALUE = 2147483637; -public const int MAX_VALUE_M_1 = 2147483636; - -type IntArray int[]; - -// @type LargeArray < IntArray -type LargeArray int[MAX_VALUE]; - -// @type LargeArray2 < IntArray -// @type LargeArray <> LargeArray2 -type LargeArray2 int[MAX_VALUE_M_1]; - -// @type Int5Intersection = Int5 -//type Int5Intersection int[5] & !LargeArray; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/fixed-length-array-tuple.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/fixed-length-array-tuple.bal deleted file mode 100644 index df4bd385f125..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/fixed-length-array-tuple.bal +++ /dev/null @@ -1,23 +0,0 @@ -// Int1<:IntT -// Int2<:IntIntT -// Int2R<:Int2 -// Int2R<:IntIntRT -// Int2R<:IntIntT -// IntIntRT<:Int2 -// IntIntRT<:Int2R -// IntIntRT<:IntIntT -// IntIntT<:Int2 -// IntT<:Int1 - -type Int1 int[1]; -type Int2 int[2]; - -type IntT [int]; - -type IntIntT [int, int]; - -type IntIntRT readonly & [int, int]; - -type Int2R readonly & int[2]; - -type Int int; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/fixed-length-array.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/fixed-length-array.bal deleted file mode 100644 index a8cecd384acc..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/fixed-length-array.bal +++ /dev/null @@ -1,93 +0,0 @@ -// Array2OfInt5<:ArrayOfInt5 -// Array2OfInt5<:ArrayOfIntArray -// Array2OfInt5<:ArrayOfIntFive -// Array5OfInt5<:Array5OfIntArray -// Array5OfInt5<:ArrayFiveOfIntFive -// Array5OfInt5<:ArrayOfInt5 -// Array5OfInt5<:ArrayOfIntArray -// Array5OfInt5<:ArrayOfIntFive -// Array5OfIntArray<:ArrayOfIntArray -// Array7OfArray2OfInt5<:Array7x2x5 -// Array7x2x5<:Array7OfArray2OfInt5 -// ArrayFiveOfIntFive<:Array5OfInt5 -// ArrayFiveOfIntFive<:Array5OfIntArray -// ArrayFiveOfIntFive<:ArrayOfInt5 -// ArrayFiveOfIntFive<:ArrayOfIntArray -// ArrayFiveOfIntFive<:ArrayOfIntFive -// ArrayOfInt5<:ArrayOfIntArray -// ArrayOfInt5<:ArrayOfIntFive -// ArrayOfIntFive<:ArrayOfInt5 -// ArrayOfIntFive<:ArrayOfIntArray -// EmptyIntArray<:ArrayOfInt5 -// EmptyIntArray<:ArrayOfIntArray -// EmptyIntArray<:ArrayOfIntFive -// EmptyIntArray<:IntArray -// FIVE<:INT -// Int5<:IntArray -// N<:Array2OfInt5 -// N<:Array5OfInt5 -// N<:Array5OfIntArray -// N<:Array7OfArray2OfInt5 -// N<:Array7x2x5 -// N<:ArrayFiveOfIntFive -// N<:ArrayOfInt5 -// N<:ArrayOfIntArray -// N<:ArrayOfIntFive -// N<:EmptyIntArray -// N<:FIVE -// N<:INT -// N<:Int5 -// N<:IntArray -// N<:ROArrayFiveOfIntFive -// N<:ROInt5 -// N<:ROIntArray -// N<:TwoArraysOfInt5 -// ROArrayFiveOfIntFive<:Array5OfInt5 -// ROArrayFiveOfIntFive<:Array5OfIntArray -// ROArrayFiveOfIntFive<:ArrayFiveOfIntFive -// ROArrayFiveOfIntFive<:ArrayOfInt5 -// ROArrayFiveOfIntFive<:ArrayOfIntArray -// ROArrayFiveOfIntFive<:ArrayOfIntFive -// ROInt5<:Int5 -// ROInt5<:IntArray -// ROInt5<:ROIntArray -// ROIntArray<:IntArray -// EmptyIntArray<:ROIntArray - -type IntArray int[]; - -type Int5 int[5]; - -type ArrayOfIntArray int[][]; - -type ArrayOfInt5 int[][5]; - -type Array5OfInt5 int[5][5]; - -type INT int; - -type Array5OfIntArray int[5][]; - -type ROIntArray readonly & IntArray; - -type ROInt5 readonly & int[5]; - -const FIVE = 5; - -type ArrayOfIntFive int[][FIVE]; - -type ArrayFiveOfIntFive int[FIVE][FIVE]; - -type ROArrayFiveOfIntFive ArrayFiveOfIntFive & readonly; - -type N never; - -type TwoArraysOfInt5 int[2][][5]; - -type EmptyIntArray int[0]; - -type Array2OfInt5 Int5[2]; - -type Array7OfArray2OfInt5 Array2OfInt5[7]; - -type Array7x2x5 int[7][2][5]; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/float-singleton.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/float-singleton.bal deleted file mode 100644 index 7a28045e105e..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/float-singleton.bal +++ /dev/null @@ -1,25 +0,0 @@ -// Z<:F -// Z<:ZO -// Z<:ZOT -// Z<:ZT -// ZO<:F -// ZO<:ZOT -// ZOT<:F -// ZT<:F -// ZT<:ZOT -// O<:F -// O<:ZO -// O<:ZOT -// T<:F -// T<:ZOT -// T<:ZT - -type Z 0.0; -type O 1.0; -type T -2.0; - -type ZOT Z|O|T; -type ZO Z|O; -type ZT Z|T; - -type F float; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/float-singleton2.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/float-singleton2.bal deleted file mode 100644 index 3f404c273992..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/float-singleton2.bal +++ /dev/null @@ -1,20 +0,0 @@ -// ALSO_NAN<:Float -// ALSO_NAN<:NAN -// INFINITY<:Float -// NAN<:ALSO_NAN -// NAN<:Float -// NEGATIVE_INFINITY<:Float -// NegativeZero<:Float -// NegativeZero<:Zero -// Zero<:Float -// Zero<:NegativeZero - -const INFINITY = 1.0/0.0; -const NEGATIVE_INFINITY = -1.0/0.0; -const NAN = 0f/0f; -const ALSO_NAN = -NAN; - -type Zero 0.0; -type NegativeZero -0.0; - -type Float float; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/function.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/function.bal deleted file mode 100644 index c1657b0ca2cc..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/function.bal +++ /dev/null @@ -1,10 +0,0 @@ -// F<:A -// S<:T - -type F function() returns F; -type A function() returns any|error; - -type S function(int?) returns string; -type T function(int) returns string?; - - diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/future-subtype.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/future-subtype.bal deleted file mode 100644 index 20f552629616..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/future-subtype.bal +++ /dev/null @@ -1,10 +0,0 @@ -// I<:U1 -// I<:U2 -// S<:U1 -// S<:U2 -// U1<:U2 - -type I future; -type S future; -type U1 I|S; -type U2 future; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/hard.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/hard.bal deleted file mode 100644 index d64f6c812c45..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/hard.bal +++ /dev/null @@ -1,11 +0,0 @@ -// J1<:J2 -// J1<:J3 -// J2<:J1 -// J2<:J3 -// J3<:J1 -// J3<:J2 -type J1 [J2,J1]|record {| J1 x; J1 y; |}|()|int|string; -type J2 ()|int|string|[J1,J2]|record {| J2 x; J1 y; |}; -type J3 ()|int|string|[J3,J3]|record {| J3 x; J3 y; |}; - - diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/int-singleton.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/int-singleton.bal deleted file mode 100644 index 12e49cac6304..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/int-singleton.bal +++ /dev/null @@ -1,13 +0,0 @@ -// INT_MIN<:Int -// ONE<:Int -// ONE<:ZERO_OR_ONE -// ZERO<:Int -// ZERO<:ZERO_OR_ONE -// ZERO_OR_ONE<:Int -const ONE = 1; -const ZERO = 0; -const INT_MIN = -9223372036854775807 - 1; - -type ZERO_OR_ONE ZERO|ONE; -type Int int; - diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/int-singleton2.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/int-singleton2.bal deleted file mode 100644 index c5d713c07693..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/int-singleton2.bal +++ /dev/null @@ -1,7 +0,0 @@ -// MinusOne<:Sign -// One<:Byte -// One<:Sign -type One 1; -type MinusOne -1; -type Sign One|MinusOne; -type Byte byte; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/int-subtype.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/int-subtype.bal deleted file mode 100644 index bc5fa06625d9..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/int-subtype.bal +++ /dev/null @@ -1,26 +0,0 @@ -// Byte<:Sint16 -// Byte<:Sint32 -// Byte<:Uint16 -// Byte<:Uint32 -// Byte<:Uint8 -// N33000<:Sint32 -// N33000<:Uint16 -// N33000<:Uint32 -// Sint16<:Sint32 -// Sint8<:Sint16 -// Sint8<:Sint32 -// Uint16<:Sint32 -// Uint16<:Uint32 -// Uint8<:Byte -// Uint8<:Sint16 -// Uint8<:Sint32 -// Uint8<:Uint16 -// Uint8<:Uint32 -type Byte byte; -type Uint8 int:Unsigned8; -type Uint16 int:Unsigned16; -type Uint32 int:Unsigned32; -type Sint8 int:Signed8; -type Sint16 int:Signed16; -type Sint32 int:Signed32; -const N33000 = 33000; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/list-fixed.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/list-fixed.bal deleted file mode 100644 index eb030abfabfc..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/list-fixed.bal +++ /dev/null @@ -1,8 +0,0 @@ -// IF<:I -// IF<:IFF -// IFF<:I -// IFF<:IF - -type I int[]; -type IF int[12224]; -type IFF int[12224]; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/mapping1.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/mapping1.bal deleted file mode 100644 index e07ea23f6ec2..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/mapping1.bal +++ /dev/null @@ -1,19 +0,0 @@ -// M1<:M -// M1<:M2 -// M1<:N -// M2<:M -// M2<:M1 -// M2<:N -// M<:M1 -// M<:M2 -// M<:N -// N<:M -// N<:M1 -// N<:M2 -type M map; - -type N map; - -type M1 map|record {}; - -type M2 map|record {}; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/mapping2.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/mapping2.bal deleted file mode 100644 index 53dec4dc4440..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/mapping2.bal +++ /dev/null @@ -1,19 +0,0 @@ -// M1<:M -// M1<:M2 -// M1<:N -// M2<:M -// M2<:M1 -// M2<:N -// M<:M1 -// M<:M2 -// M<:N -// N<:M -// N<:M1 -// N<:M2 -type M map<(1|2|3)>; - -type N map<(1|2|3)>; - -type M1 M|map<(1|2)>; - -type M2 N|map<(1|2)>; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/mutable-record1.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/mutable-record1.bal deleted file mode 100644 index 3cc12b9c5b3d..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/mutable-record1.bal +++ /dev/null @@ -1,36 +0,0 @@ -// NN<:U -// NN<:UU -// NS<:U -// NS<:UU -// SN<:U -// SN<:UU -// SS<:U -// SS<:UU -// U<:UU - -type NN record {| - int x; - int y; -|}; - -type SS record {| - string x; - string y; -|}; - -type NS record {| - int x; - string y; -|}; - -type SN record {| - string x; - int y; -|}; - -type UU record {| - int|string x; - int|string y; -|}; - -type U NN|SS|NS|SN; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/never.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/never.bal deleted file mode 100644 index 2516326d50c9..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/never.bal +++ /dev/null @@ -1,21 +0,0 @@ -// Fun<:FunOrNever -// FunOrNever<:Fun -// Int<:IntOrNever -// IntOrNever<:Int -// Key<:KeyOrNever -// KeyOrNever<:Key -// Never<:Fun -// Never<:FunOrNever -// Never<:Int -// Never<:IntOrNever -// Never<:Key -// Never<:KeyOrNever -type Never never; -type Int int; -type Fun function(int); -type FunOrNever Fun|never; -type IntOrNever Int|never; -type Key "key"; -type KeyOrNever Key|never; - - diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/readonly1.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/readonly1.bal deleted file mode 100644 index 0f841c7862de..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/readonly1.bal +++ /dev/null @@ -1,19 +0,0 @@ -// Boolean<:RO -// Decimal<:RO -// Error<:RO -// Float<:RO -// Handle<:RO -// Int<:RO -// Nil<:RO -// String<:RO -type RO readonly; -type Nil (); -type String string; -type Boolean boolean; -type Int int; -type Float float; -type Decimal decimal; -type Error error; -type Handle handle; -type List (any|error)[]; -type Mapping map; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/readonly2.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/readonly2.bal deleted file mode 100644 index 39142d87a52b..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/readonly2.bal +++ /dev/null @@ -1,26 +0,0 @@ -// E<:ER -// ER<:E -// IR<:Int -// Int<:IR -// LR1<:LR -// LR1<:LR2 -// LR2<:LR -// LR2<:LR1 -// MR1<:MR -// MR1<:MR2 -// MR2<:MR -// MR2<:MR1 -type E error; -type ER error>; -type LR readonly[]; -type MR map; -// These two should be equivalent -type MR1 readonly & map; -type MR2 readonly & map; -// As should these -type LR1 readonly & (any|error)[]; -type LR2 readonly & readonly[]; -// As should these -type IR int & readonly; -type Int int; - diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/stream-recursive.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/stream-recursive.bal deleted file mode 100644 index bb595595ecaa..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/stream-recursive.bal +++ /dev/null @@ -1,8 +0,0 @@ -// SR<:S -type SR stream; - -type S stream; - -// S1<:SR -// S1<:S -type S1 stream<()>; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/stream-subtype.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/stream-subtype.bal deleted file mode 100644 index 372455449317..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/stream-subtype.bal +++ /dev/null @@ -1,10 +0,0 @@ -// I<:U1 -// I<:U2 -// S<:U1 -// S<:U2 -// U1<:U2 - -type I stream; -type S stream; -type U1 I|S; -type U2 stream; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/stream-subtype2.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/stream-subtype2.bal deleted file mode 100644 index a170dd69ffe3..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/stream-subtype2.bal +++ /dev/null @@ -1,20 +0,0 @@ -// I<:J -// I<:J1 -// I<:J2 -type I stream; - -// S<:J -// S<:J1 -// S<:J2 -type S stream; - - -// J<:J1 -// J1<:J -type J stream; -type J1 stream; - -// J<:J2 -// J1<:J2 -type J2 stream; -type J3 stream; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/string-all-subtypes.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/string-all-subtypes.bal deleted file mode 100644 index 33ca5ed91c29..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/string-all-subtypes.bal +++ /dev/null @@ -1,29 +0,0 @@ -// A<:Bar -// A<:Baz -// A<:C -// A<:S -// A<:SC -// Bar<:Baz -// Bar<:S -// Bar<:SC -// Baz<:S -// Baz<:SC -// C<:Baz -// C<:S -// C<:SC -// Foo<:Bar -// Foo<:Baz -// Foo<:S -// Foo<:SC -// S<:Baz -// S<:SC -// SC<:Baz -// SC<:S - -type S string; -type C string:Char; -type A "A"; -type Foo "Foo"; -type Bar A|Foo; -type Baz Bar|S|C; -type SC S|C; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/string-char.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/string-char.bal deleted file mode 100644 index b487d618849f..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/string-char.bal +++ /dev/null @@ -1,13 +0,0 @@ -// C1<:C -// C1<:D -// C1<:S -// C<:C1 -// C<:D -// C<:S -// D<:C -// D<:C1 -// D<:S -type C string:Char; -type C1 string:Char; -type D C|C1; -type S string; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/string-singleton-same-shape.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/string-singleton-same-shape.bal deleted file mode 100644 index 681bc54ca07a..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/string-singleton-same-shape.bal +++ /dev/null @@ -1,27 +0,0 @@ -// WHY<:S -// WHY<:Y -// WHY<:Y1 -// X1<:S -// X1<:X -// X1<:XES -// X2<:S -// X2<:XES -// X<:S -// X<:X1 -// X<:XES -// XES<:S -// Y1<:S -// Y1<:WHY -// Y1<:Y -// Y<:S -// Y<:WHY -// Y<:Y1 - -type X "X"; -type X1 "X"; -type X2 "x"; -type Y "Why"; -type Y1 "Why"; -type XES X|X1|X2; -type WHY Y|Y1; -type S string; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/string-singleton.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/string-singleton.bal deleted file mode 100644 index b23a064fca77..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/string-singleton.bal +++ /dev/null @@ -1,24 +0,0 @@ -// X<:S -// X<:XY -// X<:XYZ -// X<:XZ -// XY<:S -// XY<:XYZ -// XYZ<:S -// XZ<:S -// XZ<:XYZ -// Y<:S -// Y<:XY -// Y<:XYZ -// Z<:S -// Z<:XYZ -// Z<:XZ -type X "x"; -type Y "y-y"; -type Z "z-z"; - -type XYZ X|Y|Z; -type XY X|Y; -type XZ X|Z; - -type S string; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/table-key.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/table-key.bal deleted file mode 100644 index 108808ce389b..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/table-key.bal +++ /dev/null @@ -1,30 +0,0 @@ -type R record {| - readonly [string, string] name; - readonly string department; - readonly string city; - int salary; -|}; - -type KS1 table key(name); - -type KS2 table key(city); - -type KS3 table key(department); - -type KS4 table key(city, department); - -type KS5 table key(department, city); - -type KS6 table key(name, department, city); - -// KS2<:KC1 -// KS3<:KC1 -type KC1 table key; - -// KS1<:KC2 -// KS4<:KC2 -// KS5<:KC2 -type KC2 table key<[string, string]>; - -// KS6<:KC3 -type KC3 table key<[[string, string], string, string]>; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/tuple1.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/tuple1.bal deleted file mode 100644 index 3b43eec0ab60..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/tuple1.bal +++ /dev/null @@ -1,6 +0,0 @@ -// T1<:T2 -// T4<:T3 -type T1 [int]; -type T2 [int?]; -type T3 [int, int?]; -type T4 [int, int] | [int, ()]; \ No newline at end of file diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/tuple4.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/tuple4.bal deleted file mode 100644 index ecb6410c704e..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/tuple4.bal +++ /dev/null @@ -1,11 +0,0 @@ -// T2<:T1 -// T2<:T4 -// T3<:T1 -// T3<:T2 -// T3<:T4 - -type T1 [int...]; -type T2 [int,int...]; - -type T4 [int?,int?...]; -type T3 [int, int, int, int...]; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/typedesc-subtype.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/typedesc-subtype.bal deleted file mode 100644 index 64b30d899d46..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/typedesc-subtype.bal +++ /dev/null @@ -1,10 +0,0 @@ -// I<:U1 -// I<:U2 -// S<:U1 -// S<:U2 -// U1<:U2 - -type I typedesc; -type S typedesc; -type U1 I|S; -type U2 typedesc; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/xml-never.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/xml-never.bal deleted file mode 100644 index d8054d1fcecd..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/xml-never.bal +++ /dev/null @@ -1,34 +0,0 @@ -// C<:CS -// E<:ENS -// E<:ES -// ENS<:ES -// ES<:ENS -// N<:CS -// N<:ENS -// N<:ES -// N<:NS -// N<:PS -// N<:T -// N<:TS -// NS<:CS -// NS<:ENS -// NS<:ES -// NS<:N -// NS<:PS -// NS<:T -// NS<:TS -// P<:PS -// T<:TS -// TS<:T - -type N xml; -type NS xml; -type E xml:Element; -type T xml:Text; -type C xml:Comment; -type P xml:ProcessingInstruction; -type ES xml; -type CS xml; -type TS xml; -type PS xml; -type ENS xml; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/xml-sequence.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/xml-sequence.bal deleted file mode 100644 index ccb734bfffd4..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/xml-sequence.bal +++ /dev/null @@ -1,90 +0,0 @@ -// E<:P -// E<:Q -// E<:U -// E<:V -// E<:X -// E<:XE -// E<:XEU -// E<:Y -// N<:P -// N<:Q -// N<:T -// N<:U -// N<:V -// N<:X -// N<:XE -// N<:XEU -// N<:XT -// N<:Y -// P<:Q -// P<:X -// P<:XE -// P<:XEU -// P<:Y -// Q<:P -// Q<:X -// Q<:XE -// Q<:XEU -// Q<:Y -// T<:P -// T<:Q -// T<:V -// T<:X -// T<:XE -// T<:XEU -// T<:XT -// T<:Y -// U<:P -// U<:Q -// U<:V -// U<:X -// U<:XE -// U<:XEU -// U<:Y -// V<:P -// V<:Q -// V<:X -// V<:XE -// V<:XEU -// V<:Y -// X<:P -// X<:Q -// X<:XE -// X<:XEU -// X<:Y -// XE<:P -// XE<:Q -// XE<:X -// XE<:XEU -// XE<:Y -// XEU<:P -// XEU<:Q -// XEU<:X -// XEU<:XE -// XEU<:Y -// XT<:P -// XT<:Q -// XT<:T -// XT<:V -// XT<:X -// XT<:XE -// XT<:XEU -// XT<:Y -// Y<:P -// Y<:Q -// Y<:X -// Y<:XE -// Y<:XEU - -type X xml; -type Y xml; -type P xml; -type Q xml

; -type U xml; -type V xml; -type N xml; -type E xml:Element; -type XE xml; -type XEU xml|E; -type T xml:Text; -type XT xml; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/xml-singleton.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/xml-singleton.bal deleted file mode 100644 index ca48dee0cd10..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/xml-singleton.bal +++ /dev/null @@ -1,13 +0,0 @@ -// C<:CTE -// C<:X -// CTE<:X -// E<:CTE -// E<:X -// T<:CTE -// T<:X - -type C xml:Comment; -type E xml:Element; -type CTE C|T|E; -type T xml:Text; -type X xml; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/xml.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/xml.bal deleted file mode 100644 index 5b347b8ccea5..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/data/xml.bal +++ /dev/null @@ -1,13 +0,0 @@ -// C<:EC -// C<:X -// E<:EC -// E<:ET -// E<:X -// EC<:X -// ET<:X - -type E xml; -type C xml; -type EC xml; -type ET xml; -type X xml; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/fixed-length-array-too-large-te.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/fixed-length-array-too-large-te.bal deleted file mode 100644 index 6b25f6b2e889..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/fixed-length-array-too-large-te.bal +++ /dev/null @@ -1,2 +0,0 @@ -public const int MAX_VALUE = 9223372036854775807; -type LargeArray int[MAX_VALUE]; // @error diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/localVar/func.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/localVar/func.bal deleted file mode 100644 index a4511d0bca26..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/localVar/func.bal +++ /dev/null @@ -1,11 +0,0 @@ -// x = R -// y = S - -type N int; -type S string; -type R N|S; - -function foo() { - R x = 1; - S y = "str"; -} diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/simple-type/float-altered.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/simple-type/float-altered.bal deleted file mode 100644 index 985013bd1e1f..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/simple-type/float-altered.bal +++ /dev/null @@ -1,9 +0,0 @@ -// NegativeZero<:Float -// NegativeZero<:Zero -// Zero<:Float -// Zero<:NegativeZero - -type Zero 0.0; -type NegativeZero -0.0; - -type Float float; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/simple-type/function-altered.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/simple-type/function-altered.bal deleted file mode 100644 index 016125fd386a..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/simple-type/function-altered.bal +++ /dev/null @@ -1,8 +0,0 @@ -// F<:A -// S<:T - -type F function() returns S; -type A function() returns any; - -type S function(int?) returns string; -type T function(int) returns string?; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/simple-type/int-singleton-altered.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/simple-type/int-singleton-altered.bal deleted file mode 100644 index 75faa34ff975..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/simple-type/int-singleton-altered.bal +++ /dev/null @@ -1,13 +0,0 @@ -// INT_MIN<:Int -// ONE<:Int -// ONE<:ZERO_OR_ONE -// ZERO<:Int -// ZERO<:ZERO_OR_ONE -// ZERO_OR_ONE<:Int - -const ONE = 1; -const ZERO = 0; -const int INT_MIN = -9223372036854775807 - 1; - -type ZERO_OR_ONE ZERO|ONE; -type Int int; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/simple-type/list-type-test.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/simple-type/list-type-test.bal deleted file mode 100644 index 62d962464787..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/simple-type/list-type-test.bal +++ /dev/null @@ -1,19 +0,0 @@ -// IIT<:IRIT -// IIT<:L -// IIT<:L1 -// IIT<:RIT -// IRIT<:L -// IRIT<:L1 -// IRIT<:RIT -// L1<:L -// L1<:RIT -// L<:L1 -// L<:RIT -// RIT<:L -// RIT<:L1 - -type L int[]; -type L1 int[]; -type RIT [int...]; -type IRIT [int, int...]; -type IIT [int, int]; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/simple-type/map-type-test.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/simple-type/map-type-test.bal deleted file mode 100644 index f0de0af00861..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/simple-type/map-type-test.bal +++ /dev/null @@ -1,11 +0,0 @@ -// MB<:MI -// MB<:RIC -// MI<:RIC -// RC<:MI -// RC<:RIC -// RIC<:MI - -type MI map; -type MB map; -type RIC record {| int...; |}; -type RC record {| int i; |}; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/simple-type/type-test.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/simple-type/type-test.bal deleted file mode 100644 index dadcd0eaaca4..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/simple-type/type-test.bal +++ /dev/null @@ -1,11 +0,0 @@ -// N<:R -// N<:T -// R<:N -// R<:T -// T<:N -// T<:R - -type T int; -type T1 string; -type N int; -type R N; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel-wrong.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel-wrong.bal deleted file mode 100644 index 0dfe7e74972a..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel-wrong.bal +++ /dev/null @@ -1,4 +0,0 @@ -type X int; - -// Y <: X -type Y byte; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/anydata-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/anydata-tv.bal deleted file mode 100644 index f0eb6b30bc68..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/anydata-tv.bal +++ /dev/null @@ -1,19 +0,0 @@ -type A anydata; - -// @type T < A -type T table>; - -// @type TB < A -type TB table>; - -// @type TI < A -type TI table>; - -// @type TARR < A -type TARR table>; - -// @type TANY <> A -type TANY table>; - -// @type TERR <> A -type TERR table>; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/basic-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/basic-tv.bal deleted file mode 100644 index fabd47e8f069..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/basic-tv.bal +++ /dev/null @@ -1,17 +0,0 @@ -// @type T1 < T2 -// @type T1 <> T3 -type T1 1|1.0|"foo"; -type T2 int|float|string; -type T3 int|string; - -// @type T4 = OneFoo -type T4 T3 & T1; -type OneFoo 1|"foo"; - -// @type T5 = One -// @type DoubleOne = One -// @type AnotherDoubleOne = One -type T5 1|1; -type One 1; -type DoubleOne One|One; -type AnotherDoubleOne One|1; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/bdddiff1-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/bdddiff1-tv.bal deleted file mode 100644 index 3012aea1fdae..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/bdddiff1-tv.bal +++ /dev/null @@ -1,4 +0,0 @@ -type INA int?[]; -type IA int[]; -// @type U = INA -type U IA|INA; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/cyclic-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/cyclic-tv.bal deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/decimal-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/decimal-tv.bal deleted file mode 100644 index 257448a987f1..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/decimal-tv.bal +++ /dev/null @@ -1,13 +0,0 @@ -// @type PosZero < Decimal -// @type NegZero < Decimal -// @type OtherZero < Decimal -// @type PosZero = NegZero -// @type PosZero = OtherZero -type PosZero 0.0d; -type NegZero -0.0d; -type OtherZero 0d; - -type Decimal decimal; - -// @type IntZero <> OtherZero -type IntZero 0; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/dependently-typed-fn-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/dependently-typed-fn-tv.bal deleted file mode 100644 index b0b9d98eeae3..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/dependently-typed-fn-tv.bal +++ /dev/null @@ -1,9 +0,0 @@ -// @type F1 < F2 -type F1 function (typedesc td) returns td; - -type F2 function (typedesc td) returns anydata; - -// @type Fu1 < Fu2 -type Fu1 function (typedesc td) returns td|error; - -type Fu2 function (typedesc td) returns anydata|error; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/error1-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/error1-tv.bal deleted file mode 100644 index 8a188010c68f..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/error1-tv.bal +++ /dev/null @@ -1,9 +0,0 @@ -// @type EL < E -// @type ER1 < E -// @type ER1 = ER2 -// @type EL <> ER1 -// @type ER2 < E -type EL error; -type ER1 error; -type ER2 error; -type E error; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/fixed-length-array-large-t.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/fixed-length-array-large-t.bal deleted file mode 100644 index 52bcf3cdb1f8..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/fixed-length-array-large-t.bal +++ /dev/null @@ -1,21 +0,0 @@ -type IntArray int[]; -type Int5 int[5]; -type ISTArray (1|2|3)[]; - -public const int MAX_VALUE = 2147483637; -public const int MAX_VALUE_M_1 = MAX_VALUE - 1; - -// @type LargeArray < IntArray -type LargeArray int[MAX_VALUE]; - -// @type LargeArray2 < IntArray -// @type LargeArray <> LargeArray2 -type LargeArray2 int[MAX_VALUE_M_1]; - -// -@type Int5Intersection = Int5 -type Int5Intersection int[5] & !LargeArray; - -type Int10000 int[100000]; - -// -@type ISTArray < I10000A -type I10000A Int10000|(!Int10000 & IntArray); diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/fixed-length-array-t.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/fixed-length-array-t.bal deleted file mode 100644 index 66421f63cf41..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/fixed-length-array-t.bal +++ /dev/null @@ -1,68 +0,0 @@ -type IntArray int[]; - -// @type Int5 < IntArray -type Int5 int[5]; - -// @type Int5 = Int5AndIntArray -// @type Int5AndIntArray < IntArray -type Int5AndIntArray Int5 & IntArray; - -// @type IntArray <> ArrayOfIntArray -type ArrayOfIntArray int[][]; - -// @type ArrayOfInt5 < ArrayOfIntArray -// @type Int5 <> ArrayOfInt5 -// @type Int5 = ArrayOfInt5[0] -// @type Int5 = ArrayOfInt5[5] -// @type Int5 = ArrayOfInt5[6] -type ArrayOfInt5 int[][5]; - -// @type Array5OfInt5 < ArrayOfInt5 -// @type Array5OfInt5 < ArrayOfIntArray -type Array5OfInt5 int[5][5]; - -type INT int; - -// @type Array5OfInt5 < Array5OfIntArray -// @type Array5OfIntArray < ArrayOfIntArray -// @type IntArray = Array5OfIntArray[0] -// @type IntArray = Array5OfIntArray[4] -type Array5OfIntArray int[5][]; - -type ROIntArray readonly & IntArray; - -// @type ROInt5 < Int5 -// @type ROInt5 < ROIntArray -type ROInt5 readonly & int[5]; - -// -@type ArrayExcept5 <> Int5; -// -@type ArrayExcept5 < IntArray; -type ArrayExcept5 IntArray & !Int5; - -const FIVE = 5; - -// @type ArrayOfInt5 = ArrayOfIntFive -type ArrayOfIntFive int[][FIVE]; - -// @type Array5OfInt5 = ArrayFiveOfIntFive -type ArrayFiveOfIntFive int[FIVE][FIVE]; - -// @type ROArrayFiveOfIntFive < ArrayFiveOfIntFive -// @type ROArrayFiveOfIntFive < Array5OfInt5 -type ROArrayFiveOfIntFive ArrayFiveOfIntFive & readonly; - -type N never; -// @type ArrayOfInt5 = TwoArraysOfInt5[0] -// @type ArrayOfInt5 = TwoArraysOfInt5[1] -// @type N = TwoArraysOfInt5[2] -type TwoArraysOfInt5 int[2][][5]; - -// @type EmptyIntArray < IntArray -type EmptyIntArray int[0]; - -type Array2OfInt5 Int5[2]; - -type Array7OfArray2OfInt5 Array2OfInt5[7]; - -// @type Array7x2x5 = Array7OfArray2OfInt5 -type Array7x2x5 int[7][2][5]; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/fixed-length-array-tuple-t.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/fixed-length-array-tuple-t.bal deleted file mode 100644 index 91cab8527bef..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/fixed-length-array-tuple-t.bal +++ /dev/null @@ -1,27 +0,0 @@ -type Int1 int[1]; -type Int2 int[2]; - -// @type IntT = Int1 -type IntT [int]; - -// @type IntIntT = Int2 -type IntIntT [int, int]; - -// @type IntIntRT < IntIntT -// @type IntIntRT < Int2 -type IntIntRT readonly & [int, int]; - -// @type Int2R = IntIntRT -type Int2R readonly & int[2]; - -// @type Int = IntIntT[0] -type Int int; - -// @type Int = Int2Intersection[0] -// @type Int = Int2Intersection[1] -type Int2Intersection IntIntT & int[2]; - -// @type Int2Intersection = Int2AnyArrayIntersection -// @type Int = Int2AnyArrayIntersection[0] -// @type Int = Int2AnyArrayIntersection[1] -type Int2AnyArrayIntersection IntIntT & any[]; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/fixed-length-array2-t.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/fixed-length-array2-t.bal deleted file mode 100644 index a66701665330..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/fixed-length-array2-t.bal +++ /dev/null @@ -1,66 +0,0 @@ -type IntArray int[]; -type ISArray (int|string)[]; -type ISTArray (1|2|3)[]; - -type Int4 int[4]; -type Int1 int[1]; -type Int14 Int4|Int1; -type NegInt14 (!Int14 & IntArray); - -// -@type I4A = IntArray -// -@type I4A < ISArray -type I4A Int4|(!Int4 & IntArray); - -type Int10000 int[100000]; - -// -@type ISTArray < I10000A -type I10000A Int10000|(!Int10000 & IntArray); - -// -@type IA = IntArray -// -@type IA < ISArray -type IA Int14|NegInt14; - -type IS int|string; -type EMPTY []; -type IS1 IS[1]; -type IS2 IS[2]; -type IS3 IS[3]; - -// @type ALL = ISArray -type ALL EMPTY|IS1|IS2|IS3|[IS, IS, IS, IS, IS...]; - -// @type ISArray < U -type U EMPTY|[IS|float, IS...]; - -// @type ISArray < V -type V EMPTY|[IS]|[IS, IS|float, IS...]; - -// @type ISArray < W -type W EMPTY|[IS]|[IS, IS|float]|[IS, IS, IS|float, IS...]; - -// @type ISArray < X -type X EMPTY|[IS]|[IS, IS|float]|[IS, IS, IS|float]|[IS, IS, IS, IS|float, IS...]; - -// @type ISArray < Y -type Y EMPTY|[IS, IS, IS, IS|float, IS...]|[IS, IS, IS|float]|[IS, IS|float]|[IS]; - -// @type ISArray < Z -type Z [IS, IS, IS, IS|float, IS...]|[IS, IS, IS|float]|[IS, IS|float]|[IS]|EMPTY; - -// @type IntArray < P -type P EMPTY|[int]|[IS, int]|[IS, IS, IS, IS...]; - -// @type IntArray < Q -type Q EMPTY|[int]|[IS, IS]|[IS, IS, IS|float, IS...]; - -// @type IntArray < R -type R EMPTY|[int]|[IS, IS]|[int, int, IS|float, IS...]; - -// @type IntArray < S -type S EMPTY|[int]|[IS, IS]|[int, int, int, IS...]; - -// @type IntArray < T -type T EMPTY|[int]|[IS, int]|[IS, IS, IS|float, IS...]; - -// @type IntArray < T1 -type T1 EMPTY|[int]|[IS, IS, string...]|[IS, IS, IS, IS...]; \ No newline at end of file diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/float-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/float-tv.bal deleted file mode 100644 index e11c0d03170c..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/float-tv.bal +++ /dev/null @@ -1,22 +0,0 @@ -// @type NegativeZero < Float -// @type Zero < Float -// @type NegativeZero = Zero - -type Zero 0.0; - -type NegativeZero -0.0; - -type Float float; - -// @type D1 <> Float -// @type D1 <> Zero -type D1 0.0d; - -// @type F1 < Float -// @type F1 = Zero -// @type F1 = NegativeZero -// @type F2 = Zero -// @type F2 = NegativeZero -type F1 Zero|NegativeZero; - -type F2 F1 & Zero; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/func-quals-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/func-quals-tv.bal deleted file mode 100644 index b1d05f965f6a..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/func-quals-tv.bal +++ /dev/null @@ -1,43 +0,0 @@ -// @type IsolatedFuncTop < FuncTop -type IsolatedFuncTop isolated function; - -type FuncTop function; - -// @type FI1 < F1 -// @type FI1 < IsolatedFuncTop -// @type FI1 < FuncTop -type FI1 isolated function (); - -type F1 function (); - -type FI2 isolated function (int); - -type FI3 isolated function (int, int); - -// @type FI1 < FIX -// @type FI2 < FIX -// @type FI3 < FIX -// @type FIX < IsolatedFuncTop -// @type FIX < FuncTop -type FIX FI1|FI2|FI3; - -type F2 function (int); - -type F3 function (int, int); - -// @type FIX < FX -type FX F1|F2|F3; - -// @type F1 < FT1 -type FT1 transactional function (); - -type FT2 transactional function (int); - -type FT3 transactional function (int, int); - -// @type FT1 < FTX -// @type FT2 < FTX -// @type FT3 < FTX -// @type FX < FTX -// @type FIX < FTX -type FTX FT1|FT2|FT3; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/function-intersection-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/function-intersection-tv.bal deleted file mode 100644 index 51d2c21b43b3..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/function-intersection-tv.bal +++ /dev/null @@ -1,6 +0,0 @@ -type F1 function(1|2|3); -type F2 function(2|3|4); - -// @type F < F1 -// @type F < F2 -type F F1&F2; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/function-param-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/function-param-tv.bal deleted file mode 100644 index 92e13f181a44..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/function-param-tv.bal +++ /dev/null @@ -1,7 +0,0 @@ -// @type F12 < F1 -type F12 function(1|2); -type F1 function(1); - -// @type F_ret1 < F_ret12 -type F_ret12 function() returns 1|2; -type F_ret1 function() returns 1; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/function-rec-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/function-rec-tv.bal deleted file mode 100644 index 203a184e923d..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/function-rec-tv.bal +++ /dev/null @@ -1,7 +0,0 @@ -// @type F < Fx -type F function() returns F; -type Fx function() returns function; - -// @type Gx < G -type G function(G); -type Gx function(function); diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/function-rest-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/function-rest-tv.bal deleted file mode 100644 index 9699a0cec5a6..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/function-rest-tv.bal +++ /dev/null @@ -1,8 +0,0 @@ -// @type FInt < F1 -// @type FInt < F2 -// @type FInt < F3 -// @type F3 < F2 -type FInt function(int...); -type F1 function(int); -type F2 function(int, int); -type F3 function(int, int, int...); diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/function-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/function-tv.bal deleted file mode 100644 index a1d805b70a34..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/function-tv.bal +++ /dev/null @@ -1,16 +0,0 @@ -type F function; - -// @type F1 < F -// @type F1_bar < F -type F1 function(int); -type F1_bar function(int a); - -// @type F2 < F -// @type F2_bar < F -type F2 function(int) returns boolean; -type F2_bar function(int a) returns boolean; - -// @type F3 < F -// @type F3_bar < F -type F3 function(int...) returns boolean; -type F3_bar function(int... a) returns boolean; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/function-union-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/function-union-tv.bal deleted file mode 100644 index 6858050e36ff..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/function-union-tv.bal +++ /dev/null @@ -1,8 +0,0 @@ -type F1 function(1|2); -type F2 function(2|3); - -// @type F1 < F -// @type F2 < F -// @type F < Fx -type F F1|F2; -type Fx function(2); diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/function2-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/function2-tv.bal deleted file mode 100644 index 1a6563cd54f9..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/function2-tv.bal +++ /dev/null @@ -1,13 +0,0 @@ -type ANY any; - -// @type F1 < ANY -// @type F_INT < ANY -// @type F_INT < F1 -type F1 function(1); -type F_INT function(int); - -// @type F1_ret < ANY -// @type F_INT_ret < ANY -// @type F1_ret < F_INT_ret -type F1_ret function() returns 1; -type F_INT_ret function() returns int; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/future-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/future-tv.bal deleted file mode 100644 index 0a9e4c396769..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/future-tv.bal +++ /dev/null @@ -1,7 +0,0 @@ -// @type FInt < FUTURE -// @type FByte < FInt -type FUTURE future; - -type FInt future; - -type FByte future; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/list1-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/list1-tv.bal deleted file mode 100644 index d80b50d5df6e..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/list1-tv.bal +++ /dev/null @@ -1,3 +0,0 @@ -// @type A <> B -type A int[2][][5]; -type B int[][]; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mapping-basic-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mapping-basic-tv.bal deleted file mode 100644 index a17a0d5da75d..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mapping-basic-tv.bal +++ /dev/null @@ -1,3 +0,0 @@ -// @type M_INT < M_ANY -type M_ANY map; -type M_INT map; \ No newline at end of file diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mapping-record-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mapping-record-tv.bal deleted file mode 100644 index 8b0262b000ab..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mapping-record-tv.bal +++ /dev/null @@ -1,32 +0,0 @@ -// @type R1 < M1 -type R1 record {| int x; int...; |}; -type M1 map; - -// @type R3 = R1 -type R3 record {| int x; int ...; |}; - -// @type R4 < M2 -// @type R1 < M2 -// @type M1 < M2 -type R4 record {| int|string x; int|string ...; |}; -type M2 map; - -// @type R5 < M1 -// @type R5 < R1 -type R5 record {| int x; |}; - -// @type R6 < R1 -// @type R6 < M1 -type R6 record {| int x; int y; int ...; |}; - -// @type R7 <> R6 -type R7 record {| int x; int y; string ...; |}; - -// @type R6 < R8 -type R8 record {| int x; int y; int|string ...; |}; - -// @type R9 <> R8 -type R9 record {| int j; string k; |}; - -// @type R10 < R8 -type R10 record {| int x; int y; string j; |}; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mapping-t.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mapping-t.bal deleted file mode 100644 index 7ea9c2f212b9..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mapping-t.bal +++ /dev/null @@ -1,25 +0,0 @@ -// @type T < S -public type T R1|map<"A">; - -public type R1 record {| - byte A; - float...; -|}; - -public type S R2|map; - -public type R2 record {| - int A; - float...; -|}; - -// @type T2504 < T2525 -public type T2504 [map<[int]>, map<1>]; - -public type T2525 (map|map)[]; - - -// @type MISI < MIS -type MISI map|map; - -type MIS map; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mapping1-t.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mapping1-t.bal deleted file mode 100644 index 71bf0b0446ca..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mapping1-t.bal +++ /dev/null @@ -1,15 +0,0 @@ -// the order of type defns are intentional - -type M map; - -// @type M = N -type N map; - -// @type M1 = N -// @type M1 = M -type M1 M|record {}; - -// @type M1 = M2 -// @type M2 = M -// @type M2 = N -type M2 N|record {}; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mapping2-t.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mapping2-t.bal deleted file mode 100644 index b12f20a25f38..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mapping2-t.bal +++ /dev/null @@ -1,15 +0,0 @@ -// the order of type defns are intentional - -type M map<(1|2|3)>; - -// @type M = N -type N map<(1|2|3)>; - -// @type M1 = N -// @type M1 = M -type M1 M|map<(1|2)>; - -// @type M1 = M2 -// @type M2 = M -// @type M2 = N -type M2 N|map<(1|2)>; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mapping3-t.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mapping3-t.bal deleted file mode 100644 index 81a50d3cb104..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mapping3-t.bal +++ /dev/null @@ -1,13 +0,0 @@ -type M1 map|record {}; - -// @type M1 = M2 -type M2 mapM|record {}; - -type M3 map<(1|2|3)>|map<(1|2)>; - -// @type M3 = M4 -// @type M4 < M1 -// @type M4 < M2 -// @type M3 < M1 -// @type M3 < M2 -type M4 map<(1|2|3)>|map<(1|2)>; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mappingIntersect-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mappingIntersect-tv.bal deleted file mode 100644 index 375bc186966c..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mappingIntersect-tv.bal +++ /dev/null @@ -1,11 +0,0 @@ -type M1 map; -type M2 map; - -// @type T1 = M1M2 -type M1M2 map; -type T1 M1 & M2; - -type M3 map; - -// @type T2 = M1M2 -type T2 M1 & M2 & M3; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mutable-record-t.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mutable-record-t.bal deleted file mode 100644 index c9029bf6b586..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/mutable-record-t.bal +++ /dev/null @@ -1,82 +0,0 @@ -type I record {| - int x; -|}; - -type S record {| - string x; -|}; - -type IS record {| - int|string x; -|}; - -// @type IorS < IS -type IorS I|S; - -type NN record {| - int x; - int y; -|}; - -type SS record {| - string x; - string y; -|}; - -type NS record {| - int x; - string y; -|}; - -type SN record {| - string x; - int y; -|}; - -type UU record {| - int|string x; - int|string y; -|}; - -// @type U < UU -type U NN|SS|NS|SN; - -type P record {| - I|S x; -|}; - -// @type P < Q -type Q record {| - IS x; -|}; - -type P2 record {| - I|S x; - boolean y; -|}; - -// @type P2 < Q2 -type Q2 record {| - IS x; - boolean y; -|}; - -type P3 record {| - I|S x; - boolean...; -|}; - -// @type P3 < Q3 -type Q3 record {| - IS x; - boolean...; -|}; - -type P4 record { - I|S x; -}; - -// @type P4 < Q4 -type Q4 record { - IS x; -}; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/not1-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/not1-tv.bal deleted file mode 100644 index ae68b0827b06..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/not1-tv.bal +++ /dev/null @@ -1,5 +0,0 @@ - -type T1 int; - -// -@type T1 = T2 -type T2 int? & !(); diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/object-binaryops-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/object-binaryops-tv.bal deleted file mode 100644 index fce837339546..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/object-binaryops-tv.bal +++ /dev/null @@ -1,34 +0,0 @@ -type TOP object {}; -type O1 object { - int a; -}; - -type O2 object { - float b; -}; - -// @type O12 < TOP -// @type O1 < O12 -// @type O2 < O12 -type O12 O1|O2; - -type O3 object { - int a; - float b; - decimal c; -}; - -type O4 object { - int a; - float b; - string c; -}; - -type O34 O3 & O4; - -// @type OX < TOP -// @type O34 < OX -type OX object { - int a; - float b; -}; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/object-distinct-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/object-distinct-tv.bal deleted file mode 100644 index bae6af6458b4..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/object-distinct-tv.bal +++ /dev/null @@ -1,27 +0,0 @@ -// @type DistinctObject1 < ObjectTy1 -// @type DistinctObject2 < ObjectTy1 -// @type DistinctObject1 <> DistinctObject2 -// @type DistinctObject3 < DistinctObject1 - -type DistinctObject1 distinct ObjectTy1; - -type DistinctObject2 distinct ObjectTy1; - -type DistinctObject3 distinct DistinctObject1; - -type ObjectTy1 object { - int foo; - function bar() returns int; -}; - -// @type RecursiveDistinctObject1 < RecursiveObject -// @type RecursiveDistinctObject1 <> RecursiveDistinctObject2 -type RecursiveDistinctObject1 distinct object { - RecursiveDistinctObject1? oo; -}; - -type RecursiveDistinctObject2 distinct RecursiveObject; - -type RecursiveObject object { - RecursiveObject? oo; -}; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/object-qulifiers-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/object-qulifiers-tv.bal deleted file mode 100644 index d56694168bac..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/object-qulifiers-tv.bal +++ /dev/null @@ -1,61 +0,0 @@ -// @type IO1 < O1 -type IO1 isolated object { - int x; - function f() returns int; -}; - -// @type IO1 < IO2 -// @type IO2 <> O1 -type IO2 isolated object { - int x; -}; - -type O1 object { - int x; - function f() returns int; -}; - -// @type SO1 < O1 -type SO1 service object { - int x; - function f() returns int; -}; - -// @type ISO1 < O1 -// @type ISO1 < IO1 -// @type ISO1 < SO1 -type ISO1 isolated service object { - int x; - function f() returns int; -}; - -// @type CO1 < O1 -// @type CO1 <> SO1 -type CO1 client object { - int x; - function f() returns int; -}; - -// @type ICO1 < O1 -// @type ICO1 < IO1 -// @type ICO1 < CO1 -// @type ICO1 <> SO1 -// @type ICO1 <> ISO1 -type ICO1 isolated client object { - int x; - function f() returns int; -}; - -// @type I_TOP < TOP -// @type IO1 < I_TOP -type I_TOP isolated object {}; - -// @type S_TOP < TOP -// @type SO1 < S_TOP -type S_TOP service object {}; - -// @type C_TOP < TOP -// @type CO1 < C_TOP -type C_TOP client object {}; - -type TOP object {}; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/object-rec-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/object-rec-tv.bal deleted file mode 100644 index f269f36c136a..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/object-rec-tv.bal +++ /dev/null @@ -1,18 +0,0 @@ -// @type O1 = O2 -type O1 object { - O1? other; -}; - -type O2 object { - O2? other; -}; - -// @type O4 < O3 -type O3 object { - function foo(O3 other); -}; - -type O4 object { - function foo(O3 other); - function bar(O4 other); -}; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/object-resource-fn-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/object-resource-fn-tv.bal deleted file mode 100644 index 0f7843aac4fc..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/object-resource-fn-tv.bal +++ /dev/null @@ -1,32 +0,0 @@ -// @type C1 <> C2 -type C1 client object { - resource function get [int](); -}; - -// @type Ci1 <> C1 -type Ci1 client object { - resource function post [int](); -}; - -type C2 client object { - resource function get [string](); -}; - -// @type C1 < C3 -type C3 client object { - resource function get [byte](); -}; - -type Cx1 client object { - resource function get foo/[int](int x); -}; - -// @type Cx1 < Cx2 -type Cx2 client object { - resource function get foo/[byte](byte x); -}; - -// @type Cx3 <> Cx2 -type Cx3 client object { - resource function get bar/[byte]/bar(byte x); -}; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/object-simple-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/object-simple-tv.bal deleted file mode 100644 index 902997948a66..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/object-simple-tv.bal +++ /dev/null @@ -1,64 +0,0 @@ -// @type O1 = O2 -type O1 object { - public int a; -}; - -type O2 object { - public int a; -}; - -// @type O3 < O1 -type O3 object { - public int a; - public string b; -}; - -// @type O4 < O1 -type O4 object { - public byte a; -}; - -// @type OO1 = OO2 -type OO1 object { - public function foo(int a) returns int; -}; - -type OO2 object { - public function foo(int a) returns int; -}; - -// @type OO3 < OO1 -type OO3 object { - public function foo(int a, int... rest) returns int; -}; - -// @type OO4 < OO1 -type OO4 object { - public function foo(int a) returns int; - public int a; -}; - -// @type OO5 <> OO4 -type OO5 object { - public function (int a) returns int foo; - public int a; -}; - -// @type G3 <> O3 -// @type G3 < O1 -type G3 object { - public int a; - string b; -}; - -// @type OO4 <> GG4 -// @type GG4 < O1 -type GG4 object { - function foo(int a) returns int; - public int a; -}; - -// @type I1 < OO1 -type I1 object { - public isolated function foo(int a) returns int; -} diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/object-with-dependently-typed-object-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/object-with-dependently-typed-object-tv.bal deleted file mode 100644 index 629eb7bcf547..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/object-with-dependently-typed-object-tv.bal +++ /dev/null @@ -1,8 +0,0 @@ -// @type Bar < Baz -type Bar object { - public function get(typedesc td) returns td|error; -}; - -type Baz object { - public function get(typedesc td) returns anydata|error; -}; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/optional-field-record1-t.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/optional-field-record1-t.bal deleted file mode 100644 index 2fa3c00a3606..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/optional-field-record1-t.bal +++ /dev/null @@ -1,52 +0,0 @@ -type M1 map; - -type R1 record {| int a; |}; - -// @type R2 < M1 -// @type R1 < R2 -type R2 record {| int a?; |}; - -// @type R2 <> R3 -type R3 record {| int? a; |}; - -// @type R4 <> R2 -type R4 record {| int a?; string b; |}; - -type R5 record {| int a; string b; |}; - -// @type R1 < R6 -// @type R2 < R6 -// @type R4 < R6 -// @type R5 < R6 -type R6 record {| int a?; string b?; |}; - -// @type R1 < R7 -// @type R2 <> R7 -// @type R4 <> R7 -// @type R5 < R7 -// @type R7 < R6 -type R7 record {| int a; string b?; |}; - -// @type R2 < R8 -type R8 record {| int|string a?; |}; - -// @type R2 < R9 -// @type R1 < R9 -type R9 record {| int|string a?; string|boolean b?; boolean c?; |}; - -// @type R1 < R10 -// @type R2 < R10 -type R10 record {| int? a?; |}; - -// @type M2 <> R1 -// @type M2 < R2 -// @type M2 <> R3 -// @type M2 <> R4 -// @type M2 <> R5 -// @type M2 < R6 -// @type M2 <> R7 -// @type M2 < R8 -// @type M2 < R9 -// @type M2 < R10 -// @type M2 < M1 -type M2 map; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/optional-field-record2-t.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/optional-field-record2-t.bal deleted file mode 100644 index 7e17b13ff91d..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/optional-field-record2-t.bal +++ /dev/null @@ -1,52 +0,0 @@ - -type M1 map; - -type R1 record {| int a; anydata...; |}; - -// @type M1 < R2 -// @type R1 < R2 -type R2 record {| int a?; anydata...; |}; - -// @type R2 <> R3 -type R3 record {| int? a; anydata...; |}; - -// @type R4 < R2 -type R4 record {| int a?; string b; anydata...; |}; - -type R5 record {| int a; string b; anydata...; |}; - -// @type R1 <> R6 -// @type R6 < R2 -// @type R4 < R6 -// @type R5 < R6 -type R6 record {| int a?; string b?; anydata...; |}; - -// @type R7 < R1 -// @type R7 < R2 -// @type R4 <> R7 -// @type R5 < R7 -// @type R7 < R6 -type R7 record {| int a; string b?; anydata...; |}; - -// @type R2 < R8 -type R8 record {| int|string a?; anydata...; |}; - -// @type R9 <> R2 -// @type R1 <> R9 -type R9 record {| int|string a?; string|boolean b?; boolean c?; anydata...; |}; - -// @type R1 < R10 -// @type R2 < R10 -type R10 record {| int? a?; anydata...; |}; - -// @type R1 < M2 -// @type R2 < M2 -// @type R3 < M2 -// @type R4 < M2 -// @type R5 < M2 -// @type R6 < M2 -// @type R7 < M2 -// @type R8 < M2 -// @type R9 < M2 -// @type R10 < M2 -type M2 map; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/optional-field-record3-t.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/optional-field-record3-t.bal deleted file mode 100644 index 2be19be8b930..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/optional-field-record3-t.bal +++ /dev/null @@ -1,173 +0,0 @@ -// @type R11 < R12 -type R11 record {| int a; |}; - -type R12 record {| int a; anydata...; |}; - -// @type R11 < R21 -// @type R21 < R22 -type R21 record {| int a?; |}; - -// @type R11 < R22 -// @type R12 < R22 -type R22 record {| int a?; anydata...; |}; - -// @type R11 < R31 -// @type R31 < R32 -type R31 record {| int? a; |}; - -// @type R11 < R32 -// @type R12 < R32 -type R32 record {| int? a; anydata...; |}; - -// @type R41 < R22 -// @type R41 < R42 -type R41 record {| int a?; string b; |}; - -// @type R42 < R22 -type R42 record {| int a?; string b; anydata...; |}; - -// @type R51 < R12 -// @type R51 < R22 -// @type R51 < R32 -// @type R51 < R41 -// @type R51 < R42 -// @type R51 < R52 -type R51 record {| int a; string b; |}; - -// @type R52 < R12 -// @type R52 < R22 -// @type R52 < R32 -// @type R52 < R42 -type R52 record {| int a; string b; anydata...; |}; - -// @type R11 < R61 -// @type R21 < R61 -// @type R61 < R22 -// @type R41 < R61 -// @type R51 < R61 -// @type R61 < R62 -type R61 record {| int a?; string b?; |}; - -// @type R11 < R62 -// @type R21 < R62 -// @type R41 < R62 -// @type R42 < R62 -// @type R51 < R62 -// @type R52 < R62 -// @type R62 < R22 -type R62 record {| int a?; string b?; anydata...; |}; - -// @type R11 < R71 -// @type R71 < R12 -// @type R71 < R22 -// @type R71 < R32 -// @type R71 < R61 -// @type R71 < R62 -// @type R51 < R71 -// @type R71 < R72 -type R71 record {| int a; string b?; |}; - -// @type R11 < R72 -// @type R72 < R12 -// @type R72 < R22 -// @type R72 < R32 -// @type R51 < R72 -// @type R52 < R72 -// @type R72 < R62 -type R72 record {| int a; string b?; anydata...; |}; - -// @type R11 < R81 -// @type R21 < R81 -// @type R81 < R82 -type R81 record {| int|string a?; |}; - -// @type R11 < R82 -// @type R12 < R82 -// @type R21 < R82 -// @type R22 < R82 -// @type R42 < R82 -// @type R41 < R82 -// @type R51 < R82 -// @type R52 < R82 -// @type R61 < R82 -// @type R62 < R82 -// @type R71 < R82 -// @type R72 < R82 -type R82 record {| int|string a?; anydata...; |}; - -// @type R11 < R91 -// @type R21 < R91 -// @type R41 < R91 -// @type R51 < R91 -// @type R61 < R91 -// @type R71 < R91 -// @type R81 < R91 -// @type R91 < R82 -// @type R91 < R92 -type R91 record {| int|string a?; string|boolean b?; boolean c?; |}; - -// @type R11 < R92 -// @type R21 < R92 -// @type R41 < R92 -// @type R51 < R92 -// @type R61 < R92 -// @type R71 < R92 -// @type R81 < R92 -// @type R92 < R82 -type R92 record {| int|string a?; string|boolean b?; boolean c?; anydata...; |}; - -// @type R11 < R101 -// @type R21 < R101 -// @type R31 < R101 -// @type R101 < R102 -type R101 record {| int? a?; |}; - -// @type R11 < R102 -// @type R12 < R102 -// @type R21 < R102 -// @type R22 < R102 -// @type R31 < R102 -// @type R41 < R102 -// @type R42 < R102 -// @type R51 < R102 -// @type R52 < R102 -// @type R61 < R102 -// @type R62 < R102 -// @type R71 < R102 -// @type R72 < R102 -type R102 record {| int? a?; anydata...; |}; - -// @type M1 < R21 -// @type M1 < R22 -// @type M1 < R61 -// @type M1 < R62 -// @type M1 < R81 -// @type M1 < R82 -// @type M1 < R91 -// @type M1 < R92 -// @type M1 < R101 -// @type M1 < R102 -// @type M1 < M2 -type M1 map; - -// @type R11 < M2 -// @type R12 < M2 -// @type R21 < M2 -// @type R22 < M2 -// @type R31 < M2 -// @type R32 < M2 -// @type R41 < M2 -// @type R42 < M2 -// @type R51 < M2 -// @type R52 < M2 -// @type R61 < M2 -// @type R62 < M2 -// @type R71 < M2 -// @type R72 < M2 -// @type R81 < M2 -// @type R82 < M2 -// @type R91 < M2 -// @type R92 < M2 -// @type R101 < M2 -// @type R102 < M2 -type M2 map; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj1-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj1-tv.bal deleted file mode 100644 index 9481bf4bb97b..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj1-tv.bal +++ /dev/null @@ -1,41 +0,0 @@ -type B boolean; - -// @type TF = B -type TF true|false; - -// @type T < TF -type T true; - -// @type F < B -type F false; - -// @type INTEGER <> B -type INTEGER int; - -type S string; -type I int; -type N 2; -const ONE = 1; - -// @type BL[1] = B -// @type BL[2] = B -// @type BL[I] = B -// @type BL[N] = B -// @type BL[ONE] = B -type BL boolean[]; - -// @type M[S] = B -type M map; - -type f1 "f1"; -type f2 "f2"; -const FOO = "f2"; - -// @type R[f1] = INTEGER -// @type R[f2] = B -// @type R[FOO] = B -type R record {| - int f1; - boolean f2; -|}; - diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj10-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj10-tv.bal deleted file mode 100644 index b23b7c7614b1..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj10-tv.bal +++ /dev/null @@ -1,22 +0,0 @@ -type NEVER never; -type INT int; -type FLOAT float; - -type FirstFive 0|1|2|3|4|5; -type FFFloat FirstFive|float; - -type T1 [int...]; -type T2 [int, int, int...]; - -// @type T3[0] = NEVER -// @type T3[1] = NEVER -// @type T3[1] = NEVER -type T3 T1 & !T2; - -type T4 [FirstFive|float...]; -type T5 [int, int, FirstFive...]; - -// @type T6[0] = FFFloat -// @type T6[1] = FFFloat -// @type T6[3] = FFFloat -type T6 T4 & !T5; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj2-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj2-tv.bal deleted file mode 100644 index 0dd6026f4e1a..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj2-tv.bal +++ /dev/null @@ -1,6 +0,0 @@ -type I int; - -// -@type A[I] = I -// -@type A[0] = I -// -@type A[1] = I -type A [int?, int?] & ![(), ()] & ![int, ()] & ![(), int]; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj3-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj3-tv.bal deleted file mode 100644 index ce6d648ef2c7..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj3-tv.bal +++ /dev/null @@ -1,13 +0,0 @@ -type IB int|boolean; -type SB string|boolean; -type C string:Char; -type NonC string & !C; - -// @type R[C] = IB -// -@type R[NonC] = SB -type R record {| - int a; - int b; - string fieldName; - boolean...; -|}; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj4-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj4-tv.bal deleted file mode 100644 index 7fd417cabbfe..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj4-tv.bal +++ /dev/null @@ -1,11 +0,0 @@ -const ZERO = 0; -const ONE = 1; -type Index ZERO|ONE; -type Int int; -type Str string; -type IntStr Int|Str; - -// @type T[ZERO] = Int -// @type T[ONE] = Str -// @type T[Index] = IntStr -type T [int, string]; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj5-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj5-tv.bal deleted file mode 100644 index 3e0de9d8ed3f..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj5-tv.bal +++ /dev/null @@ -1,14 +0,0 @@ -const THREE = 3; -type F float; -type Int int; -type ISF int|string|float; -type IF int|float; -type SF string|float; -type T02 0|2; -type T12 1|2; - -// @type T[THREE] = F -// @type T[Int] = ISF -// @type T[T02] = IF -// @type T[T12] = SF -type T [int, string, float...]; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj6-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj6-tv.bal deleted file mode 100644 index 7db777560fb1..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj6-tv.bal +++ /dev/null @@ -1,19 +0,0 @@ -const THREE = 3; -const FOUR = 4; -type F float; -type Int int; -type ISF int|string|float; -type IF int|float; -type SF string|float; -type T02 0|2; -type T12 1|2; -type NEVER never; - -type T1 [int, string, float...]; - -// @type T[THREE] = F -// @type T[FOUR] = NEVER -// @type T[Int] = ISF -// @type T[T02] = IF -// @type T[T12] = SF -type T T1 & any[4]; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj7-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj7-tv.bal deleted file mode 100644 index 00c78786b66d..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj7-tv.bal +++ /dev/null @@ -1,25 +0,0 @@ -type NEVER never; -type BOOL boolean; -type BOOLOPT boolean?; -type INT int; -type NIL (); -type INTOPT int?; -type STROPT string?; -type INTSTROPT int|string?; -type INT_FLOAT_BOOL_OPT int|float|boolean?; -type STR_FLOAT_BOOL_OPT string|float|boolean?; -type INT_STR_FLOAT_BOOL_OPT int|string|float|boolean?; - -type C01 0|1; -type C02 0|2; -type C12 1|2; - -type T1 [int?, string?, float|boolean...]; -type T2 [int, (string|float)...]; -// @type T3[0] = INTOPT -// @type T3[1] = STROPT -// @type T3[C01] = INTSTROPT -// @type T3[C02] = INT_FLOAT_BOOL_OPT -// @type T3[C12] = STR_FLOAT_BOOL_OPT -// @type T3[INT] = INT_STR_FLOAT_BOOL_OPT -type T3 T1 & !T2; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj8-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj8-tv.bal deleted file mode 100644 index 080363062f2d..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj8-tv.bal +++ /dev/null @@ -1,20 +0,0 @@ -type INT int; -type STRING string; -type STROPT string?; -type NIL (); - -type C01 0|1; -type C02 0|2; -type C12 1|2; - -type T1 [int?, string...]; -type T2 [int, (string|float)...]; -// @type T3[0] = NIL -// @type T3[1] = STRING -// @type T3[2] = STRING -// @type T3[100] = STRING -// @type T3[C01] = STROPT -// @type T3[C02] = STROPT -// @type T3[C12] = STRING -// @type T3[INT] = STROPT -type T3 T1 & !T2; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj9-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj9-tv.bal deleted file mode 100644 index b84619878962..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/proj9-tv.bal +++ /dev/null @@ -1,30 +0,0 @@ -type INT int; -type INTFLOAT int|float; -type NEVER never; - -type C01 0|1; -type C02 0|2; -type C12 1|2; - -type NOTC01 !C01 & int; - -type T1 int[100000]; -type T2 [C01, C01, C01, (int|float)...]; - - -// @type T3[0] = NOTC01 -// @type T3[100] = INT -// @type T3[1000] = INT -// @type T3[10000] = INT -// @type T3[99999] = INT -// @type T3[100000] = NEVER -type T3 T1 & !T2; - -// @type T4[0] = C01 -// @type T4[1] = C01 -// @type T4[2] = C01 -// @type T4[3] = INTFLOAT -// @type T4[100] = INTFLOAT -// @type T4[1000] = INTFLOAT -// @type T4[100000] = INTFLOAT -type T4 T2 & !T1; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/record-proj-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/record-proj-tv.bal deleted file mode 100644 index fc65b365f1eb..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/record-proj-tv.bal +++ /dev/null @@ -1,45 +0,0 @@ -type A record {| - int x; - string y; -|}; - -// @type B[XorY] = IorS -// @type B[other] = NEVER -type B record {| - string x; - int y; -|}; - -// @type C[other] = BOOLEAN -// @type C[XorY] = IorS -// @type C[XorYorOther] = IorSOrB -type C record {| - string x; - int y; - float z; - boolean...; -|}; - -type IorS int|string; -type IorSOrB IorS|boolean; -type IorSorF IorS|float; - -const x = "x"; -const z = "z"; -const other = "other"; -type XorY "x"|"y"; -type NEVER never; -type BOOLEAN boolean; -type FLOAT float; - -type XorYorOther XorY|other; - -// @type AorB[x] = IorS -// @type AorB[XorY] = IorS -type AorB A|B; - -// @type AorBorC[x] = IorS -// @type AorBorC[z] = FLOAT -// @type AorBorC[other] = BOOLEAN -// @type AorBorC[XorYorOther] = IorSOrB -type AorBorC AorB|C; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/record-t.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/record-t.bal deleted file mode 100644 index b6ad2c517c54..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/record-t.bal +++ /dev/null @@ -1,16 +0,0 @@ -// the order of type defns are intentional - -type T1 record {| - 65 X; -|}; - -type T2 record {| - int:Signed8 X; -|}; - -// @type T1 < T3 -type T3 T4|T2; - -type T4 record {| - int:Signed8 a; -|}; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/recursive-record-t.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/recursive-record-t.bal deleted file mode 100644 index 1a6b0375ae40..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/recursive-record-t.bal +++ /dev/null @@ -1,9 +0,0 @@ -type Bdd Node|boolean; - -// @type Node < Bdd -type Node readonly & record {| - int atom; - Bdd left; - Bdd middle; - Bdd right; -|}; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/stream-recursive-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/stream-recursive-tv.bal deleted file mode 100644 index 5b96f55fc9ca..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/stream-recursive-tv.bal +++ /dev/null @@ -1,8 +0,0 @@ -// @type SR < S -type SR stream; - -type S stream; - -// @type S1 < SR -// @type S1 < S -type S1 stream<()>; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/stream-subtype-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/stream-subtype-tv.bal deleted file mode 100644 index 20237c2bc796..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/stream-subtype-tv.bal +++ /dev/null @@ -1,10 +0,0 @@ -// @type I < U1 -// @type I < U2 -// @type S < U1 -// @type S < U2 -// @type U1 < U2 - -type I stream; -type S stream; -type U1 I|S; -type U2 stream; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/stream-subtype2-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/stream-subtype2-tv.bal deleted file mode 100644 index 32ccf067c9fe..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/stream-subtype2-tv.bal +++ /dev/null @@ -1,19 +0,0 @@ -// @type I < J -// @type I < J1 -// @type I < J2 -type I stream; - -// @type S < J -// @type S < J1 -// @type S < J2 -type S stream; - -type T int|string|(); -// @type J = J1 -type J stream; -type J1 stream; - -// @type J < J2 -// @type J1 < J2 -type J2 stream; -type J3 stream; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/string-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/string-tv.bal deleted file mode 100644 index db4f84e356ac..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/string-tv.bal +++ /dev/null @@ -1,16 +0,0 @@ -// @type U1 < String -// @type U1 < Char -type U1 "අ"; -// @type U2 < String -// @type U2 < Char -type U2 "🛧"; -// @type C1 < String -// @type C1 < Char -type C1 "a"; - -// @type S1 < String -// @type S1 <> Char -type S1 "abc"; - -type String string; -type Char string:Char; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/table-readonly-t.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/table-readonly-t.bal deleted file mode 100644 index ebebd154b787..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/table-readonly-t.bal +++ /dev/null @@ -1,25 +0,0 @@ -type R record {| - int id; - int f; -|}; - -type R1 record {| - int id; - int f; - float d; -|}; - -type READ readonly; - -// @type W < T -// @type W < READ -// @type T < READ -// @type W < Y1 -// @type Y1 <> T -// -@type Z < Y1 -// -@type Z <> T -type T table & readonly | table & readonly; -type W table & readonly; -type Y1 table; -type Y table; -type Z table & !readonly; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/table-t.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/table-t.bal deleted file mode 100644 index 9c52d92c3703..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/table-t.bal +++ /dev/null @@ -1,13 +0,0 @@ -type X1 record {| - int id; - string f; -|}; - -type X2 record {| - int id; - string:Char f; -|}; - -// @type T2 < T1 -type T1 table; -type T2 table; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/table2-t.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/table2-t.bal deleted file mode 100644 index f7e40035b911..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/table2-t.bal +++ /dev/null @@ -1,31 +0,0 @@ -type R1 record {| - int id; - string f; -|}; - -type R2 record {| - int id; - string f; - float d; -|}; - -type R3 record {| - int id; - string:Char f; -|}; - -type READ readonly; - -type T1 table; -type T2 table; -type T3 table; - -// @type TI < T1 -// @type TI = T3 -// @type T1 < TU -// @type T2 < TU -type TI T1 & T3; -type TU T1|T2; - -// -@type T1 <> TC -type TC !T1; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/table3-t.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/table3-t.bal deleted file mode 100644 index 0c639556f062..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/table3-t.bal +++ /dev/null @@ -1,27 +0,0 @@ -type X1 record {| - int x; -|}; - -type X2 record {| - string x; -|}; - -type T1 table; -type T2 table; -type T3 T1|T2; -// @type T3 < T4 -type T4 table; - - -type X3 map; -type X4 map; - -type T5 table; -type T6 table; -type T7 T5|T6; -// @type T7 < T8 -type T8 table; - -// @type T8 < T9 -// @type T7 < T9 -type T9 table>; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/test_test.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/test_test.bal deleted file mode 100644 index 009d8ac1322c..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/test_test.bal +++ /dev/null @@ -1,17 +0,0 @@ -type I int; -type F float; -type S string; - -// @type I <> F - -type K decimal; - -type M map; - -// @type M[S] = I - -// @type L[I] = I -type L int[]; - -// @type SL[I] = S -type SL string[]; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/tuple1-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/tuple1-tv.bal deleted file mode 100644 index cfac1e3640a7..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/tuple1-tv.bal +++ /dev/null @@ -1,16 +0,0 @@ -type R record {| - int f1; - boolean f2; -|}; - -// @type A1 = T1 -type A1 int[]; -type T1 [int...]; - -// @type A2 = T2 -type A2 R[]; -type T2 [R...]; - -// @type A3 = T3 -type A3 T2[]; -type T3 [T2...]; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/tuple2-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/tuple2-tv.bal deleted file mode 100644 index d0f64d6d92ad..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/tuple2-tv.bal +++ /dev/null @@ -1,14 +0,0 @@ -type IS16 int:Signed16; -type I int; -type I2 int?; - -// @type T1 <> T2 -type T1 [int, string]; -type T2 [string, int]; - -// @type T4 < T3 -// @type T3[0] = I2 -// @type T3[1] = I -// @type T4[1] = IS16 -type T3 [int?, int, any]; -type T4 [int, int:Signed16, int]; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/tuple3-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/tuple3-tv.bal deleted file mode 100644 index 9a12b1aed2cc..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/tuple3-tv.bal +++ /dev/null @@ -1,20 +0,0 @@ -type R record {| - int f1; - boolean f2; -|}; - -type R1 record {| - int f1; - boolean f2; -|}; - -type R2 record {| - int:Signed16 f1; - boolean f2; -|}; - -// @type T1 = T -// @type T2 < T -type T [R...]; -type T1 [R1...]; -type T2 [R2...]; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/tuple4-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/tuple4-tv.bal deleted file mode 100644 index 537b8c836d1d..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/tuple4-tv.bal +++ /dev/null @@ -1,7 +0,0 @@ -// @type T2 < T1 -type T1 [int...]; -type T2 [int,int...]; - -// @type T3 < T1 -type T4 [int?,int?...]; -type T3 [int, int, int, int...]; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/typedesc-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/typedesc-tv.bal deleted file mode 100644 index 146649ab6d7e..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/typedesc-tv.bal +++ /dev/null @@ -1,10 +0,0 @@ -// @type I < U1 -// @type I < U2 -// @type S < U1 -// @type S < U2 -// @type U1 < U2 - -type I typedesc; -type S typedesc; -type U1 I|S; -type U2 typedesc; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/xml-complex-ro-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/xml-complex-ro-tv.bal deleted file mode 100644 index 6716b76bfc66..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/xml-complex-ro-tv.bal +++ /dev/null @@ -1,38 +0,0 @@ -type X xml; -type RX readonly & X; - -type N xml; -type T xml:Text; -type E readonly & xml:Element; -type P readonly & xml:ProcessingInstruction; -type C readonly & xml:Comment; -type XE xml; -type XP xml

; -type XC xml; - -type ReadOnlyFlat T|E|P|C; - -// -@type NonEmptyRoSingletons < ReadOnlyFlat -// -@type NonEmptyRoSingletons <> T -// -@type NonEmptyRoSingletons <> N -// -@type E < NonEmptyRoSingletons -// -@type P < NonEmptyRoSingletons -// -@type C < NonEmptyRoSingletons -type NonEmptyRoSingletons ReadOnlyFlat & !N; - -// -@type NonEmptyRoSingletons < UX -type UX XE|XP|XC|T; - -// -@type XNonEmptyRoSingletons = RX -// -@type XNonEmptyRoSingletons < X -type XNonEmptyRoSingletons xml; - -// @type XUX = RX -type XUX xml; - -type NEVER never; -type RWX X & !readonly; - -// -@type RX_UNION_RO = X -type RX_UNION_RO RX | RWX; - diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/xml-complex-rw-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/xml-complex-rw-tv.bal deleted file mode 100644 index 9c9e293ca8c9..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/xml-complex-rw-tv.bal +++ /dev/null @@ -1,30 +0,0 @@ -type X xml; - -type N xml; -type T xml:Text; -type E xml:Element; -type P xml:ProcessingInstruction; -type C xml:Comment; -type XE xml; -type XP xml

; -type XC xml; - -type S T|E|P|C; - -// -@type NonEmptyS < S -// -@type NonEmptyS <> T -// -@type NonEmptyS <> N -// -@type E < NonEmptyS -// -@type P < NonEmptyS -// -@type C < NonEmptyS -type NonEmptyS S & !N; - -// -@type NonEmptyS < UX -type UX XE|XP|XC|T; - -// -@type XNonEmptyS = X -type XNonEmptyS xml; - -// @type XUX = X -type XUX xml; - diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/xml-never-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/xml-never-tv.bal deleted file mode 100644 index 7a4059117df9..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/xml-never-tv.bal +++ /dev/null @@ -1,31 +0,0 @@ -type N xml; - -// @type N = NS -type NS xml; - -// @type N <> E -type E xml:Element; - -// @type N < T -type T xml:Text; - -// @type N <> C -type C xml:Comment; - -// @type N <> P -type P xml:ProcessingInstruction; - -// @type N < ES -type ES xml; - -// @type N < CS -type CS xml; - -// @type N < TS -type TS xml; - -// @type N < PS -type PS xml; - -// @type ENS = ES -type ENS xml; diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/xml-readonly-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/xml-readonly-tv.bal deleted file mode 100644 index 1256d31d26e7..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/xml-readonly-tv.bal +++ /dev/null @@ -1,33 +0,0 @@ -type R readonly; -type X xml; - -// @type N < R -type N xml; - -// @type T < R -// @type N < T -type T xml:Text; - -// @type N = RN -type RN readonly & N; - -// @type RO_E < R -type RO_E xml:Element & readonly; - -// @type RO_C < R -type RO_C xml:Comment & readonly; - -// @type RO_P < R -type RO_P xml:ProcessingInstruction & readonly; - -// @type RX < R -// @type RX < X -type RX readonly & X; - -// @type RX = RO_XML -type RO_XML xml; - -// @type RO_XML_INTERSECTION = RO_XML -// @type RO_XML_INTERSECTION = RX -type RO_XML_INTERSECTION RO_XML & readonly; - diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/xml-sequence-tv.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/xml-sequence-tv.bal deleted file mode 100644 index e37193290a6e..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/xml-sequence-tv.bal +++ /dev/null @@ -1,40 +0,0 @@ - -type X xml; - -// @type X = Y -type Y xml; - -// @type X = P -// @type Y = P -type P xml; - -// @type X = Q -type Q xml

; - -// @type U < X -type U xml; - -// @type V < X -// @type U < V -type V xml; - -// @type N < X -// @type N < V -// @type N < U -type N xml; - -// @type N <> E -// @type E < V -// @type E < X -type E xml:Element; - -// @type XE = X -type XE xml; - -// @type XEU = X -type XEU xml|E; - -type T xml:Text; - -// @type T = XT -type XT xml; \ No newline at end of file diff --git a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/xml-te.bal b/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/xml-te.bal deleted file mode 100644 index c923d65298fd..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/test-src/type-rel/xml-te.bal +++ /dev/null @@ -1,7 +0,0 @@ -type X xml; -type RX readonly & X; -type NEVER never; - -type RWX X & !readonly; - -type RX_MINUS_RO RX & RWX; // @error diff --git a/tests/jballerina-semtype-port-test/src/test/resources/testng.xml b/tests/jballerina-semtype-port-test/src/test/resources/testng.xml deleted file mode 100644 index e1138781de8e..000000000000 --- a/tests/jballerina-semtype-port-test/src/test/resources/testng.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - diff --git a/tests/jballerina-semtype-test/src/test/java/io/ballerina/test/SemTypeTest.java b/tests/jballerina-semtype-test/src/test/java/io/ballerina/test/SemTypeTest.java index d494a411fcf3..80a1c769613e 100644 --- a/tests/jballerina-semtype-test/src/test/java/io/ballerina/test/SemTypeTest.java +++ b/tests/jballerina-semtype-test/src/test/java/io/ballerina/test/SemTypeTest.java @@ -55,7 +55,7 @@ */ public class SemTypeTest { - private Types types; + private final Types types = Types.getInstance(new CompilerContext()); @DataProvider(name = "filePathProvider") public Object[] filePathProvider() { @@ -63,7 +63,7 @@ public Object[] filePathProvider() { List files = new ArrayList<>(); for (File file : Objects.requireNonNull(dir.listFiles())) { String fileName = file.getName(); - if (!fileName.endsWith(".bal") || fileName.endsWith(FAILING_FILE) || fileName.endsWith(DISABLED_FILE)) { + if (fileName.endsWith(FAILING_FILE) || fileName.endsWith(DISABLED_FILE)) { continue; } files.add(file.getAbsolutePath()); @@ -83,9 +83,6 @@ public void testSubTypeRelationship(String filePath) throws IOException { private Set actualSubTypeRelations(String filePath) { CompileResult compileResult = BCompileUtil.compile(filePath); BLangPackage bLangPackage = (BLangPackage) compileResult.getAST(); - // Need to use the same semtypeEnv used in the compiler as we keep cache for some BTypes. - types = new Types(new CompilerContext(), bLangPackage.semtypeEnv); - List bTypeDefinitionSymbols = new ArrayList<>(); for (Scope.ScopeEntry value : bLangPackage.symbol.scope.entries.values()) { BSymbol bSymbol = value.symbol; diff --git a/tests/jballerina-semtype-test/src/test/resources/test-src/proj1-f.bal b/tests/jballerina-semtype-test/src/test/resources/test-src/proj1-f.bal new file mode 100644 index 000000000000..980df3145686 --- /dev/null +++ b/tests/jballerina-semtype-test/src/test/resources/test-src/proj1-f.bal @@ -0,0 +1,5 @@ +// B<:TF +type B boolean; +type TF true|false; +// B should be a subtype of TF +// BUG #34711 diff --git a/tests/jballerina-semtype-test/src/test/resources/test-src/proj1.bal b/tests/jballerina-semtype-test/src/test/resources/test-src/proj1.bal index 48de5616ac03..9f50bee77dec 100644 --- a/tests/jballerina-semtype-test/src/test/resources/test-src/proj1.bal +++ b/tests/jballerina-semtype-test/src/test/resources/test-src/proj1.bal @@ -1,4 +1,3 @@ // TF<:B -// B<:TF type B boolean; type TF true|false; diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/nativeimpl/jvm/runtime/api/tests/TypeReference.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/nativeimpl/jvm/runtime/api/tests/TypeReference.java index 688d474423d0..d5b51e67fa30 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/nativeimpl/jvm/runtime/api/tests/TypeReference.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/nativeimpl/jvm/runtime/api/tests/TypeReference.java @@ -18,7 +18,6 @@ package org.ballerinalang.nativeimpl.jvm.runtime.api.tests; import io.ballerina.runtime.api.creators.ErrorCreator; -import io.ballerina.runtime.api.types.MapType; import io.ballerina.runtime.api.types.ObjectType; import io.ballerina.runtime.api.types.Parameter; import io.ballerina.runtime.api.types.ReferenceType; @@ -40,6 +39,7 @@ import io.ballerina.runtime.internal.types.BErrorType; import io.ballerina.runtime.internal.types.BFunctionType; import io.ballerina.runtime.internal.types.BIntersectionType; +import io.ballerina.runtime.internal.types.BMapType; import io.ballerina.runtime.internal.types.BParameterizedType; import io.ballerina.runtime.internal.types.BRecordType; import io.ballerina.runtime.internal.types.BStreamType; @@ -112,7 +112,7 @@ public static Boolean validateIntersectionType(BTypedesc typedesc) { } public static Boolean validateMapType(BTypedesc typedesc) { - MapType mapType = (MapType) TypeUtils.getImpliedType(typedesc.getDescribingType()); + BMapType mapType = (BMapType) TypeUtils.getImpliedType(typedesc.getDescribingType()); if (mapType.getConstrainedType().getTag() != TypeTags.TYPE_REFERENCED_TYPE_TAG) { throw ErrorCreator.createError(StringUtils.fromString("map type API provided a non type reference " + diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/nativeimpl/jvm/tests/VariableReturnType.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/nativeimpl/jvm/tests/VariableReturnType.java index 4e7ed88a701d..891e1beb46a4 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/nativeimpl/jvm/tests/VariableReturnType.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/nativeimpl/jvm/tests/VariableReturnType.java @@ -198,10 +198,10 @@ public static MapValue getRecord(BTypedesc td) { BRecordType recType = (BRecordType) td.getDescribingType(); MapValueImpl person = new MapValueImpl<>(recType); - if (recType.getName().contains("Person")) { + if (recType.getName().equals("Person")) { person.put(NAME, JOHN_DOE); person.put(AGE, 20); - } else if (recType.getName().contains("Employee")) { + } else if (recType.getName().equals("Employee")) { person.put(NAME, JANE_DOE); person.put(AGE, 25); person.put(DESIGNATION, SOFTWARE_ENGINEER); @@ -226,7 +226,7 @@ public static Object getVariedUnion(long x, BTypedesc td1, BTypedesc td2) { } MapValueImpl rec = new MapValueImpl<>(type2); - if (type2.getName().contains("Person")) { + if (type2.getName().equals("Person")) { rec.put(NAME, JOHN_DOE); rec.put(AGE, 20); } else { @@ -279,10 +279,10 @@ private static Object getValue(Type type) { BRecordType recType = (BRecordType) type; MapValueImpl person = new MapValueImpl<>(recType); - if (recType.getName().contains("Person")) { + if (recType.getName().equals("Person")) { person.put(NAME, JOHN_DOE); person.put(AGE, 20); - } else if (recType.getName().contains("Employee")) { + } else if (recType.getName().equals("Employee")) { person.put(NAME, JANE_DOE); person.put(AGE, 25); person.put(DESIGNATION, SOFTWARE_ENGINEER); diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/action/start/StartActionTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/action/start/StartActionTest.java index 3a403d6e41ee..08e3b060a65e 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/action/start/StartActionTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/action/start/StartActionTest.java @@ -59,6 +59,7 @@ public void testStartActionNegative() { BAssertUtil.validateError(result, indx++, "'wait' cannot be used with actions", 72, 18); BAssertUtil.validateError(result, indx++, "action invocation as an expression not allowed here", 72, 28); BAssertUtil.validateError(result, indx++, "action invocation as an expression not allowed here", 76, 25); + BAssertUtil.validateError(result, indx++, "incompatible types: expected 'other', found 'int'", 90, 13); BAssertUtil.validateError(result, indx++, "incompatible types: '(int[]|error)' is not an iterable collection" , 90, 22); BAssertUtil.validateError(result, indx++, "'wait' cannot be used with actions", 90, 27); diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/bala/functions/DependentlyTypedFunctionsBalaTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/bala/functions/DependentlyTypedFunctionsBalaTest.java index 9c7d8b31021a..66ce02a19730 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/bala/functions/DependentlyTypedFunctionsBalaTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/bala/functions/DependentlyTypedFunctionsBalaTest.java @@ -50,7 +50,7 @@ public void testRuntimeCastError() { @Test(expectedExceptions = BLangTestException.class, expectedExceptionsMessageRegExp = ".*error: \\{ballerina}TypeCastError \\{\"message\":\"incompatible types:" + - " 'PersonDTBT' cannot be cast to 'int'\"}.*") + " 'Person' cannot be cast to 'int'\"}.*") public void testCastingForInvalidValues() { BRunUtil.invoke(result, "testCastingForInvalidValues"); } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/binaryoperations/EqualAndNotEqualOperationsTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/binaryoperations/EqualAndNotEqualOperationsTest.java index 0ab237cfc05f..acbed8f5c684 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/binaryoperations/EqualAndNotEqualOperationsTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/binaryoperations/EqualAndNotEqualOperationsTest.java @@ -127,8 +127,7 @@ public Object[] getMapTestFunctions() { return new String[]{ "checkMapEqualityPositive", "checkMapEqualityNegative", "checkComplexMapEqualityPositive", "checkComplexMapEqualityNegative", "checkUnionConstrainedMapsPositive", - "checkUnionConstrainedMapsNegative", "testEmptyMapAndRecordEquality", - "checkEqualityOfMapsOfIncompatibleConstraintTypes" + "checkUnionConstrainedMapsNegative", "testEmptyMapAndRecordEquality" }; } @@ -201,18 +200,6 @@ public void selfAndCyclicReferencingFunctions(String testFunctionName) { BRunUtil.invoke(result, testFunctionName); } - @Test(dataProvider = "getReadonlyEqualityFunctions") - public void testReadonlyEquality(String testFunctionName) { - BRunUtil.invoke(result, testFunctionName); - } - - @DataProvider(name = "getReadonlyEqualityFunctions") - public Object[] getReadonlyEqualityFunctions() { - return new String[]{ - "readonlyMapEquality", "readonlyListEquality" - }; - } - @Test(description = "Test equal and not equal with errors") public void testEqualAndNotEqualNegativeCases() { int i = 0; @@ -220,43 +207,50 @@ public void testEqualAndNotEqualNegativeCases() { validateError(resultNegative, i++, "operator '!=' not defined for 'int' and 'string'", 20, 24); validateError(resultNegative, i++, "operator '==' not defined for 'int[2]' and 'string[2]'", 26, 21); validateError(resultNegative, i++, "operator '!=' not defined for 'int[2]' and 'string[2]'", 26, 33); + validateError(resultNegative, i++, "operator '==' not defined for 'map' and 'map'", 38, 21); + validateError(resultNegative, i++, "operator '!=' not defined for 'map' and 'map'", 38, 33); + validateError(resultNegative, i++, "operator '==' not defined for 'map<(string|int)>' and 'map'", + 42, 21); + validateError(resultNegative, i++, "operator '!=' not defined for 'map<(string|int)>' and 'map'", + 42, 33); validateError(resultNegative, i++, "operator '==' not defined for '[string,int]' and '[boolean,float]'", - 38, 21); + 50, 21); validateError(resultNegative, i++, "operator '!=' not defined for '[string,int]' and '[boolean,float]'", - 38, 33); + 50, 33); validateError(resultNegative, i++, "operator '==' not defined for '[(float|int),int]' and '[boolean,int]'", - 42, 21); + 54, 21); validateError(resultNegative, i++, "operator '!=' not defined for '[(float|int),int]' and '[boolean,int]'", - 42, 33); - validateError(resultNegative, i++, "operator '==' not defined for 'Employee' and 'Person'", 50, 17); - validateError(resultNegative, i++, "operator '!=' not defined for 'Employee' and 'Person'", 50, 29); - validateError(resultNegative, i++, "operator '==' not defined for 'map' and 'ClosedDept'", 59, 23); - validateError(resultNegative, i++, "operator '!=' not defined for 'ClosedDept' and 'map'", 59, 35); - validateError(resultNegative, i++, "operator '==' not defined for 'int[]' and '[float,float]'", 66, 23); - validateError(resultNegative, i++, "operator '!=' not defined for 'int[]' and '[float,float]'", 66, 35); - validateError(resultNegative, i++, "operator '==' not defined for 'int[]' and '[int,float]'", 69, 23); - validateError(resultNegative, i++, "operator '!=' not defined for '[int,float]' and 'int[]'", 69, 35); - validateError(resultNegative, i++, "operator '==' not defined for 'Employee' and '()'", 117, 9); - validateError(resultNegative, i++, "operator '==' not defined for 'Foo' and '()'", 123, 9); + 54, 33); + validateError(resultNegative, i++, "operator '==' not defined for 'Employee' and 'Person'", 62, 17); + validateError(resultNegative, i++, "operator '!=' not defined for 'Employee' and 'Person'", 62, 29); + validateError(resultNegative, i++, "operator '==' not defined for 'EmployeeWithOptionalId' and " + + "'PersonWithOptionalId'", 66, 17); + validateError(resultNegative, i++, "operator '!=' not defined for 'EmployeeWithOptionalId' and " + + "'PersonWithOptionalId'", 66, 31); + validateError(resultNegative, i++, "operator '==' not defined for 'map' and 'ClosedDept'", 75, 23); + validateError(resultNegative, i++, "operator '!=' not defined for 'ClosedDept' and 'map'", 75, 35); + validateError(resultNegative, i++, "operator '==' not defined for 'int[]' and '[float,float]'", 82, 23); + validateError(resultNegative, i++, "operator '!=' not defined for 'int[]' and '[float,float]'", 82, 35); + validateError(resultNegative, i++, "operator '==' not defined for 'int[]' and '[int,float]'", 85, 23); + validateError(resultNegative, i++, "operator '!=' not defined for '[int,float]' and 'int[]'", 85, 35); + validateError(resultNegative, i++, "operator '==' not defined for 'Employee' and '()'", 138, 9); + validateError(resultNegative, i++, "operator '==' not defined for 'Foo' and '()'", 144, 9); validateError(resultNegative, i++, "operator '==' not defined for 'function () returns (string)' and '()'", - 129, 9); - validateError(resultNegative, i++, "operator '==' not defined for '[int,map]' and '[int,float]'", 142, + 150, 9); + validateError(resultNegative, i++, "operator '!=' not defined for 'readonly' and 'map'", + 168, 12); + validateError(resultNegative, i++, "operator '==' not defined for '[int,map]' and '[int,float]'", 179, 23); - validateError(resultNegative, i++, "operator '!=' not defined for '[int,float]' and '[int,map]'", 142, + validateError(resultNegative, i++, "operator '!=' not defined for '[int,float]' and '[int,map]'", 179, 35); - validateError(resultNegative, i++, "operator '==' not defined for 'MyObject' and '()'", 145, + validateError(resultNegative, i++, "operator '==' not defined for 'MyObject' and '()'", 182, 15); - validateError(resultNegative, i++, "operator '!=' not defined for 'MyObject' and '()'", 145, + validateError(resultNegative, i++, "operator '!=' not defined for 'MyObject' and '()'", 182, 30); - validateError(resultNegative, i++, "operator '==' not defined for 'MyObject' and 'MyObject'", 147, + validateError(resultNegative, i++, "operator '==' not defined for 'MyObject' and 'MyObject'", 184, 15); - validateError(resultNegative, i++, "operator '!=' not defined for 'MyObject' and 'MyObject'", 147, + validateError(resultNegative, i++, "operator '!=' not defined for 'MyObject' and 'MyObject'", 184, 32); - validateError(resultNegative, i++, "operator '!=' not defined for 'FloatOne' and 'FloatTwo'", 161, 18); - validateError(resultNegative, i++, "operator '==' not defined for 'FloatOne' and 'FloatTwo'", 161, 45); - validateError(resultNegative, i++, "operator '==' not defined for 'IntOne' and 'IntTwo'", 162, 19); - validateError(resultNegative, i++, "operator '!=' not defined for 'IntOne' and 'IntTwo'", 162, 44); - validateError(resultNegative, i++, "operator '==' not defined for 'Array' and 'Mapping'", 171, 17); Assert.assertEquals(resultNegative.getErrorCount(), i); } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/binaryoperations/NegativeTypeTestExprTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/binaryoperations/NegativeTypeTestExprTest.java index 222aba4fbee2..bb2f5f9bbd11 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/binaryoperations/NegativeTypeTestExprTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/binaryoperations/NegativeTypeTestExprTest.java @@ -79,6 +79,8 @@ public void testNegativeTypeTestExprNegative() { "expression will always evaluate to 'false'", 131, 17); BAssertUtil.validateHint(negativeResult, i++, "unnecessary condition: expression will always evaluate to 'true'", 131, 32); + BAssertUtil.validateError(negativeResult, i++, "incompatible types: 'int[]' will not be matched to 'float[]'", + 132, 17); BAssertUtil.validateHint(negativeResult, i++, "expression will always evaluate to 'false'", 133, 17); BAssertUtil.validateHint(negativeResult, i++, @@ -168,7 +170,11 @@ public void testNegativeTypeTestExprNegative() { BAssertUtil.validateError(negativeResult, i++, "incompatible types: 'ClosedRecordWithIntField' will not be matched to " + "'record {| int i; string s; |}'", 297, 17); + BAssertUtil.validateError(negativeResult, i++, "incompatible types: 'object { }[]' will not be matched to " + + "'anydata'", 330, 10); BAssertUtil.validateWarning(negativeResult, i++, "unused variable 'p'", 331, 9); + BAssertUtil.validateError(negativeResult, i++, "incompatible types: 'anydata' will not be matched to 'object " + + "{ }[]'", 336, 10); BAssertUtil.validateError(negativeResult, i++, "incompatible types: 'Record' will not be matched to " + "'RecordWithIntFieldAndNeverRestField'", 358, 17); BAssertUtil.validateError(negativeResult, i++, "incompatible types: 'Record' will not be matched to " + diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/binaryoperations/RefEqualAndNotEqualOperationsTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/binaryoperations/RefEqualAndNotEqualOperationsTest.java index 5c05d0fb49fe..c449c3e2e41f 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/binaryoperations/RefEqualAndNotEqualOperationsTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/binaryoperations/RefEqualAndNotEqualOperationsTest.java @@ -376,6 +376,16 @@ public void testRefEqualNegativeCases() { validateError(resultNegative, i++, "operator '!==' not defined for 'int' and 'string'", 20, 25); validateError(resultNegative, i++, "operator '===' not defined for 'int[2]' and 'string[2]'", 26, 21); validateError(resultNegative, i++, "operator '!==' not defined for 'int[2]' and 'string[2]'", 26, 34); + validateError(resultNegative, i++, "operator '===' not defined for '(float|int)?[]' and '(boolean|xml)?[]'", 30, + 21); + validateError(resultNegative, i++, "operator '!==' not defined for '(float|int)?[]' and '(boolean|xml)?[]'", 30, + 34); + validateError(resultNegative, i++, "operator '===' not defined for 'map' and 'map'", 38, 21); + validateError(resultNegative, i++, "operator '!==' not defined for 'map' and 'map'", 38, 34); + validateError(resultNegative, i++, "operator '===' not defined for 'map<(string|int)>' and 'map'", 42, + 21); + validateError(resultNegative, i++, "operator '!==' not defined for 'map<(string|int)>' and 'map'", 42, + 34); validateError(resultNegative, i++, "operator '===' not defined for '[string,int]' and '[boolean,float]'", 50, 21); validateError(resultNegative, i++, "operator '!==' not defined for '[string,int]' and '[boolean,float]'", 50, @@ -390,6 +400,8 @@ public void testRefEqualNegativeCases() { "xml])' and 'json'", 68, 21); validateError(resultNegative, i++, "operator '!==' not defined for '(record {| xml x; anydata...; |}|[string," + "xml])' and 'json'", 68, 34); + validateError(resultNegative, i++, "operator '===' not defined for 'Abc' and 'Def'", 76, 12); + validateError(resultNegative, i++, "operator '!==' not defined for 'Def' and 'Abc'", 76, 25); Assert.assertEquals(resultNegative.getErrorCount(), i); } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/binaryoperations/TypeTestExprTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/binaryoperations/TypeTestExprTest.java index 84360a8f5b7d..ec14e679b854 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/binaryoperations/TypeTestExprTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/binaryoperations/TypeTestExprTest.java @@ -89,6 +89,8 @@ public void testTypeTestExprNegative() { "unnecessary condition: expression will always evaluate to 'true'", 131, 17); BAssertUtil.validateHint(negativeResult, i++, "unnecessary condition: expression will always evaluate to 'true'", 131, 31); + BAssertUtil.validateError(negativeResult, i++, "incompatible types: 'int[]' will not be matched to 'float[]'", + 132, 17); BAssertUtil.validateHint(negativeResult, i++, "unnecessary condition: expression will always evaluate to 'true'", 133, 17); BAssertUtil.validateHint(negativeResult, i++, @@ -173,12 +175,15 @@ public void testTypeTestExprNegative() { BAssertUtil.validateError(negativeResult, i++, "incompatible types: 'ClosedRecordWithIntField' will not be matched to " + "'record {| int i; string s; |}'", 297, 17); + BAssertUtil.validateError(negativeResult, i++, "incompatible types: 'object { }[]' will not be matched to " + + "'anydata'", 330, 8); + BAssertUtil.validateError(negativeResult, i++, "incompatible types: 'anydata' will not be matched to 'object " + + "{ }[]'", 336, 8); BAssertUtil.validateError(negativeResult, i++, "incompatible types: 'Record' will not be matched to " + "'RecordWithIntFieldAndNeverRestField'", 358, 17); BAssertUtil.validateError(negativeResult, i++, "incompatible types: 'Record' will not be matched to " + "'RecordWithIntFieldAndEffectivelyNeverRestField'", 359, 17); - Assert.assertEquals(negativeResult.getErrorCount(), 32); - Assert.assertEquals(negativeResult.getDiagnostics().length, i); + Assert.assertEquals(negativeResult.getErrorCount(), 35); } @Test diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/conversion/NativeConversionNegativeTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/conversion/NativeConversionNegativeTest.java index 56ca7a0f5992..63bc74d68d79 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/conversion/NativeConversionNegativeTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/conversion/NativeConversionNegativeTest.java @@ -142,6 +142,10 @@ public void testConvertRecordToMapWithCyclicValueReferences() { Object results = BRunUtil.invoke(negativeResult, "testConvertRecordToMapWithCyclicValueReferences"); Object error = results; Assert.assertEquals(getType(error).getClass(), BErrorType.class); + Assert.assertEquals( + ((BMap) ((BError) results).getDetails()).get(StringUtils.fromString("message")) + .toString(), + "'Manager' value has cyclic reference"); } @Test(description = "Test converting record to json having cyclic reference.") @@ -149,6 +153,10 @@ public void testConvertRecordToJsonWithCyclicValueReferences() { Object results = BRunUtil.invoke(negativeResult, "testConvertRecordToJsonWithCyclicValueReferences"); Object error = results; Assert.assertEquals(getType(error).getClass(), BErrorType.class); + Assert.assertEquals( + ((BMap) ((BError) results).getDetails()).get(StringUtils.fromString("message")) + .toString(), + "'Manager' value has cyclic reference"); } @Test(dataProvider = "testConversionFunctionList") diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/lambda/IterableOperationsTests.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/lambda/IterableOperationsTests.java index c1d84b08c851..7a34bd628fd6 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/lambda/IterableOperationsTests.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/lambda/IterableOperationsTests.java @@ -55,6 +55,7 @@ public void setup() { @Test() public void testNegative() { + Assert.assertEquals(negative.getErrorCount(), 33); int index = 0; BAssertUtil.validateError(negative, index++, "undefined function 'forEach' in type 'int'", 6, 7); BAssertUtil.validateError(negative, index++, "undefined function 'map' in type 'string'", 8, 7); @@ -67,9 +68,11 @@ public void testNegative() { BAssertUtil.validateError(negative, index++, "incompatible types: expected 'string', found 'any'", 35, 27); BAssertUtil.validateError(negative, index++, "incompatible types: expected 'string', found 'any'", 38, 22); BAssertUtil.validateError(negative, index++, "incompatible types: expected 'int', found '()'", 46, 9); + BAssertUtil.validateError(negative, index++, "incompatible types: expected '[other,other]', found 'string[]'", + 48, 18); BAssertUtil.validateError(negative, index++, - "invalid list binding pattern; member variable count mismatch with member type count", - 48, 5); + "invalid list binding pattern: attempted to infer a list type, but found 'other'", + 48, 18); BAssertUtil.validateError(negative, index++, "invalid operation: type 'string' does not support field access", 49, 35); BAssertUtil.validateError(negative, index++, "too many arguments in call to 'length()'", 55, 9); @@ -93,6 +96,9 @@ public void testNegative() { "'function (ballerina/lang.array:0.0.0:Type) returns (boolean)', " + "found 'function (other) returns ()'", 67, 14); BAssertUtil.validateError(negative, index++, "unknown type 'person'", 67, 24); + BAssertUtil.validateError(negative, index++, "incompatible types: expected " + + "'function (ballerina/lang.array:0.0.0:Type) " + + "returns (boolean)', found 'function (string) returns (other)'", 68, 18); BAssertUtil.validateError(negative, index++, "unknown type 'person'", 68, 48); BAssertUtil.validateError(negative, index++, "incompatible types: expected 'int[]', found 'any[]'", 73, 15); BAssertUtil.validateError(negative, index++, "incompatible types: expected 'int[]', found 'string[]'", 80, 15); @@ -101,8 +107,7 @@ public void testNegative() { BAssertUtil.validateError(negative, index++, "incompatible types: expected 'string', found 'map'", 103, 16); BAssertUtil.validateError(negative, index++, "incompatible types: expected 'boolean', found 'int'", 111, 20); BAssertUtil.validateError(negative, index++, "incompatible types: expected 'float', found 'int'", 120, 39); - BAssertUtil.validateError(negative, index++, "incompatible types: expected 'float', found 'int'", 137, 42); - Assert.assertEquals(negative.getErrorCount(), index); + BAssertUtil.validateError(negative, index, "incompatible types: expected 'float', found 'int'", 137, 42); } @Test diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/stamp/AnydataStampInbuiltFunctionTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/stamp/AnydataStampInbuiltFunctionTest.java index 4ae4e03ea2fe..52a2fc6d489b 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/stamp/AnydataStampInbuiltFunctionTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/stamp/AnydataStampInbuiltFunctionTest.java @@ -17,7 +17,6 @@ */ package org.ballerinalang.test.expressions.stamp; -import io.ballerina.runtime.api.types.MapType; import io.ballerina.runtime.api.types.TypeTags; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.values.BArray; @@ -90,7 +89,7 @@ public void testStampAnydataToJSONV2() { BMap mapValue0 = (BMap) results; Assert.assertTrue(getType(mapValue0) instanceof BMapType); - Assert.assertTrue(((MapType) getType(mapValue0)).getConstrainedType() instanceof BJsonType); + Assert.assertTrue(((BMapType) getType(mapValue0)).getConstrainedType() instanceof BJsonType); Assert.assertEquals((mapValue0).size(), 5); Assert.assertEquals(((LinkedHashMap) mapValue0).get(StringUtils.fromString("school")).toString(), @@ -191,8 +190,8 @@ public void testStampAnydataToAnydata() { Object results = BRunUtil.invoke(compileResult, "stampAnydataToAnydata"); BMap mapValue = (BMap) results; - Assert.assertTrue(getType(mapValue) instanceof MapType); - Assert.assertTrue(((MapType) getType(mapValue)).getConstrainedType() instanceof BAnydataType); + Assert.assertTrue(getType(mapValue) instanceof BMapType); + Assert.assertTrue(((BMapType) getType(mapValue)).getConstrainedType() instanceof BAnydataType); } @Test @@ -203,8 +202,8 @@ public void testStampAnydataMapToUnion() { Assert.assertEquals(mapValue.size(), 5); - Assert.assertTrue(getType(mapValue) instanceof MapType); - Assert.assertTrue(((MapType) getType(mapValue)).getConstrainedType() instanceof BJsonType); + Assert.assertTrue(getType(mapValue) instanceof BMapType); + Assert.assertTrue(((BMapType) getType(mapValue)).getConstrainedType() instanceof BJsonType); Assert.assertEquals(mapValue.get(StringUtils.fromString("name")).toString(), "Raja"); Assert.assertTrue(getType(mapValue.get(StringUtils.fromString("name"))) instanceof BStringType); diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/stamp/ArrayStampInbuiltFunctionTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/stamp/ArrayStampInbuiltFunctionTest.java index 80440910dfa0..8bdd33f86ec3 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/stamp/ArrayStampInbuiltFunctionTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/stamp/ArrayStampInbuiltFunctionTest.java @@ -17,7 +17,6 @@ */ package org.ballerinalang.test.expressions.stamp; -import io.ballerina.runtime.api.types.MapType; import io.ballerina.runtime.api.types.TypeTags; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.values.BArray; @@ -67,10 +66,10 @@ public void testStampRecordToAnydataArray() { Assert.assertEquals(results.size(), 2); - Assert.assertTrue(getType(mapValue0) instanceof MapType); - Assert.assertEquals(((MapType) mapValue0.getType()).getConstrainedType().getClass(), BAnydataType.class); - Assert.assertTrue(getType(mapValue1) instanceof MapType); - Assert.assertEquals(((MapType) mapValue1.getType()).getConstrainedType().getClass(), BAnydataType.class); + Assert.assertEquals(getType((mapValue0)).getClass(), BMapType.class); + Assert.assertEquals(((BMapType) mapValue0.getType()).getConstrainedType().getClass(), BAnydataType.class); + Assert.assertEquals(getType((mapValue1)).getClass(), BMapType.class); + Assert.assertEquals(((BMapType) mapValue1.getType()).getConstrainedType().getClass(), BAnydataType.class); } @Test diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/typecast/TypeCastExprTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/typecast/TypeCastExprTest.java index f8f157e2f45d..1a1138915746 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/typecast/TypeCastExprTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/typecast/TypeCastExprTest.java @@ -274,7 +274,7 @@ public void testNullJsonToBoolean() { @Test(description = "Test casting nil to a record", expectedExceptions = {BLangTestException.class}, - expectedExceptionsMessageRegExp = ".*incompatible types: '\\(\\)' cannot be cast to 'StudentTC'.*") + expectedExceptionsMessageRegExp = ".*incompatible types: '\\(\\)' cannot be cast to 'Student'.*") public void testNullStructToStruct() { BRunUtil.invoke(result, "testNullStructToStruct"); } @@ -317,7 +317,7 @@ public void testAnyMapToJson() { @Test(description = "Test casting a struct as any type to json", expectedExceptions = {BLangTestException.class}, - expectedExceptionsMessageRegExp = ".*incompatible types: 'AddressTC' cannot be cast to 'json'.*") + expectedExceptionsMessageRegExp = ".*incompatible types: 'Address' cannot be cast to 'json'.*") public void testAnyStructToJson() { BRunUtil.invoke(result, "testAnyStructToJson"); } @@ -368,14 +368,14 @@ public void testStructAsAnyToStruct() { @Test(description = "Test casting any to struct", expectedExceptions = {BLangTestException.class}, - expectedExceptionsMessageRegExp = ".*incompatible types: 'map' cannot be cast to 'PersonTC'.*") + expectedExceptionsMessageRegExp = ".*incompatible types: 'map' cannot be cast to 'Person'.*") public void testAnyToStruct() { BRunUtil.invoke(result, "testAnyToStruct"); } @Test(description = "Test casting a null stored as any to struct", expectedExceptions = {BLangTestException.class}, - expectedExceptionsMessageRegExp = ".*incompatible types: '\\(\\)' cannot be cast to 'PersonTC'.*") + expectedExceptionsMessageRegExp = ".*incompatible types: '\\(\\)' cannot be cast to 'Person'.*") public void testAnyNullToStruct() { Object returns = BRunUtil.invoke(result, "testAnyNullToStruct"); Assert.assertNull(returns); diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/typecast/TypeCastExpressionsTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/typecast/TypeCastExpressionsTest.java index 36fc99cebefd..874bea5794fc 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/typecast/TypeCastExpressionsTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/typecast/TypeCastExpressionsTest.java @@ -18,7 +18,6 @@ import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.values.BArray; -import io.ballerina.runtime.api.values.BError; import io.ballerina.runtime.api.values.BMap; import org.ballerinalang.test.BCompileUtil; import org.ballerinalang.test.BRunUtil; @@ -42,12 +41,11 @@ */ public class TypeCastExpressionsTest { - private CompileResult result, result2; + private CompileResult result; @BeforeClass public void setup() { result = BCompileUtil.compile("test-src/expressions/typecast/type_cast_expr.bal"); - result2 = BCompileUtil.compile("test-src/expressions/typecast/type_cast_expr_runtime_errors.bal"); } @Test(dataProvider = "positiveTests") @@ -121,6 +119,12 @@ public void testCastNegatives() { , 13); validateError(resultNegative, errIndex++, "incompatible types: '(json|error)' cannot be cast to 'string'", 69, 13); + validateError(resultNegative, errIndex++, "incompatible types: '(string[]|int)' cannot be cast to 'byte[]'", + 78, 32); + validateError(resultNegative, errIndex++, "incompatible mapping constructor expression for type '(record {| " + + "byte[] a; anydata...; |}|record {| string a; anydata...; |})'", 79, 47); + validateError(resultNegative, errIndex++, "incompatible types: '(string[]|int)' cannot be cast to 'byte[]'", + 79, 51); validateError(resultNegative, errIndex++, "incompatible mapping constructor expression for type '(record {| " + "string[] a; anydata...; |}|record {| string a; anydata...; |})'", 82, 49); validateError(resultNegative, errIndex++, "incompatible types: expected 'Obj', found 'object { int i; }'", 96, @@ -272,28 +276,8 @@ public Object[] typeCastWithConstructorTests() { }; } - @Test(dataProvider = "typeCastRuntimeErrorTests") - public void testTypeCastRuntimeErrors(String testFuncName) { - Object returns = BRunUtil.invoke(result2, testFuncName); - BError error = (BError) returns; - Assert.assertEquals(error.getErrorMessage().getValue(), "{ballerina}TypeCastError"); - } - - @DataProvider - public Object[] typeCastRuntimeErrorTests() { - return new Object[]{ - "testTupleToJSONCastRuntimeError", - "testCastingWithEmptyKeyedKeylessTbl", - "testMapCastingRuntimeError", - "testListCastingRuntimeError", - "testCastingObjects", - "testCastingObjects2", - }; - } - @AfterClass public void tearDown() { result = null; - result2 = null; } } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/DependentlyTypedFunctionsTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/DependentlyTypedFunctionsTest.java index 61e6acff92a6..b17b3e374633 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/DependentlyTypedFunctionsTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/DependentlyTypedFunctionsTest.java @@ -58,6 +58,7 @@ public void testNegatives() { validateError(errors, indx++, "incompatible types: expected 'typedesc<(int|float|decimal|string|boolean)>', " + "found 'typedesc'", 41, 23); validateError(errors, indx++, "unknown type 'aTypeVar'", 44, 60); + validateError(errors, indx++, "incompatible types: expected 'map', found 'map'", 51, 18); validateError(errors, indx++, "incompatible types: expected 'int', found 'customType'", 61, 13); validateError(errors, indx++, "incompatible types: expected 'float', found 'customType'", 62, 15); validateError(errors, indx++, "unknown type 'td'", 65, 73); @@ -81,21 +82,20 @@ public void testNegatives() { validateError(errors, indx++, "mismatched function signatures: expected 'public function get" + "(typedesc) returns (td|error)', found 'public function get(typedesc) returns" + " (other|error)'", 140, 5); - validateError(errors, indx++, - "a function with a non-'external' function body cannot be a dependently-typed function", 140, 64); + validateError(errors, indx++, "a function with a non-'external' function body cannot be a dependently-typed " + + "function", 140, 64); validateError(errors, indx++, "mismatched function signatures: expected 'public function get" + "(typedesc) returns (td|error)', found 'public function get(typedesc) returns" + " (other|error)'", 144, 5); - validateError(errors, indx++, - "a function with a non-'external' function body cannot be a dependently-typed function", 144, 64); + validateError(errors, indx++, "a function with a non-'external' function body cannot be a dependently-typed " + + "function", 144, 64); validateError(errors, indx++, "incompatible types: expected 'Bar', found 'Baz'", 176, 15); validateError(errors, indx++, "incompatible types: expected 'Quux', found 'Qux'", 180, 17); validateError(errors, indx++, "incompatible types: expected 'Qux', found 'Quux'", 181, 15); validateError(errors, indx++, "incompatible types: expected 'Baz', found 'Quux'", 182, 16); validateError(errors, indx++, "incompatible types: expected 'Quuz', found 'Qux'", 183, 17); - // TODO: 26/8/24 verify -// validateError(errors, indx++, "incompatible types: expected 'Corge', found 'Grault'", 185, 19); -// validateError(errors, indx++, "incompatible types: expected 'Grault', found 'Corge'", 186, 21); + validateError(errors, indx++, "incompatible types: expected 'Corge', found 'Grault'", 185, 19); + validateError(errors, indx++, "incompatible types: expected 'Grault', found 'Corge'", 186, 21); validateError(errors, indx++, "incompatible types: expected 'string', found 'int'", 196, 16); validateError(errors, indx++, "incompatible types: expected 'string', found 'int'", 197, 16); validateError(errors, indx++, "incompatible types: expected 'int', found 'string'", 198, 13); @@ -178,8 +178,6 @@ public void testNegatives() { validateError(errors, indx++, "incompatible types: expected 'string', found 'int'", 363, 18); validateError(errors, indx++, "incompatible type for parameter 't' with inferred typedesc value: expected " + "'typedesc<(int|string)>', found 'typedesc'", 369, 17); - validateError(errors, indx++, "a wildcard binding pattern can be used only with a value that belong to type " + - "'any'", 371, 5); validateError(errors, indx++, "incompatible types: expected 'TargetType', found 'typedesc'", 371, 64); validateError(errors, indx++, "incompatible type for parameter 'td' with inferred typedesc value: expected " + "'typedesc', found 'typedesc'", 383, 24); @@ -195,7 +193,7 @@ public void testRuntimeCastError() { @Test(expectedExceptions = BLangTestException.class, expectedExceptionsMessageRegExp = "error: \\{ballerina\\}TypeCastError \\{\"message\":\"incompatible types:" + - " 'PersonDTFT' cannot be cast to 'int'.*") + " 'Person' cannot be cast to 'int'.*") public void testCastingForInvalidValues() { BRunUtil.invoke(result, "testCastingForInvalidValues"); } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/InferredDependentlyTypeFunctionTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/InferredDependentlyTypeFunctionTest.java index ebc1cd4c9877..4dcd51d0d91e 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/InferredDependentlyTypeFunctionTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/InferredDependentlyTypeFunctionTest.java @@ -203,8 +203,6 @@ public void testDependentlyTypedFunctionWithInferredTypedescValueNegative() { "an argument for the parameter or a contextually-expected type to infer the argument", 185, 44); validateError(negativeResult, index++, "cannot infer the 'typedesc' argument for parameter 'td': expected " + "an argument for the parameter or a contextually-expected type to infer the argument", 186, 52); - validateError(negativeResult, index++, "invalid return type: members of a dependently-typed union type with " + - "an inferred typedesc parameter should have disjoint basic types", 193, 64); validateError(negativeResult, index++, "cannot infer the 'typedesc' argument for parameter 'td': expected " + "an argument for the parameter or a contextually-expected type to infer the argument", 196, 5); validateError(negativeResult, index++, "cannot infer the 'typedesc' argument for parameter 'td2': expected " + diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/basic/NegativeValidationTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/basic/NegativeValidationTest.java index c4fdb3f15920..41aadfc88701 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/basic/NegativeValidationTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/basic/NegativeValidationTest.java @@ -284,7 +284,14 @@ public void testMethodSignatureNotMatch7() { public void testMethodSignatureNotMatch8() { CompileResult compileResult = BCompileUtil.compile("test-src/javainterop/negative/distinct_error"); compileResult.getDiagnostics(); - Assert.assertEquals(compileResult.getErrorCount(), 0); + Assert.assertEquals(compileResult.getDiagnostics().length, 2); + BAssertUtil.validateError(compileResult, 0, + "{ballerina/jballerina.java}METHOD_SIGNATURE_DOES_NOT_MATCH " + + "'Incompatible ballerina return type for Java method " + + "'returnDistinctErrorUnionWhichThrowsCheckedException' which throws checked exception " + + "found in class 'org.ballerinalang.nativeimpl.jvm.tests.StaticMethods': " + + "expected 'int|error', found '(int|testorg/distinct_error.errors:1.0.0:DistinctError)''", + 21, 1); } @Test @@ -544,7 +551,15 @@ public void testMethodSignatureNotMatch16() { String path = "test-src/javainterop/negative/method_sig_not_match16.bal"; CompileResult compileResult = BCompileUtil.compile(path); compileResult.getDiagnostics(); - Assert.assertEquals(compileResult.getDiagnostics().length, 0); + Assert.assertEquals(compileResult.getDiagnostics().length, 1); + BAssertUtil.validateError(compileResult, 0, + "{ballerina/jballerina.java}METHOD_SIGNATURE_DOES_NOT_MATCH " + + "'Incompatible ballerina return type for Java method " + + "'acceptIntErrorUnionReturnWhichThrowsUncheckedException' which throws " + + "'java.lang.RuntimeException' found in class " + + "'org.ballerinalang.nativeimpl.jvm.tests.StaticMethods': " + + "expected 'int', found '(int|error)''", + "method_sig_not_match16.bal", 19, 1); } @Test @@ -554,10 +569,12 @@ public void testMethodSignatureNotMatch17() { compileResult.getDiagnostics(); Assert.assertEquals(compileResult.getDiagnostics().length, 1); BAssertUtil.validateError(compileResult, 0, - "{ballerina/jballerina.java}METHOD_SIGNATURE_DOES_NOT_MATCH 'Incompatible return type for method " + - "'acceptIntErrorUnionReturnWhichThrowsUncheckedException' in class " + + "{ballerina/jballerina.java}METHOD_SIGNATURE_DOES_NOT_MATCH " + + "'Incompatible ballerina return type for Java method " + + "'acceptIntErrorUnionReturnWhichThrowsUncheckedException' which throws " + + "'java.lang.RuntimeException' found in class " + "'org.ballerinalang.nativeimpl.jvm.tests.StaticMethods': " + - "Java type 'long' will not be matched to ballerina type 'error''", + "no return type expected but found 'error''", "method_sig_not_match17.bal", 19, 1); } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/jvm/ObjectSubtypingTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/jvm/ObjectSubtypingTest.java index c8ebdbe98049..da7b9cde168a 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/jvm/ObjectSubtypingTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/jvm/ObjectSubtypingTest.java @@ -29,6 +29,7 @@ import static org.ballerinalang.test.BAssertUtil.validateError; import static org.ballerinalang.test.BAssertUtil.validateWarning; import static org.testng.Assert.assertEquals; +import static java.lang.String.format; /** * Test cases for testing the object subtyping rules. @@ -93,6 +94,12 @@ public void testNegatives() { int i = 0; validateError(result, i++, "private qualifier in object member descriptor", 21, 5); validateError(result, i++, "private qualifier in object member descriptor", 28, 5); + validateError(result, i++, format(msgFormat, "ObjWithPvtField", "AnotherObjWithAPvtField"), 45, 26); + validateError(result, i++, format(msgFormat, "ObjWithPvtMethod", "AnotherObjWithPvtMethod"), 46, 27); + validateError(result, i++, format(msgFormat, "testorg/subtyping:1.0.0:ModuleLevelSubtypableObj", "Subtype1"), + 65, 45); + validateError(result, i++, format(msgFormat, "testorg/subtyping:1.0.0:ModuleLevelSubtypableObj2", "Subtype2"), + 66, 46); assertEquals(result.getErrorCount(), i); } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/klass/ServiceClassTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/klass/ServiceClassTest.java index 4ad19a162ed3..0d020f637b5c 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/klass/ServiceClassTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/klass/ServiceClassTest.java @@ -180,6 +180,9 @@ public void testResourceFunctionWithInvalidPathParam() { CompileResult result = BCompileUtil.compile("test-src/klass/resource_function_with_invalid_path_param_type_negative.bal"); int index = 0; + validateError(result, index++, "only 'int', 'string', 'float', 'boolean', 'decimal' types " + + "are supported as path params, found 'other'", + 24, 29); validateError(result, index++, "undefined module 'module1'", 24, 29); validateError(result, index++, "unknown type 'RequestMessage'", 24, 29); diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/object/ObjectEquivalencyNegativeTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/object/ObjectEquivalencyNegativeTest.java index 7bc9cfde21cc..da5afea56a50 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/object/ObjectEquivalencyNegativeTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/object/ObjectEquivalencyNegativeTest.java @@ -31,27 +31,32 @@ public class ObjectEquivalencyNegativeTest { @Test(description = "Test equivalence of objects that are in the same package") public void testEquivalenceOfObjectsInSamePackage() { CompileResult compileResult = BCompileUtil.compile("test-src/object/object-equivalency-01-negative.bal"); - int i = 0; - BAssertUtil.validateError(compileResult, i++, + Assert.assertEquals(compileResult.getErrorCount(), 12); + BAssertUtil.validateError(compileResult, 0, + "incompatible types: 'employee01' cannot be cast to 'person01'", 24, 18); + BAssertUtil.validateError(compileResult, 1, "incompatible types: 'employee02' cannot be cast to 'person02'", 51, 18); - BAssertUtil.validateError(compileResult, i++, + BAssertUtil.validateError(compileResult, 2, "incompatible types: 'employee04' cannot be cast to 'person04'", 108, 18); - BAssertUtil.validateError(compileResult, i++, + BAssertUtil.validateError(compileResult, 3, "incompatible types: 'employee05' cannot be cast to 'person05'", 145, 18); - BAssertUtil.validateError(compileResult, i++, + BAssertUtil.validateError(compileResult, 4, "incompatible types: 'employee06' cannot be cast to 'person06'", 175, 18); - BAssertUtil.validateError(compileResult, i++, + BAssertUtil.validateError(compileResult, 5, + "incompatible types: 'employee08' cannot be cast to 'person08'", 284, 18); + BAssertUtil.validateError(compileResult, 6, + "incompatible types: 'employee09' cannot be cast to 'person09'", 341, 18); + BAssertUtil.validateError(compileResult, 7, "incompatible types: expected 'ObjWithRemoteMethod', found 'NonClientObj'", 460, 29); - BAssertUtil.validateError(compileResult, i++, + BAssertUtil.validateError(compileResult, 8, "incompatible types: expected 'ObjWithRemoteMethod', found 'ClientObjWithoutRemoteMethod'", 465, 29); - BAssertUtil.validateError(compileResult, i++, + BAssertUtil.validateError(compileResult, 9, "incompatible types: expected 'ObjWithOnlyRemoteMethod', " + "found 'ClientObjWithoutRemoteMethod'", 470, 33); - BAssertUtil.validateError(compileResult, i++, + BAssertUtil.validateError(compileResult, 10, "incompatible types: expected 'ObjWithOnlyRemoteMethod', found 'NonClientObj'", 475, 33); - BAssertUtil.validateError(compileResult, i++, + BAssertUtil.validateError(compileResult, 11, "incompatible types: expected 'NonClientObj', found 'ObjWithRemoteMethod'", 480, 22); - Assert.assertEquals(compileResult.getErrorCount(), i); } @Test(description = "Test equivalence of objects that are in the same package from a third package") diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/GroupByClauseTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/GroupByClauseTest.java index 59b02cec27e5..bebc32dcd459 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/GroupByClauseTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/GroupByClauseTest.java @@ -229,6 +229,8 @@ public void testNegativeCases() { "constructor or function invocation", 32, 28); BAssertUtil.validateError(negativeResult, i++, "sequence variable can be used in a single element list " + "constructor or function invocation", 35, 25); + BAssertUtil.validateError(negativeResult, i++, "incompatible types: expected 'seq int', found 'seq int'", + 36, 20); BAssertUtil.validateError(negativeResult, i++, "operator '+' not defined for 'seq int' and 'int'", 39, 20); BAssertUtil.validateError(negativeResult, i++, "sequence variable can be used in a single element list " + "constructor or function invocation", 39, 20); diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/JoinClauseTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/JoinClauseTest.java index b70824a062d5..9d482b6a9ef9 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/JoinClauseTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/JoinClauseTest.java @@ -127,10 +127,10 @@ public void testJoinClauseWithLargeList() { @Test(description = "Test negative scenarios for query expr with join clause") public void testNegativeScenarios() { + Assert.assertEquals(negativeResult.getErrorCount(), 40); int i = 0; validateError(negativeResult, i++, "incompatible types: expected 'Department', found 'Person'", 46, 13); validateError(negativeResult, i++, "undeclared field 'name' in record 'Person'", 51, 19); - validateError(negativeResult, i++, "incompatible types: expected 'Department', found 'other'", 69, 13); validateError(negativeResult, i++, "unknown type 'XYZ'", 69, 13); validateError(negativeResult, i++, "incompatible types: expected 'int', found 'other'", 70, 28); validateError(negativeResult, i++, "undefined symbol 'deptId'", 93, 11); @@ -167,8 +167,9 @@ public void testNegativeScenarios() { validateError(negativeResult, i++, "incompatible types: expected 'int', found 'other'", 389, 59); validateError(negativeResult, i++, "invalid operation: type 'Person?' does not support field access", 389, 59); validateError(negativeResult, i++, "invalid operation: type 'Person?' does not support field access", 395, 22); + validateError(negativeResult, i++, "order by not supported for complex type fields, order key should belong" + + " to a basic type", 395, 22); validateError(negativeResult, i++, "invalid operation: type 'Person?' does not support field access", 397, 36); - Assert.assertEquals(negativeResult.getErrorCount(), i); } @AfterClass diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/OrderByClauseTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/OrderByClauseTest.java index 791844e1dcf1..448332adbbf7 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/OrderByClauseTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/OrderByClauseTest.java @@ -234,7 +234,12 @@ public void testQueryExprWithOrderByClauseReturnXML() { @Test(description = "Test negative scenarios for query expr with order by clause") public void testNegativeScenarios() { int index = 0; - validateError(negativeResult, index++, "undefined symbol 'address'", 35, 18); + + validateError(negativeResult, index++, "order by not supported for complex type fields, " + + "order key should belong to a basic type", + 35, 18); + validateError(negativeResult, index++, "undefined symbol 'address'", + 35, 18); validateError(negativeResult, index++, "order by not supported for complex type fields, order key should belong to a basic type", 47, 18); diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryActionOrExprTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryActionOrExprTest.java index e9dcf503eb5b..fe8ed238035a 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryActionOrExprTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryActionOrExprTest.java @@ -107,6 +107,7 @@ public void testQueryActionOrExprSemanticsNegative() { validateError(negativeResult, i++, "incompatible types: '()' is not an iterable collection", 42, 24); validateError(negativeResult, i++, "incompatible types: '()' is not an iterable collection", 51, 27); validateError(negativeResult, i++, "incompatible types: '()' is not an iterable collection", 61, 27); + validateError(negativeResult, i++, "incompatible types: expected 'other', found 'int'", 71, 18); validateError(negativeResult, i++, "incompatible types: '()' is not an iterable collection", 71, 27); validateError(negativeResult, i++, "incompatible types: '()' is not an iterable collection", 82, 27); validateError(negativeResult, i++, "incompatible types: '()' is not an iterable collection", 93, 27); @@ -116,7 +117,10 @@ public void testQueryActionOrExprSemanticsNegative() { validateError(negativeResult, i++, "receive action not supported wth 'var' type", 168, 27); validateError(negativeResult, i++, "action invocation as an expression not allowed here", 279, 15); validateError(negativeResult, i++, "action invocation as an expression not allowed here", 291, 18); + validateError(negativeResult, i++, "order by not supported for complex type fields, order key should " + + "belong to a basic type", 291, 18); validateError(negativeResult, i++, "action invocation as an expression not allowed here", 303, 15); + validateError(negativeResult, i++, "incompatible types: expected 'int', found 'other'", 303, 15); validateError(negativeResult, i++, "action invocation as an expression not allowed here", 315, 23); validateError(negativeResult, i++, "incompatible types: expected 'int', found 'other'", 316, 21); validateError(negativeResult, i++, "action invocation as an expression not allowed here", 320, 50); diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryExprWithQueryConstructTypeTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryExprWithQueryConstructTypeTest.java index e62ae3d3a9df..f279c44272da 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryExprWithQueryConstructTypeTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryExprWithQueryConstructTypeTest.java @@ -36,11 +36,14 @@ */ public class QueryExprWithQueryConstructTypeTest { - private CompileResult result; + private CompileResult result, negativeResult, semanticsNegativeResult; @BeforeClass public void setup() { result = BCompileUtil.compile("test-src/query/query-expr-with-query-construct-type.bal"); + negativeResult = BCompileUtil.compile("test-src/query/query-expr-query-construct-type-negative.bal"); + semanticsNegativeResult = BCompileUtil.compile("test-src/query/query-expr-query-construct-type-semantics" + + "-negative.bal"); } @Test(description = "Test query expr returning a stream ") @@ -158,12 +161,10 @@ public void testMapConstructQueryWithConflictingKeys() { BRunUtil.invoke(result, "testMapConstructQueryWithConflictingKeys"); } - @Test(enabled = false, description = "Test negative scenarios for query expr with query construct type") + @Test(description = "Test negative scenarios for query expr with query construct type") public void testNegativeScenarios() { - CompileResult negativeResult = - BCompileUtil.compile("test-src/query/query-expr-query-construct-type-negative.bal"); - int index = 0; + validateError(negativeResult, index++, "incompatible types: expected 'Person[]', found 'stream'", 54, 35); validateError(negativeResult, index++, "incompatible types: expected 'Customer[]', " + @@ -334,9 +335,6 @@ public void testNegativeScenarios() { @Test(description = "Test semantic negative scenarios for query expr with query construct type") public void testSemanticNegativeScenarios() { - CompileResult semanticsNegativeResult = - BCompileUtil.compile("test-src/query/query-expr-query-construct-type-semantics-negative.bal"); - int index = 0; validateError(semanticsNegativeResult, index++, "on conflict can only be used with queries which produce " + "maps or tables with key specifiers", 39, 13); @@ -362,7 +360,7 @@ public void testSemanticNegativeScenarios() { @Test(expectedExceptions = BLangTestException.class, expectedExceptionsMessageRegExp = "error: \\{ballerina/lang.map\\}InherentTypeViolation " + "\\{\"message\":\"cannot update 'readonly' field 'id' in record of type 'record " + - "\\{\\| readonly int id; readonly string name; UserX user; \\|\\}'\".*") + "\\{\\| readonly int id; readonly string name; User user; \\|\\}'\".*") public void testQueryConstructingTableUpdateKeyPanic1() { BRunUtil.invoke(result, "testQueryConstructingTableUpdateKeyPanic1"); } @@ -370,7 +368,7 @@ public void testQueryConstructingTableUpdateKeyPanic1() { @Test(expectedExceptions = BLangTestException.class, expectedExceptionsMessageRegExp = "error: \\{ballerina/lang.map\\}InherentTypeViolation " + "\\{\"message\":\"cannot update 'readonly' field 'id' in record of type 'record " + - "\\{\\| readonly int id; readonly string name; UserX user; \\|\\}'\".*") + "\\{\\| readonly int id; readonly string name; User user; \\|\\}'\".*") public void testQueryConstructingTableUpdateKeyPanic2() { BRunUtil.invoke(result, "testQueryConstructingTableUpdateKeyPanic2"); } @@ -536,5 +534,7 @@ public void testInnerQueryConstructedWithCEP() { @AfterClass public void tearDown() { result = null; + negativeResult = null; + semanticsNegativeResult = null; } } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryNegativeTests.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryNegativeTests.java index 3e7f756b767d..29c4fcdc886b 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryNegativeTests.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryNegativeTests.java @@ -42,7 +42,6 @@ public void testFromClauseWithInvalidType() { 64, 18); validateError(compileResult, index++, "undeclared field 'lastName' in record 'Teacher'", 67, 30); validateError(compileResult, index++, "undeclared field 'age' in record 'Teacher'", 68, 25); - validateError(compileResult, index++, "incompatible types: expected 'Person', found 'other'", 83, 18); validateError(compileResult, index++, "unknown type 'XYZ'", 83, 18); validateError(compileResult, index++, "undefined field 'lastName' in record 'Teacher'", 103, 20); validateError(compileResult, index++, "incompatible types: 'int' is not an iterable collection", 116, 32); diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/reachability/ReachabilityAnalysisTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/reachability/ReachabilityAnalysisTest.java index 1dda40d7ff6c..96644ffad04f 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/reachability/ReachabilityAnalysisTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/reachability/ReachabilityAnalysisTest.java @@ -302,6 +302,7 @@ public void testUnreachability() { validateError(result, i++, ERROR_TYPE_NEVER_EXPRESSION_NOT_ALLOWED, 818, 19); validateError(result, i++, ERROR_UNREACHABLE_CODE, 829, 9); validateError(result, i++, ERROR_TYPE_NEVER_EXPRESSION_NOT_ALLOWED, 829, 19); + validateError(result, i++, ERROR_TYPE_NEVER_EXPRESSION_NOT_ALLOWED, 839, 15); validateError(result, i++, ERROR_UNREACHABLE_CODE, 840, 9); validateError(result, i++, ERROR_TYPE_NEVER_EXPRESSION_NOT_ALLOWED, 840, 19); validateHint(result, i++, HINT_UNNECESSARY_CONDITION, 850, 8); @@ -555,7 +556,7 @@ public void testUnreachability2() { validateError(result, i++, ERROR_UNREACHABLE_CODE, 401, 9); validateError(result, i++, ERROR_UNREACHABLE_CODE, 408, 9); validateError(result, i++, ERROR_UNREACHABLE_CODE, 419, 9); - validateError(result, i++, ERROR_UNREACHABLE_CODE, 430, 9); + validateError(result, i++, ERROR_UNREACHABLE_CODE, 428, 9); validateError(result, i++, ERROR_UNREACHABLE_CODE, 432, 9); validateError(result, i++, ERROR_UNREACHABLE_CODE, 438, 9); validateError(result, i++, ERROR_UNREACHABLE_CODE, 446, 9); diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/record/RecordTypeInclusionTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/record/RecordTypeInclusionTest.java index 3351ce1f7a9a..4736ac5a3bc3 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/record/RecordTypeInclusionTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/record/RecordTypeInclusionTest.java @@ -54,12 +54,14 @@ public void testCyclicInclusionViaFieldNegative() { "test-src/record/test_record_cyclic_inclusion_via_field_negative.bal"); int index = 0; validateError(compileResult, index++, "missing non-defaultable required record field 'x'", 26, 13); - validateError(compileResult, index++, "cannot update 'readonly' value of type 'Foo'", 27, 5); + validateError(compileResult, index++, "incompatible types: expected 'Bar', found 'int'", 27, 11); validateError(compileResult, index++, "incompatible types: expected 'Bar', found 'int'", 29, 17); validateError(compileResult, index++, "incompatible types: expected 'Bar', found 'int'", 31, 21); validateError(compileResult, index++, "missing non-defaultable required record field 'innerError'", 42, 21); validateError(compileResult, index++, "incompatible types: expected 'record {| string code?; ... innerError; " + "anydata...; |}', found 'int'", 43, 20); + validateError(compileResult, index++, "incompatible types: expected 'int', found 'record {| string code?; ..." + + " innerError; anydata...; |}'", 46, 13); Assert.assertEquals(compileResult.getErrorCount(), index); } } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/arrays/ArrayFillTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/arrays/ArrayFillTest.java index 8112cc9ee997..f7fc07fb2dd8 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/arrays/ArrayFillTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/arrays/ArrayFillTest.java @@ -303,7 +303,7 @@ public void testFiniteTypeArrayFill1() { assertEquals(unionArr.size(), index + 1); for (int i = 0; i < index; i++) { - assertEquals(unionArr.get(i), 0); + assertEquals(unionArr.get(i), 0L); } assertEquals(unionArr.get(index), 5L); diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/arrays/arraysofarrays/SealedArraysOfArraysTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/arrays/arraysofarrays/SealedArraysOfArraysTest.java index a41a788529ad..8c27e3bed470 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/arrays/arraysofarrays/SealedArraysOfArraysTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/arrays/arraysofarrays/SealedArraysOfArraysTest.java @@ -114,6 +114,7 @@ public void testStringSealedArraysOfArrays() { @Test() public void testNegativeSealedArraysOfArrays() { + Assert.assertEquals(resultNegative.getErrorCount(), 34); int i = 0; BAssertUtil.validateError( resultNegative, i++, "size mismatch in closed array. expected '2', but found '3'", 19, 23); @@ -152,7 +153,10 @@ public void testNegativeSealedArraysOfArrays() { BAssertUtil.validateError( resultNegative, i++, "size mismatch in closed array. expected '3', but found '4'", 72, 66); BAssertUtil.validateError( - resultNegative, i++, "invalid usage of closed type: array not initialized", 73, 5);; + resultNegative, i++, "invalid usage of closed type: array not initialized", 73, 5); + BAssertUtil.validateError( + resultNegative, i++, "incompatible types: expected '((float[*][]|string) & readonly)', " + + "found '(float[2][2] & readonly)'", 76, 40); BAssertUtil.validateError( resultNegative, i++, "list index out of range: index: '4'", 83, 11); BAssertUtil.validateError( @@ -179,9 +183,8 @@ public void testNegativeSealedArraysOfArrays() { resultNegative, i++, "incompatible types: expected 'map', found 'map<(float|int[1][1])>'", 118, 19); BAssertUtil.validateError( - resultNegative, i++, "incompatible types: expected '[(int[*][] & readonly),float]', " + + resultNegative, i, "incompatible types: expected '[(int[*][] & readonly),float]', " + "found '[(string|int[1][]),float]'", 121, 34); - Assert.assertEquals(resultNegative.getErrorCount(), i); } @Test diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/ifelse/TypeGuardTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/ifelse/TypeGuardTest.java index 7d624653296d..cdfc29dd5868 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/ifelse/TypeGuardTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/ifelse/TypeGuardTest.java @@ -63,8 +63,6 @@ public void testTypeGuardNegative() { "incompatible types: '(int|boolean)' will not be matched to 'float'", 90, 63); BAssertUtil.validateError(negativeResult, i++, "incompatible types: '(boolean|float)' will not be matched to 'int'", 99, 30); - BAssertUtil.validateError(negativeResult, i++, - "incompatible types: '(int|string)' will not be matched to 'boolean'", 99, 44); BAssertUtil.validateError(negativeResult, i++, "incompatible types: 'string' will not be matched to 'int'", 108, 25); BAssertUtil.validateError(negativeResult, i++, @@ -95,10 +93,14 @@ public void testTypeGuardNegative() { BAssertUtil.validateError(negativeResult, i++, "incompatible types: 'map<(int|string)>' will not be matched to 'record {| int i; float f; |}'", 214, 8); + BAssertUtil.validateError(negativeResult, i++, "incompatible types: 'map<(int|string)>' will not be matched " + + "to 'map'", 221, 8); BAssertUtil.validateError(negativeResult, i++, "incompatible types: 'CyclicComplexUnion' will not" + " be matched to 'float'", 232, 8); BAssertUtil.validateError(negativeResult, i++, "incompatible types: 'CyclicComplexUnion' will not" + " be matched to 'floatUnion'", 239, 8); + BAssertUtil.validateError(negativeResult, i++, "incompatible types: 'CyclicComplexUnion' will not" + + " be matched to 'float[]'", 245, 8); Assert.assertEquals(negativeResult.getDiagnostics().length, i); } @@ -132,12 +134,12 @@ public void testTypeGuardSemanticsNegative() { BAssertUtil.validateError(negativeResult, i++, "incompatible types: expected 'int', found '(int|boolean)'", 181, 17); // TODO : Fix me : #21609 - BAssertUtil.validateError(negativeResult, i++, - "incompatible types: expected 'string', found '(float|string)'", 183, - 20); +// BAssertUtil.validateError(negativeResult, i++, +// "incompatible types: expected 'string', found '(float|string|int|boolean)'", 183, +// 20); // TODO : Fix me : #21609 - BAssertUtil.validateError(negativeResult, i++, "incompatible types: expected 'int', found '(int|string|float)'", - 190, 17); +// BAssertUtil.validateError(negativeResult, i++, "incompatible types: expected 'int', found '(boolean|float)'", +// 190, 17); // BAssertUtil.validateError(negativeResult, i++, // "incompatible types: expected 'string', found '(boolean|int|string)'", 192, 20); BAssertUtil.validateError(negativeResult, i++, @@ -147,18 +149,16 @@ public void testTypeGuardSemanticsNegative() { BAssertUtil.validateError(negativeResult, i++, "incompatible types: expected 'string', found '(float|string)'", 201, 20); // TODO : Fix me : #21609 - BAssertUtil.validateError(negativeResult, i++, "incompatible types: expected 'int', found '(string|boolean)'", - 208, 17); - // TODO : Fix me : #21609 - BAssertUtil.validateError(negativeResult, i++, - "incompatible types: expected 'string', found '(int|float)'", 210, 20); +// BAssertUtil.validateError(negativeResult, i++, "incompatible types: expected 'int', found '(string|boolean)'", +// 208, 17); +// BAssertUtil.validateError(negativeResult, i++, +// "incompatible types: expected 'string', found '(int|float|string)'", 210, 20); BAssertUtil.validateError(negativeResult, i++, "unknown type 'T'", 216, 30); // TODO : Fix me : #21609 - BAssertUtil.validateError(negativeResult, i++, "incompatible types: expected 'int', found '(string|boolean)'", - 217, 17); - // TODO : Fix me : #21609 - BAssertUtil.validateError(negativeResult, i++, - "incompatible types: expected 'string', found '(int|float)'", 219, 20); +// BAssertUtil.validateError(negativeResult, i++, "incompatible types: expected 'int', found '(string|boolean)'", +// 217, 17); +// BAssertUtil.validateError(negativeResult, i++, +// "incompatible types: expected 'string', found '(int|float|string)'", 219, 20); // BAssertUtil.validateError(negativeResult, i++, "incompatible types: expected 'int', found '(Person|boolean)'", // 238, 17); BAssertUtil.validateError(negativeResult, i++, @@ -1080,6 +1080,8 @@ public void testTypeGuardTypeNarrowing3() { "incompatible types: expected 'string', found '(string|int)'", 243, 20); BAssertUtil.validateError(result, index++, "incompatible types: expected 'string', found '(string|int)'", 252, 20); + BAssertUtil.validateError(result, index++, + "incompatible types: expected 'int', found 'other'", 263, 17); // issue #34965 BAssertUtil.validateError(result, index++, "incompatible types: expected 'string', found '(string|int)'", 265, 20); // issue #34965 BAssertUtil.validateError(result, index++, @@ -1122,7 +1124,14 @@ public void testTypeGuardTypeNarrowing3() { @Test public void testTypeGuardTypeNarrowing4() { CompileResult result = BCompileUtil.compile("test-src/statements/ifelse/test_type_guard_type_narrow_4.bal"); - Assert.assertEquals(result.getDiagnostics().length, 0); + int index = 0; + BAssertUtil.validateError(result, index++, + "expression of type 'never' or equivalent to type 'never' not allowed here", 21, 19); // issue #34965 + BAssertUtil.validateError(result, index++, + "expression of type 'never' or equivalent to type 'never' not allowed here", 27, 19); // issue #34965 + BAssertUtil.validateError(result, index++, + "expression of type 'never' or equivalent to type 'never' not allowed here", 33, 19); // issue #34965 + Assert.assertEquals(result.getDiagnostics().length, index); } @Test(description = "Test type guard type narrowing with no errors") diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/matchstmt/MatchGuardAnalysisTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/matchstmt/MatchGuardAnalysisTest.java index 68007630242d..3b994cba5e9d 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/matchstmt/MatchGuardAnalysisTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/matchstmt/MatchGuardAnalysisTest.java @@ -64,6 +64,14 @@ public void testMatchGuardCodeAnalysisNegative() { BAssertUtil.validateWarning(result, i++, "pattern will not be matched", 42, 9); BAssertUtil.validateError(result, i++, "incompatible types: 'Foo' will not be " + "matched to 'record {| string x; int i; anydata...; |}'", 42, 30); + BAssertUtil.validateError(result, i++, "incompatible types: 'function () returns ()' will not be " + + "matched to 'isolated function'", 51, 19); + BAssertUtil.validateError(result, i++, "incompatible types: 'function (int,string) returns ()' " + + "will not be matched to 'isolated function'", 60, 19); + BAssertUtil.validateError(result, i++, "incompatible types: 'function (int,string) returns (int)' " + + "will not be matched to 'isolated function'", 69, 19); + BAssertUtil.validateError(result, i++, "incompatible types: 'function () returns (int)' will not be " + + "matched to 'isolated function'", 78, 19); BAssertUtil.validateError(result, i++, "incompatible types: '\"P2\"' will not be matched to '\"P3\"'", 88, 17); Assert.assertEquals(result.getWarnCount(), 3); Assert.assertEquals(result.getErrorCount(), i - 3); diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/constant/ConstantExpressionTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/constant/ConstantExpressionTest.java index e5040c89c631..14931b3531f7 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/constant/ConstantExpressionTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/constant/ConstantExpressionTest.java @@ -58,9 +58,11 @@ public void constExpressionNegative() { BAssertUtil.validateError(compileResult1, i++, "operator '~' not defined for 'false'", 37, 22); BAssertUtil.validateError(compileResult1, i++, "illegal cyclic reference '[A, B, C]'", 39, 1); BAssertUtil.validateError(compileResult1, i++, "illegal cyclic reference '[E, F]'", 44, 1); + BAssertUtil.validateError(compileResult1, i++, "'-9.223372036854776E18' is out of range for 'int'", 47, 20); BAssertUtil.validateError(compileResult1, i++, "'9223372036854775808' is out of range for 'int'", 47, 21); BAssertUtil.validateError(compileResult1, i++, "illegal cyclic reference '[CONST5]'", 49, 1); - BAssertUtil.validateError(compileResult1, i++, "constant declaration not yet supported for type 'T'", 49, 7); + BAssertUtil.validateError(compileResult1, i++, "cannot declare a constant with type 'T', " + + "expected a subtype of 'anydata' that is not 'never'", 49, 7); Assert.assertEquals(compileResult1.getErrorCount(), i); } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/constant/ListConstantNegativeTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/constant/ListConstantNegativeTest.java index 76a9968d7167..912ce6d9130a 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/constant/ListConstantNegativeTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/constant/ListConstantNegativeTest.java @@ -46,6 +46,7 @@ public void testListConstructorExprAsConstantExprNegative() { " does not have a filler value", 30, 41); validateError(compileResult, i++, "invalid usage of list constructor: type '1|2' does not have a filler value", 31, 26); + validateError(compileResult, i++, "ambiguous type '(int[2]|[int,int])'", 32, 38); validateError(compileResult, i++, "incompatible types: expected '1', found '3'", 33, 27); validateError(compileResult, i++, "incompatible types: expected 'byte', found '300'", 34, 24); validateError(compileResult, i++, "size mismatch in closed array. expected '2', but found '3'", 35, 23); diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/constant/SimpleConstantNegativeTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/constant/SimpleConstantNegativeTest.java index ba441c2c5125..2a80fdcac758 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/constant/SimpleConstantNegativeTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/constant/SimpleConstantNegativeTest.java @@ -50,8 +50,9 @@ public void testNegative() { 9, 14); BAssertUtil.validateError(compileResult, index++, "'_' is a keyword, and may not be used as an identifier", 10, 7); - BAssertUtil.validateError(compileResult, index++, "constant declaration not yet supported for type " + - "'invalidType'", 12, 7); + BAssertUtil.validateError(compileResult, index++, "cannot declare a constant with type 'invalidType', " + + "expected a subtype of 'anydata' that is not 'never'", + 12, 7); BAssertUtil.validateError(compileResult, index++, "unknown type 'invalidType'", 12, 7); BAssertUtil.validateError(compileResult, index++, "cannot update constant value", 26, 5); diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/finite/FiniteTypeNegativeTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/finite/FiniteTypeNegativeTest.java index d5b142770971..9048996d7897 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/finite/FiniteTypeNegativeTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/finite/FiniteTypeNegativeTest.java @@ -163,7 +163,7 @@ public void testInvalidLiteralAssignment() { 183, 12); validateError(resultNegativeTwo, i++, "incompatible types: expected '2d', found 'string'", 187, 12); - validateError(resultNegativeTwo, i++, "incompatible types: expected '2d', found '2f'", + validateError(resultNegativeTwo, i++, "incompatible types: 'int' cannot be cast to '2f'", 191, 12); validateError(resultNegativeTwo, i++, "incompatible types: expected '3d', found '4f'", 192, 12); @@ -233,14 +233,14 @@ public void testInvalidLiteralAssignment() { "found 'float'", 276, 34); validateError(resultNegativeTwo, i++, "incompatible types: expected '1.7976931348623157E309d', " + "found 'decimal'", 277, 34); - validateError(resultNegativeTwo, i++, "'9223372036854775808' is out of range for 'int'", - 280, 21); + validateError(resultNegativeTwo, i++, "'-9.223372036854776E18' is out of range for 'int'", + 280, 20); validateError(resultNegativeTwo, i++, "unknown type 'testType'", 282, 5); validateError(resultNegativeTwo, i++, "'9223372036854775808' is out of range for 'int'", 285, 30); validateError(resultNegativeTwo, i++, "unknown type 'testType'", 286, 5); - validateError(resultNegativeTwo, i++, "'9223372036854775808' is out of range for 'int'", - 290, 20); + validateError(resultNegativeTwo, i++, "'-9.223372036854776E18' is out of range for 'int'", + 290, 19); validateError(resultNegativeTwo, i++, "unknown type 'InvalidTest1'", 292, 5); validateError(resultNegativeTwo, i++, "incompatible types: expected '1f', found 'float'", 296, 12); diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/map/ConstrainedMapTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/map/ConstrainedMapTest.java index 74b48bff3127..b216a7ee5b0e 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/map/ConstrainedMapTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/map/ConstrainedMapTest.java @@ -50,7 +50,7 @@ public void setup() { @Test(description = "Test Map constrained with type negative semantic validations.") public void testConstrainedMapNegative() { - Assert.assertEquals(negativeResult.getErrorCount(), 6); + Assert.assertEquals(negativeResult.getErrorCount(), 7); int i = 0; BAssertUtil.validateError(negativeResult, i++, "incompatible types: expected 'map', found 'map'", 3, 12); BAssertUtil.validateError(negativeResult, i++, "incompatible types: expected 'int', found 'string'", 7, 44); @@ -61,6 +61,8 @@ public void testConstrainedMapNegative() { "incompatible types: expected 'map', " + "found 'map'", 35, 31); BAssertUtil.validateError(negativeResult, i++, "incompatible types: expected 'map', found 'map'", 45, 31); + BAssertUtil.validateError(negativeResult, i, "incompatible types: 'map' cannot be cast to" + + " 'map'", 77, 29); } @Test(description = "Test Map constrained with value type value retrieval positive case.") diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/never/NeverTypeTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/never/NeverTypeTest.java index b0d049346c0c..e894bd8f93ac 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/never/NeverTypeTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/never/NeverTypeTest.java @@ -338,6 +338,8 @@ public Object[] dataToTestNeverRuntime() { "testNeverRuntime7", "testNeverRuntime8", "testNeverRuntime9", + "testNeverRuntime10", + "testNeverRuntime11", "testNeverRuntime12", "testNeverWithAnyAndAnydataRuntime", "testNeverFieldTypeCheck", @@ -400,25 +402,6 @@ public void testNeverTypeCodeAnalysisNegative() { Assert.assertEquals(compileResult.getWarnCount(), 1); } - @Test - public void testNeverTypeIsExprNegative() { - CompileResult res = BCompileUtil.compile("test-src/types/never/never_type_is_expr_negative.bal"); - int i = 0; - BAssertUtil.validateError(res, i++, "incompatible types: 'int' will not be matched to 'never'", 19, 17); - BAssertUtil.validateError(res, i++, "incompatible types: 'Record' will not be matched to 'never'", 29, 17); - BAssertUtil.validateError(res, i++, "incompatible types: 'record {| int x; anydata...; |}' " + - "will not be matched to 'record {| never x?; anydata...; |}'", 34, 17); - BAssertUtil.validateError(res, i++, "incompatible types: 'record {| never? x; anydata...; |}' " + - "will not be matched to 'record {| never x?; anydata...; |}'", 37, 17); - BAssertUtil.validateError(res, i++, "incompatible types: 'record {| int? x; anydata...; |}' " + - "will not be matched to 'record {| never x?; anydata...; |}'", 40, 17); - BAssertUtil.validateError(res, i++, "incompatible types: '(record {| int x; anydata...; |} & readonly)' " + - "will not be matched to 'record {| never x?; anydata...; |}'", 43, 17); - BAssertUtil.validateError(res, i++, "incompatible types: '(record {| never? x; anydata...; |} & readonly)' " + - "will not be matched to 'record {| never x?; anydata...; |}'", 46, 17); - Assert.assertEquals(res.getErrorCount(), i); - } - @AfterClass public void tearDown() { neverTypeTestResult = null; diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/InherentlyImmutableTypeTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/InherentlyImmutableTypeTest.java index f7f4aad79930..58533c393875 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/InherentlyImmutableTypeTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/InherentlyImmutableTypeTest.java @@ -54,14 +54,16 @@ public void testReadonlyTypeNegative() { BAssertUtil.validateError(negativeResult, i++, "incompatible types: expected 'any', found 'readonly'", 19, 14); BAssertUtil.validateError(negativeResult, i++, - "incompatible types: expected 'error?', found 'readonly'", 24, 26); + "operator '==' not defined for 'readonly' and '[int,int,int]'", 24, 14); BAssertUtil.validateError(negativeResult, i++, - "incompatible types: expected '(int|any)', found 'readonly'", 25, 27); + "incompatible types: expected 'error?', found 'readonly'", 29, 26); BAssertUtil.validateError(negativeResult, i++, - "incompatible types: expected '(string|readonly)', found '(readonly|any)'", 27, 43); + "incompatible types: expected '(int|any)', found 'readonly'", 30, 27); BAssertUtil.validateError(negativeResult, i++, - "incompatible types: expected 'any', found '(readonly|string)'", 29, 17); - Assert.assertEquals(negativeResult.getErrorCount(), i); + "incompatible types: expected '(string|readonly)', found '(readonly|any)'", 32, 43); + BAssertUtil.validateError(negativeResult, i++, + "incompatible types: expected 'any', found '(readonly|string)'", 34, 17); + Assert.assertEquals(negativeResult.getErrorCount(), 6); } @AfterClass diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/table/TableCastTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/table/TableCastTest.java index d478380285a7..e9c5fe210614 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/table/TableCastTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/table/TableCastTest.java @@ -72,14 +72,15 @@ public void testCastingWithEmptyKeyedKeylessTbl() { @Test public void testNegativeCases() { - int index = 0; - BAssertUtil.validateError(negativeResult, index++, "incompatible types: 'PersonTable1' " + + Assert.assertEquals(negativeResult.getErrorCount(), 5); + BAssertUtil.validateError(negativeResult, 0, "incompatible types: 'PersonTable1' " + "cannot be cast to 'table key'", 49, 34); - BAssertUtil.validateError(negativeResult, index++, "incompatible types: expected 'int', found 'string'", 50, - 16); - BAssertUtil.validateError(negativeResult, index++, "incompatible types: expected 'string', found 'int'", 60, - 16); - Assert.assertEquals(negativeResult.getErrorCount(), index); + BAssertUtil.validateError(negativeResult, 1, "incompatible types: expected 'int', found 'string'", 50, 16); + BAssertUtil.validateError(negativeResult, 2, "incompatible types: expected 'string', found 'int'", 60, 16); + BAssertUtil.validateError(negativeResult, 3, "incompatible types: 'CustomerTable' cannot be" + + " cast to 'CustomerEmptyKeyedTbl'", 77, 34); + BAssertUtil.validateError(negativeResult, 4, "incompatible types: 'CustomerTable' cannot be cast to " + + "'table'", 83, 20); } @AfterClass diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/table/TableNegativeTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/table/TableNegativeTest.java index 83eceba270a1..90b5e63918c8 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/table/TableNegativeTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/table/TableNegativeTest.java @@ -184,9 +184,6 @@ public void testTableNegativeCases() { validateError(compileResult, index++, "incompatible types: expected " + "'table key', " + "found 'table'", 539, 9); - validateError(compileResult, index++, "incompatible types: expected " + - "'table key', " + - "found 'table key'", 551, 9); validateError(compileResult, index++, "incompatible types: expected 'never', found 'int'", 551, 29); validateError(compileResult, index++, "incompatible types: expected " + "'table key', " + diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/tuples/BasicTupleTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/tuples/BasicTupleTest.java index c4d4b31a3ddb..629de1bd6008 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/tuples/BasicTupleTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/tuples/BasicTupleTest.java @@ -193,7 +193,7 @@ public void testTupleWithUnion() { @Test(description = "Test negative scenarios of assigning tuple literals") public void testNegativeTupleLiteralAssignments() { - Assert.assertEquals(resultNegative.getErrorCount(), 54); + Assert.assertEquals(resultNegative.getErrorCount(), 55); int i = 0; BAssertUtil.validateError( resultNegative, i++, @@ -310,19 +310,21 @@ public void testTupleToJSONAssignmentNegative() { int i = 36; BAssertUtil.validateError(resultNegative, i++, "incompatible types: expected 'json', " + "found '[string,int,xml...]'", 199, 21); + BAssertUtil.validateError(resultNegative, i++, "incompatible types: '[string,(int|xml),string...]' " + + "cannot be cast to 'json[]'", 202, 16); BAssertUtil.validateError(resultNegative, i, "incompatible types: expected 'json', " + "found '[string,(int|xml),string...]'", 203, 16); } @Test(description = "Test ambiguous tuple assignment to unions of tuple types") public void testAmbiguousTupleTupeNegative() { - int i = 38; + int i = 39; BAssertUtil.validateError(resultNegative, i, "ambiguous type '([1,\"hello\"]|[1])'", 208, 10); } @Test(description = "Test the tuple argument when the variable is already declared") public void testTupleParamWithExistingArg() { - int i = 39; + int i = 40; BAssertUtil.validateError(resultNegative, i++, "redeclared symbol 'i'", 215, 34); BAssertUtil.validateError(resultNegative, i++, "redeclared symbol 'i'", 222, 41); BAssertUtil.validateError(resultNegative, i++, "operator '+' not defined for 'int' and 'string'", 230, 21); @@ -336,7 +338,7 @@ public void testTupleAsTupleFirstMember() { @Test(description = "Test the tuple annotations") public void testTupleAnnotations1() { - int i = 43; + int i = 44; BAssertUtil.validateError(resultNegative, i++, "annotation 'ballerina/lang.annotations:0.0.0:typeParam' is not allowed on field", 239, 7); diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/xml/XMLIterationTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/xml/XMLIterationTest.java index fc7276975860..2e5b28fcdbbb 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/xml/XMLIterationTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/xml/XMLIterationTest.java @@ -58,18 +58,27 @@ public void testNegative() { BAssertUtil.validateError(negative, index++, "incompatible types: " + "expected 'function (ballerina/lang.xml:0.0.0:ItemType) returns ()', " + "found 'function ([int,xml,string]) returns ()'", 18, 19); + BAssertUtil.validateError(negative, index++, + "incompatible types: expected 'other', found 'xml:Element'", + 29, 13); BAssertUtil.validateError(negative, index++, "incompatible types: 'xml:Element' is not an iterable collection", 29, 34); BAssertUtil.validateError(negative, index++, "incompatible types: expected 'record {| xml:Comment value; |}?', found " + "'record {| xml:Element value; |}?'", 33, 54); + BAssertUtil.validateError(negative, index++, + "incompatible types: expected 'other', found 'xml:Comment'", + 40, 13); BAssertUtil.validateError(negative, index++, "incompatible types: 'xml:Comment' is not an iterable collection", 40, 34); BAssertUtil.validateError(negative, index++, "incompatible types: expected 'record {| xml:Element value; |}?', found " + "'record {| xml:Comment value; |}?'", 44, 54); + BAssertUtil.validateError(negative, index++, + "incompatible types: expected 'other', found 'xml:ProcessingInstruction'", + 51, 13); BAssertUtil.validateError(negative, index++, "incompatible types: 'xml:ProcessingInstruction' is not an iterable collection", 51, 48); @@ -82,9 +91,15 @@ public void testNegative() { BAssertUtil.validateError(negative, index++, "incompatible types: expected '(xml|xml)', found 'xml'", 60, 44); + BAssertUtil.validateError(negative, index++, + "incompatible types: expected 'other', found '(xml:Element|xml:Text)'", + 63, 13); BAssertUtil.validateError(negative, index++, "incompatible types: '(xml:Element|xml:Text)' is not an iterable collection", 63, 44); + BAssertUtil.validateError(negative, index++, + "incompatible types: expected 'other', found '(xml:Element|xml:Text)'", + 68, 13); BAssertUtil.validateError(negative, index++, "incompatible types: '(xml|xml)' is not an iterable collection", 68, 44); diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/equal_and_not_equal_operation.bal b/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/equal_and_not_equal_operation.bal index bffcab3d6b6f..ae0be91693b8 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/equal_and_not_equal_operation.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/equal_and_not_equal_operation.bal @@ -153,17 +153,20 @@ function checkAnyDataEquality() { } type IntOne 1; +type FloatOne 1.0; +type IntTwo 2; +type FloatTwo 2f; function checkFiniteTypeEquality() { IntOne intOne_1 = 1; IntOne intOne_2 = 1; - byte byteOne = 1; - byte byteTwo = 2; + IntTwo intTwo = 2; + FloatOne floatOne = 1f; + FloatTwo floatTwo = 2.0; test:assertTrue((intOne_1 == intOne_2) && !(intOne_1 != intOne_2)); - test:assertTrue((intOne_1 == byteOne) && !(intOne_1 != byteOne)); - test:assertTrue(!(intOne_1 == byteTwo) && (intOne_1 != byteTwo)); - test:assertTrue(!(byteOne == byteTwo) && (byteOne != byteTwo)); + test:assertTrue((floatOne != floatTwo) && !(floatOne == floatTwo)); + test:assertFalse((intOne_1 == intTwo) && !(intOne_1 != intTwo)); } type ErrorDetail record { @@ -228,16 +231,6 @@ function testOpenRecordWithOptionalFieldsEqualityNegative() { test:assertFalse((e1 == e2) || !(e1 != e2) || (e3 == e4) || !(e3 != e4)); } -type EmployeeWithOptionalId record {| - string name; - float id?; -|}; - -type PersonWithOptionalId record {| - string name; - string id?; -|}; - function testClosedRecordWithOptionalFieldsEqualityPositive() { ClosedRecordWithOptionalFieldOne e1 = {name: "Em", one: 4000}; ClosedRecordWithOptionalFieldOne e2 = e1; @@ -246,10 +239,6 @@ function testClosedRecordWithOptionalFieldsEqualityPositive() { ClosedRecordWithOptionalFieldTwo e4 = {name: "Em"}; test:assertTrue((e1 == e2) && !(e1 != e2) && isEqual(e3, e4)); - - EmployeeWithOptionalId e5 = { name: "Maryam" }; - PersonWithOptionalId p1 = { name: "Maryam" }; - test:assertTrue(e5 == p1 && !(e5 != p1)); } function testClosedRecordWithOptionalFieldsEqualityNegative() { @@ -637,6 +626,10 @@ function checkTupleEqualityNegative() { [string, ClosedEmployee] t6 = ["hi", {name: "Em"}]; test:assertFalse(t1 == t2 || !(t1 != t2) || t3 == t4 || !(t3 != t4) || t5 == t6 || !(t5 != t6)); + + Array a = ["array", 1]; + Mapping b = ["mapping", 2]; + test:assertFalse(a == b); } function checkUnionConstrainedMapsPositive() { @@ -707,18 +700,6 @@ function checkUnionConstrainedMapsNegative() { test:assertFalse('equals || m3 == m4 || !(m3 != m4)); } -function checkEqualityOfMapsOfIncompatibleConstraintTypes() { - map a = {}; - map b = {}; - boolean bool1 = a == b && !(a != b); - - map c = {}; - map d = {}; - boolean bool2 = c == d && !(c != d); - - test:assertTrue(bool1 && bool2); -} - function checkUnionArrayPositive() { (string|int)?[] a1 = []; int[] a2 = []; @@ -1839,25 +1820,3 @@ function testEqualityWithCyclicReferences() { test:assertTrue(t3 == t4); test:assertTrue(t3 == t5); } - -function readonlyMapEquality() { - map & readonly immutableMarks = { - math: 80, - physics: 85, - chemistry: 75 - }; - readonly readonlyMarks = immutableMarks; - - map marks = { - math: 80, - physics: 85, - chemistry: 75 - }; - - test:assertTrue(readonlyMarks == marks); -} - -function readonlyListEquality() { - readonly arr = [1, 2 , 3]; - test:assertTrue(arr == [1, 2 , 3]); -} diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/equal_and_not_equal_operation_negative.bal b/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/equal_and_not_equal_operation_negative.bal index c9fbed15a20c..d6b45203a8c1 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/equal_and_not_equal_operation_negative.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/equal_and_not_equal_operation_negative.bal @@ -32,6 +32,18 @@ function checkEqualityOfArraysOfDifferentTypes() returns boolean { return bool1 && bool2; } +function checkEqualityOfMapsOfIncompatibleConstraintTypes() returns boolean { + map a = {}; + map b = {}; + boolean bool1 = a == b && !(a != b); + + map c = {}; + map d = {}; + boolean bool2 = c == d && !(c != d); + + return bool1 && bool2; +} + function checkEqualityOfTuplesOfDifferentTypes() returns boolean { [string, int] a = ["", 0]; [boolean, float] b = [false, 0.0]; @@ -48,6 +60,10 @@ function checkEqualityOfRecordsOfIncompatibleTypes() returns boolean { Employee e = { name: "Maryam" }; Person p = { name: "Maryam" }; boolean b = e == p && !(e != p); + + EmployeeWithOptionalId e1 = { name: "Maryam" }; + PersonWithOptionalId p1 = { name: "Maryam" }; + return b && e1 == p1 && !(e1 != p1); } function checkEqualityWithJsonRecordMapForIncompatibleType() returns boolean { @@ -107,6 +123,11 @@ type EmployeeWithOptionalId record {| float id?; |}; +type PersonWithOptionalId record {| + string name; + string id?; +|}; + class Foo { string s = ""; } @@ -131,6 +152,22 @@ function refAndNilEqualityCheck() { } } +function readonlyEquality() returns boolean { + map & readonly immutableMarks = { + math: 80, + physics: 85, + chemistry: 75 + }; + readonly readonlyMarks = immutableMarks; + + map marks = { + math: 80, + physics: 85, + chemistry: 75 + }; + return readonlyMarks != marks; +} + type MyObject object { int i; }; @@ -146,27 +183,3 @@ function testEqualityWithNonAnydataType() returns boolean { MyObject obj2 = object {int i = 10;}; 'equals = obj == obj2 && !(obj != obj2); } - -type IntOne 1; -type FloatOne 1.0; -type IntTwo 2; -type FloatTwo 2f; - -function checkFiniteTypeEqualityNegative() { - IntOne intOne_1 = 1; - IntTwo intTwo = 2; - FloatOne floatOne = 1f; - FloatTwo floatTwo = 2.0; - - boolean _ = (floatOne != floatTwo) && !(floatOne == floatTwo); - boolean _ = ((intOne_1 == intTwo) && !(intOne_1 != intTwo)); -} - -type Array ["array", 1]; -type Mapping ["mapping", 2]; - -function checkTupleEqualityNegative() { - Array a = ["array", 1]; - Mapping b = ["mapping", 2]; - boolean _ = a == b; -} diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/negative-type-test-expr.bal b/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/negative-type-test-expr.bal index 9565ccb4161c..b06341511c3e 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/negative-type-test-expr.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/negative-type-test-expr.bal @@ -92,19 +92,19 @@ function testTypeCheckInTernary() returns string { // ========================== Records ========================== -type A1NTT record { +type A1 record { int x = 0; }; -type B1NTT record { +type B1 record { int x = 0; string y = ""; }; function testSimpleRecordTypes_1() returns string { - A1NTT a1 = {}; + A1 a1 = {}; any a = a1; - if (a !is A1NTT) { + if (a !is A1) { return "n/a"; } else { return "a is A1"; @@ -112,49 +112,49 @@ function testSimpleRecordTypes_1() returns string { } function testSimpleRecordTypes_2() returns [boolean, boolean] { - B1NTT b = {}; + B1 b = {}; any a = b; - return [a !is A1NTT, a !is B1NTT]; + return [a !is A1, a !is B1]; } -type A2NTT record { +type A2 record { int x = 0; }; -type B2NTT record { +type B2 record { int x = 0; }; function testSimpleRecordTypes_3() returns [boolean, boolean] { - B2NTT b = {}; + B2 b = {}; any a = b; - return [a !is A2NTT, a !is B2NTT]; + return [a !is A2, a !is B2]; } -type HumanNTT record { +type Human record { string name; (function (int, string) returns string) | () foo = (); }; -type ManNTT record { +type Man record { string name; (function (int, string) returns string) | () foo = (); int age = 0; }; function testRecordsWithFunctionType_1() returns [string, string] { - HumanNTT m = {name:"Piyal"}; + Human m = {name:"Piyal"}; any a = m; string s1; string s2; - if (a !is ManNTT) { + if (a !is Man) { s1 = "a is not a man"; } else { s1 = "Man: " + m.name; } - if (a !is HumanNTT) { + if (a !is Human) { s2 = "a is not a human"; } else { s2 = "Human: " + m.name; @@ -164,18 +164,18 @@ function testRecordsWithFunctionType_1() returns [string, string] { } function testRecordsWithFunctionType_2() returns [string, string] { - ManNTT m = {name:"Piyal"}; + Man m = {name:"Piyal"}; any a = m; string s1; string s2; - if (a !is ManNTT) { + if (a !is Man) { s1 = "a is not a man"; } else { s1 = "Man: " + m.name; } - if (a !is HumanNTT) { + if (a !is Human) { s2 = "a is not a human"; } else { s2 = "Human: " + m.name; @@ -184,36 +184,36 @@ function testRecordsWithFunctionType_2() returns [string, string] { return [s1, s2]; } -type XTN record { +type X record { int p = 0; string q = ""; - A1NTT r = {}; + A1 r = {}; }; -type YTN record { +type Y record { int p = 0; string q = ""; - B1NTT r = {}; // Assignable to A1. Hence Y is assignable to X. + B1 r = {}; // Assignable to A1. Hence Y is assignable to X. }; function testNestedRecordTypes() returns [boolean, boolean] { - YTN y = {}; + Y y = {}; any x = y; - return [x is XTN, x is YTN]; + return [x is X, x is Y]; } -type A3NTT record { +type A3 record { int x = 0; }; -type B3NTT record {| +type B3 record {| int x = 0; |}; function testSealedRecordTypes() returns [boolean, boolean] { - A3NTT a3 = {}; + A3 a3 = {}; any a = a3; - return [a !is A3NTT, a !is B3NTT]; + return [a !is A3, a !is B3]; } // ========================== Objects ========================== @@ -375,18 +375,18 @@ function testObjectWithUnorderedFields() returns [string, string, string, string return [s1, s2, s3, s4]; } -public type A4NTT object { +public type A4 object { public int p; public string q; }; -public type B4NTT object { +public type B4 object { public float r; - *A4NTT; + *A4; }; public class C4 { - *B4NTT; + *B4; public boolean s; public function init(int p, string q, float r, boolean s) { @@ -403,11 +403,11 @@ function testPublicObjectEquivalency() returns [string, string, string] { string s2 = "n/a"; string s3 = "n/a"; - if !(x !is A4NTT) { + if !(x !is A4) { s1 = "values: " + x.p.toString() + ", " + x.q; } - if !(x !is B4NTT) { + if !(x !is B4) { s2 = "values: " + x.p.toString() + ", " + x.q + ", " + x.r.toString(); } @@ -418,18 +418,18 @@ function testPublicObjectEquivalency() returns [string, string, string] { return [s1, s2, s3]; } -type A5NTT object { +type A5 object { int p; string q; }; -type B5NTT object { +type B5 object { float r; - *A5NTT; + *A5; }; class C5 { - *B5NTT; + *B5; boolean s; public function init(int p, string q, float r, boolean s) { @@ -446,11 +446,11 @@ function testPrivateObjectEquivalency() returns [string, string, string] { string s2 = "n/a"; string s3 = "n/a"; - if !(x !is A5NTT) { + if !(x !is A5) { s1 = "values: " + x.p.toString() + ", " + x.q; } - if !(x !is B5NTT) { + if !(x !is B5) { s2 = "values: " + x.p.toString() + ", " + x.q + ", " + x.r.toString(); } @@ -467,7 +467,7 @@ function testAnonymousObjectEquivalency() returns [string, string, string] { string s2 = "n/a"; string s3 = "n/a"; - if !(x !is object { public float r; *A4NTT; }) { + if !(x !is object { public float r; *A4; }) { s1 = "values: " + x.p.toString() + ", " + x.q + ", " + x.r.toString(); } @@ -482,50 +482,50 @@ function testAnonymousObjectEquivalency() returns [string, string, string] { return [s1, s2, s3]; } -class QuxNeg { - QuxNeg? fn; +class Qux { + Qux? fn; - public function init(QuxNeg? fn = ()) { + public function init(Qux? fn = ()) { self.fn = fn; } } -class QuuxNeg { - QuuxNeg? fn = (); +class Quux { + Quux? fn = (); } -class QuuzNeg { - QuuzNeg? fn = (); +class Quuz { + Quuz? fn = (); int i = 1; } -class ABCNeg { - QuxNeg f; +class ABC { + Qux f; string s; - function init(QuxNeg f, string s) { + function init(Qux f, string s) { self.f = f; self.s = s; } } function testObjectIsCheckWithCycles() { - QuxNeg f1 = new; - QuxNeg f2 = new (f1); + Qux f1 = new; + Qux f2 = new (f1); - any a1 = f1; - assertFalse(a1 !is QuuxNeg); - assertTrue(a1 !is QuuzNeg); + any a1 = f1; + assertFalse(a1 !is Quux); + assertTrue(a1 !is Quuz); - any a2 = f2; - assertFalse(a2 !is QuuxNeg); - assertTrue(a2 !is QuuzNeg); + any a2 = f2; + assertFalse(a2 !is Quux); + assertTrue(a2 !is Quuz); - ABCNeg ob = new (f2, "ballerina"); + ABC ob = new (f2, "ballerina"); any a3 = ob; - assertFalse(a3 !is object {QuxNeg f;}); - assertTrue(a3 !is object {QuuzNeg f;}); + assertFalse(a3 !is object { Qux f; }); + assertTrue(a3 !is object { Quuz f; }); } // ========================== Arrays ========================== @@ -539,11 +539,11 @@ function testSimpleArrays() returns [boolean, boolean, boolean, boolean, boolean } function testRecordArrays() returns [boolean, boolean, boolean, boolean] { - XTN[] a = [{}, {}]; - XTN[][] b = [[{}, {}], [{}, {}]]; + X[] a = [{}, {}]; + X[][] b = [[{}, {}], [{}, {}]]; any c = a; any d = b; - return [c !is XTN[], d !is XTN[][], c !is YTN[], d !is YTN[][]]; + return [c !is X[], d !is X[][], c !is Y[], d !is Y[][]]; } public function testUnionType() { @@ -641,20 +641,20 @@ function testSimpleTuples() returns [boolean, boolean, boolean, boolean, boolean } function testTupleWithAssignableTypes_1() returns [boolean, boolean, boolean, boolean] { - [XTN, YTN] p = [{}, {}]; + [X, Y] p = [{}, {}]; any q = p; - boolean b0 = q !is [XTN, XTN]; - boolean b1 = q !is [XTN, YTN]; - boolean b2 = q !is [YTN, XTN]; - boolean b3 = q !is [YTN, YTN]; + boolean b0 = q !is [X, X]; + boolean b1 = q !is [X, Y]; + boolean b2 = q !is [Y, X]; + boolean b3 = q !is [Y, Y]; return [b0, b1, b2, b3]; } function testTupleWithAssignableTypes_2() returns boolean { - [YTN, YTN] p = [{}, {}]; - [XTN, YTN] q = p; - boolean b1 = q !is [YTN, YTN]; - return q !is [YTN, YTN]; + [Y, Y] p = [{}, {}]; + [X, Y] q = p; + boolean b1 = q !is [Y, Y]; + return q !is [Y, Y]; } public function testRestType() { @@ -1079,12 +1079,12 @@ public function testXMLNeverType() { xml e = xml ``; assertEquality( e !is byte, true); - assertEquality( e is xml<'xml:Element>, true); + assertEquality( e !is xml<'xml:Element>, true); assertEquality( e !is xml<'xml:Text>, false); assertEquality( e !is xml, false); assertEquality( e !is 'xml:Text, false); assertEquality( e !is 'xml:Element, true); - assertEquality( e is xml<'xml:Element|'xml:Comment>, true); + assertEquality( e !is xml<'xml:Element|'xml:Comment>, true); } function testXMLTextType(){ diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/type-test-expr.bal b/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/type-test-expr.bal index 3a8c6533ec95..b6c8c183f2ba 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/type-test-expr.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/type-test-expr.bal @@ -100,21 +100,21 @@ function testTypeCheckInTernary() returns string { // ========================== Records ========================== -type A1TN record { +type A1 record { int x = 0; }; -type B1TN record { +type B1 record { int x = 0; string y = ""; }; function testSimpleRecordTypes_1() returns string { - A1TN a1 = {}; + A1 a1 = {}; any a = a1; - if (a is A1TN) { + if (a is A1) { return "a is A1"; - } else if (a is B1TN) { + } else if (a is B1) { return "a is B1"; } @@ -122,49 +122,49 @@ function testSimpleRecordTypes_1() returns string { } function testSimpleRecordTypes_2() returns [boolean, boolean] { - B1TN b = {}; + B1 b = {}; any a = b; - return [a is A1TN, a is B1TN]; + return [a is A1, a is B1]; } -type A2TN record { +type A2 record { int x = 0; }; -type B2TN record { +type B2 record { int x = 0; }; function testSimpleRecordTypes_3() returns [boolean, boolean] { - B2TN b = {}; + B2 b = {}; any a = b; - return [a is A2TN, a is B2TN]; + return [a is A2, a is B2]; } -type HumanTN record { +type Human record { string name; (function (int, string) returns string) | () foo = (); }; -type ManTN record { +type Man record { string name; (function (int, string) returns string) | () foo = (); int age = 0; }; function testRecordsWithFunctionType_1() returns [string, string] { - HumanTN m = {name:"Piyal"}; + Human m = {name:"Piyal"}; any a = m; string s1; string s2; - if (a is ManTN) { + if (a is Man) { s1 = "Man: " + m.name; } else { s1 = "a is not a man"; } - if (a is HumanTN) { + if (a is Human) { s2 = "Human: " + m.name; } else { s2 = "a is not a human"; @@ -174,18 +174,18 @@ function testRecordsWithFunctionType_1() returns [string, string] { } function testRecordsWithFunctionType_2() returns [string, string] { - ManTN m = {name:"Piyal"}; + Man m = {name:"Piyal"}; any a = m; string s1; string s2; - if (a is ManTN) { + if (a is Man) { s1 = "Man: " + m.name; } else { s1 = "a is not a man"; } - if (a is HumanTN) { + if (a is Human) { s2 = "Human: " + m.name; } else { s2 = "a is not a human"; @@ -194,39 +194,39 @@ function testRecordsWithFunctionType_2() returns [string, string] { return [s1, s2]; } -type XTTE record { +type X record { int p = 0; string q = ""; - A1TN r = {}; + A1 r = {}; }; -type YTTE record { +type Y record { int p = 0; string q = ""; - B1TN r = {}; // Assignable to A1. Hence Y is assignable to X. + B1 r = {}; // Assignable to A1. Hence Y is assignable to X. }; function testNestedRecordTypes() returns [boolean, boolean] { - YTTE y = {}; + Y y = {}; any x = y; - return [x is XTTE, x is YTTE]; + return [x is X, x is Y]; } -type A3TN record { +type A3 record { int x = 0; }; -type B3TN record {| +type B3 record {| int x = 0; |}; function testSealedRecordTypes() returns [boolean, boolean] { - A3TN a3 = {}; + A3 a3 = {}; any a = a3; - return [a is A3TN, a is B3TN]; + return [a is A3, a is B3]; } -type CountryTN record {| +type Country record {| readonly string code?; string name?; record {| @@ -236,7 +236,7 @@ type CountryTN record {| |} continent?; |}; -type MyCountryTN record {| +type MyCountry record {| readonly string code?; record {| string code?; @@ -245,9 +245,9 @@ type MyCountryTN record {| |}; function testRecordsWithOptionalFields() { - MyCountryTN x = {}; - CountryTN y = x; - test:assertTrue(x is CountryTN); + MyCountry x = {}; + Country y = x; + test:assertTrue(x is Country); } // ========================== Objects ========================== @@ -409,18 +409,18 @@ function testObjectWithUnorderedFields() returns [string, string, string, string return [s1, s2, s3, s4]; } -public type A4TN object { +public type A4 object { public int p; public string q; }; -public type B4TN object { +public type B4 object { public float r; - *A4TN; + *A4; }; -public class C4TN { - *B4TN; +public class C4 { + *B4; public boolean s; public function init(int p, string q, float r, boolean s) { @@ -432,16 +432,16 @@ public class C4TN { } function testPublicObjectEquivalency() returns [string, string, string] { - any x = new C4TN(5, "foo", 6.7, true); + any x = new C4(5, "foo", 6.7, true); string s1 = "n/a"; string s2 = "n/a"; string s3 = "n/a"; - if(x is A4TN) { + if(x is A4) { s1 = "values: " + x.p.toString() + ", " + x.q; } - if (x is B4TN) { + if (x is B4) { s2 = "values: " + x.p.toString() + ", " + x.q + ", " + x.r.toString(); } @@ -452,18 +452,18 @@ function testPublicObjectEquivalency() returns [string, string, string] { return [s1, s2, s3]; } -type A5TN object { +type A5 object { int p; string q; }; -type B5TN object { +type B5 object { float r; - *A5TN; + *A5; }; class C5 { - *B5TN; + *B5; boolean s; public function init(int p, string q, float r, boolean s) { @@ -480,11 +480,11 @@ function testPrivateObjectEquivalency() returns [string, string, string] { string s2 = "n/a"; string s3 = "n/a"; - if(x is A5TN) { + if(x is A5) { s1 = "values: " + x.p.toString() + ", " + x.q; } - if (x is B5TN) { + if (x is B5) { s2 = "values: " + x.p.toString() + ", " + x.q + ", " + x.r.toString(); } @@ -496,12 +496,12 @@ function testPrivateObjectEquivalency() returns [string, string, string] { } function testAnonymousObjectEquivalency() returns [string, string, string] { - any x = new C4TN(5, "foo", 6.7, true); + any x = new C4(5, "foo", 6.7, true); string s1 = "n/a"; string s2 = "n/a"; string s3 = "n/a"; - if(x is object { public float r; *A4TN; }) { + if(x is object { public float r; *A4; }) { s1 = "values: " + x.p.toString() + ", " + x.q + ", " + x.r.toString(); } @@ -516,50 +516,50 @@ function testAnonymousObjectEquivalency() returns [string, string, string] { return [s1, s2, s3]; } -class QuxFoo { - QuxFoo? fn; +class Qux { + Qux? fn; - public function init(QuxFoo? fn = ()) { + public function init(Qux? fn = ()) { self.fn = fn; } } -class QuuxFoo { - QuuxFoo? fn = (); +class Quux { + Quux? fn = (); } -class QuuzFoo { - QuuzFoo? fn = (); +class Quuz { + Quuz? fn = (); int i = 1; } -class ABCFoo { - QuxFoo f; +class ABC { + Qux f; string s; - function init(QuxFoo f, string s) { + function init(Qux f, string s) { self.f = f; self.s = s; } } function testObjectIsCheckWithCycles() { - QuxFoo f1 = new; - QuxFoo f2 = new (f1); + Qux f1 = new; + Qux f2 = new (f1); - any a1 = f1; - test:assertTrue(a1 is QuuxFoo); - test:assertFalse(a1 is QuuzFoo); + any a1 = f1; + test:assertTrue(a1 is Quux); + test:assertFalse(a1 is Quuz); - any a2 = f2; - test:assertTrue(a2 is QuuxFoo); - test:assertFalse(a2 is QuuzFoo); + any a2 = f2; + test:assertTrue(a2 is Quux); + test:assertFalse(a2 is Quuz); - ABCFoo ob = new (f2, "ballerina"); + ABC ob = new (f2, "ballerina"); any a3 = ob; - test:assertTrue(a3 is object {QuxFoo f;}); - test:assertFalse(a3 is object {QuuzFoo f;}); + test:assertTrue(a3 is object { Qux f; }); + test:assertFalse(a3 is object { Quuz f; }); } service class ServiceClassA { @@ -625,11 +625,11 @@ function testSimpleArrays() returns [boolean, boolean, boolean, boolean, boolean } function testRecordArrays() returns [boolean, boolean, boolean, boolean] { - XTTE[] a = [{}, {}]; - XTTE[][] b = [[{}, {}], [{}, {}]]; + X[] a = [{}, {}]; + X[][] b = [[{}, {}], [{}, {}]]; any c = a; any d = b; - return [c is XTTE[], d is XTTE[][], c is YTTE[], d is YTTE[][]]; + return [c is X[], d is X[][], c is Y[], d is Y[][]]; } public function testUnionType() { @@ -742,20 +742,20 @@ function testSimpleTuples() returns [boolean, boolean, boolean, boolean, boolean } function testTupleWithAssignableTypes_1() returns [boolean, boolean, boolean, boolean] { - [XTTE, YTTE] p = [{}, {}]; + [X, Y] p = [{}, {}]; any q = p; - boolean b0 = q is [XTTE, XTTE]; - boolean b1 = q is [XTTE, YTTE]; - boolean b2 = q is [YTTE, XTTE]; - boolean b3 = q is [YTTE, YTTE]; + boolean b0 = q is [X, X]; + boolean b1 = q is [X, Y]; + boolean b2 = q is [Y, X]; + boolean b3 = q is [Y, Y]; return [b0, b1, b2, b3]; } function testTupleWithAssignableTypes_2() returns boolean { - [YTTE, YTTE] p = [{}, {}]; - [XTTE, YTTE] q = p; - boolean b1 = q is [YTTE, YTTE]; - return q is [YTTE, YTTE]; + [Y, Y] p = [{}, {}]; + [X, Y] q = p; + boolean b1 = q is [Y, Y]; + return q is [Y, Y]; } public function testRestType() { @@ -852,35 +852,35 @@ function testJsonArrays() returns [boolean, boolean, boolean] { // ========================== Finite type ========================== -type StateTN "on"|"off"; +type State "on"|"off"; function testFiniteType() returns [boolean, boolean, boolean] { - StateTN a = "on"; + State a = "on"; any b = a; any c = "off"; any d = "hello"; - return [b is StateTN, c is StateTN, d is StateTN]; + return [b is State, c is State, d is State]; } function testFiniteTypeInTuple() returns [boolean, boolean, boolean, boolean] { - [StateTN, string] x = ["on", "off"]; + [State, string] x = ["on", "off"]; any y = x; - boolean b0 = y is [StateTN, StateTN]; - boolean b1 = y is [StateTN, string]; - boolean b2 = y is [string, StateTN]; + boolean b0 = y is [State, State]; + boolean b1 = y is [State, string]; + boolean b2 = y is [string, State]; boolean b3 = y is [string, string]; return [b0, b1, b2, b3]; } -function testFiniteTypeInTuplePoisoning() returns [StateTN, StateTN] { - [StateTN, string] x = ["on", "off"]; +function testFiniteTypeInTuplePoisoning() returns [State, State] { + [State, string] x = ["on", "off"]; any y = x; - [StateTN, StateTN] z = ["on", "on"]; + [State, State] z = ["on", "on"]; - if (y is [StateTN, StateTN]) { + if (y is [State, State]) { z = y; } @@ -892,11 +892,11 @@ public const APPLE = "apple"; public const ORANGE = "orange"; public const GRAPE = "grape"; -type FruitTN APPLE | ORANGE | GRAPE; +type Fruit APPLE | ORANGE | GRAPE; function testFiniteType_1() returns string { any a = APPLE; - if (a is FruitTN) { + if (a is Fruit) { return "a is a fruit"; } @@ -1001,13 +1001,13 @@ function testIntersectingUnionFalse() returns [boolean, boolean] { function testValueTypeAsFiniteTypeTrue() returns [boolean, boolean] { string s = "orange"; float f = 2.0; - return [s is FruitTN, f is IntTwo]; + return [s is Fruit, f is IntTwo]; } function testValueTypeAsFiniteTypeFalse() returns [boolean, boolean] { string s = "mango"; float f = 12.0; - return [s is FruitTN, f is IntTwo]; + return [s is Fruit, f is IntTwo]; } const ERR_REASON = "error reason"; @@ -1213,12 +1213,12 @@ public function testXMLNeverType() { xml e = xml ``; test:assertEquals( e is byte, false); - test:assertEquals( e is xml<'xml:Element>, true); + test:assertEquals( e is xml<'xml:Element>, false); test:assertEquals( e is xml<'xml:Text>, true); test:assertEquals( e is xml, true); test:assertEquals( e is 'xml:Text, true); test:assertEquals( e is 'xml:Element, false); - test:assertEquals( e is xml<'xml:Element|'xml:Comment>, true); + test:assertEquals( e is xml<'xml:Element|'xml:Comment>, false); } function testXMLTextType(){ @@ -1428,7 +1428,7 @@ type MyClientObjectType client object { }; function testResourceMethodTyping() { - object {} objectVar = client object { + client object {} objectVar = client object { resource function post .() { } }; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/expressions/listconstructor/list_constructor_infer_type.bal b/tests/jballerina-unit-test/src/test/resources/test-src/expressions/listconstructor/list_constructor_infer_type.bal index 2001b8768bc0..8a4be1b310b8 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/expressions/listconstructor/list_constructor_infer_type.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/expressions/listconstructor/list_constructor_infer_type.bal @@ -14,12 +14,12 @@ // specific language governing permissions and limitations // under the License. -type FooListInfer record { +type Foo record { string s; int i = 1; }; -class BarListInfer { +class Bar { int i; public function init(int i) { @@ -27,8 +27,8 @@ class BarListInfer { } } -FooListInfer f = {s: "hello"}; -BarListInfer b = new (1); +Foo f = {s: "hello"}; +Bar b = new (1); json j = 1; function inferSimpleTuple() { @@ -40,14 +40,14 @@ function inferSimpleTuple() { function inferStructuredTuple() { var x = [f, b, xml `text`, j]; typedesc ta = typeof x; - assertEquality("typedesc [FooListInfer,BarListInfer,lang.xml:Text,json]", ta.toString()); + assertEquality("typedesc [Foo,Bar,lang.xml:Text,json]", ta.toString()); } function inferNestedTuple() { int[2] arr = [1, 2]; var x = [1, 2.0d, [3, f, [b, b]], arr, j]; typedesc ta = typeof x; - assertEquality("typedesc [int,decimal,[int,FooListInfer,[BarListInfer,BarListInfer]],int[2],json]", ta.toString()); + assertEquality("typedesc [int,decimal,[int,Foo,[Bar,Bar]],int[2],json]", ta.toString()); } function testInferSameRecordsInTuple() { @@ -102,15 +102,15 @@ function testInferringForReadOnly() { error err = res; assertEquality("modification not allowed on readonly value", err.detail()["message"]); - FooListInfer & readonly foo = { + Foo & readonly foo = { s: "May", i: 20 }; readonly rd2 = [1, [b, false], foo, foo]; - assertEquality(true, rd2 is [int, [boolean, boolean], FooListInfer, FooListInfer & readonly] & readonly); - assertEquality(false, rd2 is [int, [boolean, boolean], object {} & readonly, FooListInfer & readonly] & readonly); - [int, [boolean, boolean], FooListInfer, FooListInfer] arr2 = <[int, [boolean, boolean], FooListInfer, FooListInfer] & readonly> checkpanic rd2; + assertEquality(true, rd2 is [int, [boolean, boolean], Foo, Foo & readonly] & readonly); + assertEquality(false, rd2 is [int, [boolean, boolean], object {} & readonly, Foo & readonly] & readonly); + [int, [boolean, boolean], Foo, Foo] arr2 = <[int, [boolean, boolean], Foo, Foo] & readonly> checkpanic rd2; fn = function() { arr2[0] = 2; @@ -123,17 +123,17 @@ function testInferringForReadOnly() { } function testInferringForReadOnlyInUnion() { - FooListInfer & readonly foo = { + Foo & readonly foo = { s: "May", i: 20 }; boolean b = true; - readonly|(FooListInfer|int)[] rd = [1, [b, false], foo, foo]; + readonly|(Foo|int)[] rd = [1, [b, false], foo, foo]; - assertEquality(true, rd is [int, [boolean, boolean], FooListInfer, FooListInfer & readonly] & readonly); - assertEquality(false, rd is [int, [boolean, boolean], object {} & readonly, FooListInfer & readonly] & readonly); - [int, [boolean, boolean], FooListInfer, FooListInfer] arr = <[int, [boolean, boolean], FooListInfer, FooListInfer] & readonly> checkpanic rd; + assertEquality(true, rd is [int, [boolean, boolean], Foo, Foo & readonly] & readonly); + assertEquality(false, rd is [int, [boolean, boolean], object {} & readonly, Foo & readonly] & readonly); + [int, [boolean, boolean], Foo, Foo] arr = <[int, [boolean, boolean], Foo, Foo] & readonly> checkpanic rd; var fn = function() { arr[0] = 2; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/expressions/typecast/type-casting.bal b/tests/jballerina-unit-test/src/test/resources/test-src/expressions/typecast/type-casting.bal index eb260a6c4ec9..cb1f503e661f 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/expressions/typecast/type-casting.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/expressions/typecast/type-casting.bal @@ -481,27 +481,27 @@ function testStringToJson(string s) returns (json) { return s; } -type PersonTC record { +type Person record { string name; int age; map address = {}; int[] marks = []; - PersonTC | () parent = (); + Person | () parent = (); json info = {}; anydata a = 0; float score = 0.0; boolean alive = true; }; -type StudentTC record { +type Student record { string name; int age; map address = {}; int[] marks = []; }; -function testStructToStruct() returns (StudentTC) { - PersonTC p = { name:"Supun", +function testStructToStruct() returns (Student) { + Person p = { name:"Supun", age:25, parent:{name:"Parent", age:50}, address:{"city":"Kandy", "country":"SriLanka"}, @@ -512,13 +512,13 @@ function testStructToStruct() returns (StudentTC) { return p2; } -function testNullStructToStruct() returns StudentTC { - PersonTC? p = (); - return p; +function testNullStructToStruct() returns Student { + Person? p = (); + return p; } -function testStructAsAnyToStruct() returns PersonTC|error { - PersonTC p1 = { name:"Supun", +function testStructAsAnyToStruct() returns Person|error { + Person p1 = { name:"Supun", age:25, parent:{name:"Parent", age:50}, address:{"city":"Kandy", "country":"SriLanka"}, @@ -526,11 +526,11 @@ function testStructAsAnyToStruct() returns PersonTC|error { marks:[24, 81] }; any a = p1; - var p2 = check trap a; + var p2 = check trap a; return p2; } -function testAnyToStruct() returns PersonTC { +function testAnyToStruct() returns Person { json address = {"city":"Kandy", "country":"SriLanka"}; map parent = {name:"Parent", age:50}; map info = {status:"single"}; @@ -543,18 +543,18 @@ function testAnyToStruct() returns PersonTC { marks:marks }; any b = a; - var p2 = b; + var p2 = b; return p2; } -function testAnyNullToStruct() returns PersonTC { +function testAnyNullToStruct() returns Person { any a = (); - var p = a; + var p = a; return p; } function testRecordToAny() returns (any) { - PersonTC p = { name:"Supun", + Person p = { name:"Supun", age:25, parent:{name:"Parent", age:50}, address:{"city":"Kandy", "country":"SriLanka"}, @@ -601,7 +601,7 @@ function testBooleanInJsonToInt() { } } -type AddressTC record { +type Address record { string city; string country = ""; }; @@ -671,7 +671,7 @@ function testAnyMapToJson() returns json { } function testAnyStructToJson() returns json { - AddressTC adrs = {city:"CA"}; + Address adrs = {city:"CA"}; any a = adrs; json value; value = a; @@ -917,18 +917,18 @@ function testJSONValueCasting() returns [string|error, int|error, float|error, b } function testAnyToTable() { - table tb = table [ + table tb = table [ {id:1, name:"Jane"}, {id:2, name:"Anne"} ]; any anyValue = tb; - var casted = > anyValue; - table castedValue = casted; + var casted = > anyValue; + table castedValue = casted; assertEquality("[{\"id\":1,\"name\":\"Jane\"},{\"id\":2,\"name\":\"Anne\"}]", castedValue.toString()); } -type EmployeeTC record { +type Employee record { int id; string name; }; @@ -998,31 +998,32 @@ function testCastOfReadonlyUnionArrayToByteArray() { assertEquality("[1,2,3]", f.toString()); } -type FooTC record {| +type Foo record {| string s; int[] arr; |}; -type BarTC record {| +type Bar record {| string s; byte[] arr; |}; function testCastOfReadonlyRecord() { - (FooTC & readonly) f = {s: "a", arr: [1,2,3]}; + (Foo & readonly) f = {s: "a", arr: [1,2,3]}; any a = f; - BarTC b = a; + Bar b = a; assertEquality(true, b === a); assertEquality("{\"s\":\"a\",\"arr\":[1,2,3]}", b.toString()); } function testCastOfReadonlyRecordNegative() { - (FooTC & readonly) f = {s: "a", arr: [1,2,300]}; + (Foo & readonly) f = {s: "a", arr: [1,2,300]}; any a = f; - BarTC|error b = trap a; + Bar|error b = trap a; assertEquality(true, b is error); error err = b; - string errMsg = "incompatible types: '(FooTC & readonly)' cannot be cast to 'BarTC'"; + string errMsg = "incompatible types: '(Foo & readonly)' cannot be cast to 'Bar': " + + "\n\t\tfield 'arr' in record 'Bar' should be of type 'byte[]', found '[1,2,300]'"; assertEquality("{ballerina}TypeCastError", err.message()); assertEquality(errMsg, checkpanic err.detail()["message"]); } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/expressions/typecast/type_cast_expr_runtime_errors.bal b/tests/jballerina-unit-test/src/test/resources/test-src/expressions/typecast/type_cast_expr_runtime_errors.bal deleted file mode 100644 index 677ca81a319f..000000000000 --- a/tests/jballerina-unit-test/src/test/resources/test-src/expressions/typecast/type_cast_expr_runtime_errors.bal +++ /dev/null @@ -1,245 +0,0 @@ - // Copyright (c) 2024 WSO2 LLC. (http://www.wso2.com). - // - // WSO2 LLC. licenses this file to you under the Apache License, - // Version 2.0 (the "License"); you may not use this file except - // in compliance with the License. - // You may obtain a copy of the License at - // - // http://www.apache.org/licenses/LICENSE-2.0 - // - // Unless required by applicable law or agreed to in writing, - // software distributed under the License is distributed on an - // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - // KIND, either express or implied. See the License for the - // specific language governing permissions and limitations - // under the License. - -function f1() { - xml A = xml `xml string`; - [string, int|xml, string...] C = ["text1", 1, A.toString()]; - json jsonTest = C; -} - -function testTupleToJSONCastRuntimeError() returns error? { - var e = trap f1(); - return e is error ? e : (); -} - -type Teacher record { - readonly string name; - readonly int age; - string school; -}; - -type Customer record { - readonly int id; - readonly string name; - string lname; -}; - -type CustomerTable table; - -CustomerTable tab3 = table key(name) [ - {id: 13, name: "Foo", lname: "QWER"}, - {id: 13, name: "Bar", lname: "UYOR"} -]; - -type Customer2 record {| - int id; - string name; - string lname; -|}; - -type CustomerEmptyKeyedTbl table key(); - -function f2() { - CustomerEmptyKeyedTbl tbl1 = tab3; -} - -function testCastingWithEmptyKeyedKeylessTbl() returns error? { - var e = trap f2(); - return e is error ? e : (); -} - -type Student record { - int index; - int age; -}; - -type Person record { - string name; - int age; - string address; -}; - -function f3() returns map { - map testPMap = {}; - map testSMap = >testPMap; - return testSMap; -} - -function testMapCastingRuntimeError() returns error? { - var e = trap f3(); - return e is error ? e : (); -} - -function f4() { - string[]|int val1 = []; - byte[] a = val1; -} - -function testListCastingRuntimeError() returns error? { - var e = trap f4(); - return e is error ? e : (); -} - -public class person01 { - - public int age = 0; - public string name = ""; - public string address = ""; - -} - -public class employee01 { - - public int age = 0; - public string name = ""; - public string zipcode = "95134"; - - function init (int age, string name) { - self.age = age; - self.name = name; - } -} - -function f5() returns string { - employee01 e = new (14, "rat"); - person01 p = e; - return p.name; -} - -function testCastingObjects() returns error? { - var e = trap f5(); - return e is error ? e : (); -} - -public class employee08 { - - public int age = 0; - public string name = ""; - public string address = ""; - public string zipcode = "95134"; - public string ssn = ""; - - - function init (int age, string name) { - self.age = age; - self.name = name; - } - - public function getName() returns string { - return self.name; - } - - public function getAge() returns int { - return self.age; - } - - public function getSSN() returns string { - return self.ssn; - } -} - -public class person08 { - - public int age = 0; - public string name = ""; - public string address = ""; - public string zipcode = "95134"; - public string ssn = ""; - - - public function getAge() returns int { - return self.age; - } - - public function getName() returns string { - return self.name; - } - - public function setSSN(string s) { - self.ssn = s; - } -} - -function f6() returns string { - employee08 e = new (14, "rat"); - person08 p = e; - return p.name; -} - -function testCastingObjects2() returns error? { - var e = trap f6(); - return e is error ? e : (); -} - -public class person09 { - - public int age = 0; - public string name = ""; - public string address = ""; - public string zipcode = "95134"; - public string ssn = ""; - - - public function getAge() returns int { - return self.age; - } - - public function getName() returns string { - return self.name; - } - - public function setSSN(string s) { - self.ssn = s; - } -} - -public class employee09 { - - public int age = 0; - public string name = ""; - public string address = ""; - public string zipcode = "95134"; - public string ssn = ""; - - - function init (int age, string name) { - self.age = age; - self.name = name; - } - - public function getName() returns string { - return self.name; - } - - public function getAge(int i) returns int { - return self.age; - } - - public function getSSN() returns string { - return self.ssn; - } -} - -function f7() returns string { - employee09 e = new (14, "rat"); - person09 p = e; - return p.name; -} - -function testCastingObjects3() returns error? { - var e = trap f7(); - return e is error ? e : (); -} diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/javainterop/dependently_typed_functions_bir_test.bal b/tests/jballerina-unit-test/src/test/resources/test-src/javainterop/dependently_typed_functions_bir_test.bal index 28bd92404743..7c9f597e4e39 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/javainterop/dependently_typed_functions_bir_test.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/javainterop/dependently_typed_functions_bir_test.bal @@ -16,17 +16,18 @@ import testorg/foo.dependently_typed as rt; -type PersonDTBT record { +type Person record { readonly string name; int age; }; -type EmployeeDTBT record { - *PersonDTBT; +type Employee record { + *Person; string designation; }; -PersonDTBT expPerson = {name: "John Doe", age: 20}; +Person expPerson = {name: "John Doe", age: 20}; + // Test functions @@ -48,11 +49,11 @@ function testSimpleTypes() { } function testRecordVarRef() { - PersonDTBT p = rt:getRecord(); + Person p = rt:getRecord(); assert(expPerson, p); - EmployeeDTBT e = rt:getRecord(td = EmployeeDTBT); - assert({name: "Jane Doe", age: 25, designation: "Software Engineer"}, e); + Employee e = rt:getRecord(td = Employee); + assert({name: "Jane Doe", age: 25, designation: "Software Engineer"}, e); } function testVarRefInMapConstraint() { @@ -68,12 +69,12 @@ function testRuntimeCastError() { } function testVarRefUseInMultiplePlaces() { - [int, PersonDTBT, float] tup1 = rt:getTuple(int, PersonDTBT); - assert(<[int, PersonDTBT, float]>[150, expPerson, 12.34], tup1); + [int, Person, float] tup1 = rt:getTuple(int, Person); + assert(<[int, Person, float]>[150, expPerson, 12.34], tup1); } function testUnionTypes() { - int|PersonDTBT u = rt:getVariedUnion(1, int, PersonDTBT); + int|Person u = rt:getVariedUnion(1, int, Person); assert(expPerson, u); } @@ -83,7 +84,7 @@ function testArrayTypes() { } function testCastingForInvalidValues() { - int _ = rt:getInvalidValue(int, PersonDTBT); + int _ = rt:getInvalidValue(int, Person); } type XmlElement xml:Element; @@ -100,21 +101,19 @@ function testStream() { stream newSt = rt:getStream(st, string); string s = ""; - newSt.forEach(function(string x) { - s += x; - }); + newSt.forEach(function (string x) { s += x; }); assert("helloworldfromballerina", s); } function testTable() { - table key(name) tab = table [ - {name: "Chiran", age: 33, designation: "SE"}, - {name: "Mohan", age: 37, designation: "SE"}, - {name: "Gima", age: 38, designation: "SE"}, - {name: "Granier", age: 34, designation: "SE"} + table key(name) tab = table [ + { name: "Chiran", age: 33, designation: "SE" }, + { name: "Mohan", age: 37, designation: "SE" }, + { name: "Gima", age: 38, designation: "SE" }, + { name: "Granier", age: 34, designation: "SE" } ]; - table newTab = rt:getTable(tab, PersonDTBT); + table newTab = rt:getTable(tab, Person); assert(tab, newTab); } @@ -126,12 +125,12 @@ function testFunctionPointers() { } function testTypedesc() { - typedesc tP = rt:getTypedesc(PersonDTBT); - assert(PersonDTBT.toString(), tP.toString()); + typedesc tP = rt:getTypedesc(Person); + assert(Person.toString(), tP.toString()); } function testFuture() { - var fn = function(string name) returns string => "Hello " + name; + var fn = function (string name) returns string => "Hello " + name; future f = start fn("Pubudu"); future fNew = rt:getFuture(f, string); string res = checkpanic wait fNew; @@ -151,12 +150,9 @@ class PersonObj { function name() returns string => self.fname + " " + self.lname; } -type PersonTable table; - +type PersonTable table; type IntStream stream; - type IntArray int[]; - type XmlType xml; function testComplexTypes() { @@ -169,7 +165,7 @@ function testComplexTypes() { int[] ar = rt:echo([20, 30, 40], IntArray); assert([20, 30, 40], ar); - PersonObj pObj = new ("John", "Doe"); + PersonObj pObj = new("John", "Doe"); PersonObj nObj = rt:echo(pObj, PersonObj); assertSame(pObj, nObj); @@ -178,19 +174,17 @@ function testComplexTypes() { stream newSt = rt:echo(st, IntStream); int tot = 0; - newSt.forEach(function(int x1) { - tot += x1; - }); + newSt.forEach(function (int x1) { tot+= x1; }); assert(150, tot); - table key(name) tab = table [ - {name: "Chiran", age: 33}, - {name: "Mohan", age: 37}, - {name: "Gima", age: 38}, - {name: "Granier", age: 34} + table key(name) tab = table [ + { name: "Chiran", age: 33}, + { name: "Mohan", age: 37}, + { name: "Gima", age: 38}, + { name: "Granier", age: 34} ]; - table newTab = rt:echo(tab, PersonTable); + table newTab = rt:echo(tab, PersonTable); assert(tab, newTab); } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/javainterop/dependently_typed_functions_test.bal b/tests/jballerina-unit-test/src/test/resources/test-src/javainterop/dependently_typed_functions_test.bal index bb681bdbc8c4..49817c076771 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/javainterop/dependently_typed_functions_test.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/javainterop/dependently_typed_functions_test.bal @@ -17,24 +17,23 @@ import ballerina/jballerina.java; type ItemType xml:Element|xml:Comment|xml:ProcessingInstruction|xml:Text; - type XmlElement xml:Element; -type PersonDTFT record { +type Person record { readonly string name; int age; }; -type EmployeeDTFT record { - *PersonDTFT; +type Employee record { + *Person; string designation; }; -PersonDTFT expPerson = {name: "John Doe", age: 20}; +Person expPerson = {name: "John Doe", age: 20}; -type FooDTFT int|float; +type Foo int|float; -type Foo2DTFT FooDTFT; +type Foo2 Foo; type AnnotationRecord record {| int minValue; @@ -53,7 +52,7 @@ type Foo3 int|float; minValue: 12, maxValue: 24 } -type Foo4 FooDTFT; +type Foo4 Foo; // Test functions @@ -75,31 +74,31 @@ function testSimpleTypes() { } function testReferredTypes() { - map annotationMapValue = getAnnotationValue(FooDTFT); - AnnotationRecord? 'annotation = annotationMapValue["BarAnnotation"]; + map annotationMapValue = getAnnotationValue(Foo); + AnnotationRecord? 'annotation = annotationMapValue["BarAnnotation"]; assert('annotation, ()); - map annotationMapValue2 = getAnnotationValue(Foo2DTFT); - AnnotationRecord? annotation2 = annotationMapValue2["BarAnnotation"]; + map annotationMapValue2 = getAnnotationValue(Foo2); + AnnotationRecord? annotation2 = annotationMapValue2["BarAnnotation"]; assert(annotation2, ()); map annotationMapValue3 = getAnnotationValue(Foo3); - AnnotationRecord annotation3 = annotationMapValue3["BarAnnotation"]; + AnnotationRecord annotation3 = annotationMapValue3["BarAnnotation"]; assert(annotation3, {minValue: 18, maxValue: 36}); assertTrue(getAnnotationValue2(1, Foo3, "BarAnnotation", 18, 36) is anydata); map annotationMapValue4 = getAnnotationValue(Foo4); - AnnotationRecord annotation4 = annotationMapValue4["BarAnnotation"]; - assert(annotation4, {minValue: 12, maxValue: 24}); + AnnotationRecord annotation4 = annotationMapValue4["BarAnnotation"]; + assert(annotation4, {minValue: 12, maxValue: 24}); assertTrue(getAnnotationValue2(1, Foo4, "BarAnnotation", 12, 24) is anydata); } function testRecordVarRef() { - PersonDTFT p = getRecord(); + Person p = getRecord(); assert(expPerson, p); - EmployeeDTFT e = getRecord(td = EmployeeDTFT); - assert({name: "Jane Doe", age: 25, designation: "Software Engineer"}, e); + Employee e = getRecord(td = Employee); + assert({name: "Jane Doe", age: 25, designation: "Software Engineer"}, e); } function testVarRefInMapConstraint() { @@ -115,12 +114,12 @@ function testRuntimeCastError() { } function testVarRefUseInMultiplePlaces() { - [int, PersonDTFT, float] tup1 = getTuple(int, PersonDTFT); - assert(<[int, PersonDTFT, float]>[150, expPerson, 12.34], tup1); + [int, Person, float] tup1 = getTuple(int, Person); + assert(<[int, Person, float]>[150, expPerson, 12.34], tup1); } function testUnionTypes() { - int|PersonDTFT u = getVariedUnion(1, int, PersonDTFT); + int|Person u = getVariedUnion(1, int, Person); assert(expPerson, u); } @@ -130,7 +129,7 @@ function testArrayTypes() { } function testCastingForInvalidValues() { - int x = getInvalidValue(int, PersonDTFT); + int x = getInvalidValue(int, Person); } function testXML() { @@ -145,21 +144,19 @@ function testStream() { stream newSt = getStream(st, string); string s = ""; - error? err = newSt.forEach(function(string x) { - s += x; - }); + error? err = newSt.forEach(function (string x) { s += x; }); assert("helloworldfromballerina", s); } function testTable() { - table key(name) tab = table [ - {name: "Chiran", age: 33, designation: "SE"}, - {name: "Mohan", age: 37, designation: "SE"}, - {name: "Gima", age: 38, designation: "SE"}, - {name: "Granier", age: 34, designation: "SE"} + table key(name) tab = table [ + { name: "Chiran", age: 33, designation: "SE" }, + { name: "Mohan", age: 37, designation: "SE" }, + { name: "Gima", age: 38, designation: "SE" }, + { name: "Granier", age: 34, designation: "SE" } ]; - table newTab = getTable(tab, PersonDTFT); + table newTab = getTable(tab, Person); assert(tab, newTab); } @@ -171,12 +168,12 @@ function testFunctionPointers() { } function testTypedesc() { - typedesc tP = getTypedesc(PersonDTFT); - assert(PersonDTFT.toString(), tP.toString()); + typedesc tP = getTypedesc(Person); + assert(Person.toString(), tP.toString()); } function testFuture() { - var fn = function(string name) returns string => "Hello " + name; + var fn = function (string name) returns string => "Hello " + name; future f = start fn("Pubudu"); future fNew = getFuture(f, string); string res = checkpanic wait fNew; @@ -214,7 +211,7 @@ class PersonObj { type IntStream stream; -type PersonTable table; +type PersonTable table; type IntArray int[]; @@ -230,7 +227,7 @@ function testComplexTypes() { int[] ar = echo([20, 30, 40], IntArray); assert([20, 30, 40], ar); - PersonObj pObj = new ("John", "Doe"); + PersonObj pObj = new("John", "Doe"); PersonObj nObj = echo(pObj, PersonObj); assertSame(pObj, nObj); @@ -239,24 +236,22 @@ function testComplexTypes() { stream newSt = echo(st, IntStream); int tot = 0; - error? err = newSt.forEach(function(int x1) { - tot += x1; - }); + error? err = newSt.forEach(function (int x1) { tot+= x1; }); assert(150, tot); - table key(name) tab = table [ - {name: "Chiran", age: 33}, - {name: "Mohan", age: 37}, - {name: "Gima", age: 38}, - {name: "Granier", age: 34} + table key(name) tab = table [ + { name: "Chiran", age: 33}, + { name: "Mohan", age: 37}, + { name: "Gima", age: 38}, + { name: "Granier", age: 34} ]; - table newTab = echo(tab, PersonTable); + table newTab = echo(tab, PersonTable); assert(tab, newTab); } function testObjectExternFunctions() { - PersonObj pObj = new ("John", "Doe"); + PersonObj pObj = new("John", "Doe"); string s = pObj.getObjectValue(string); assert("John Doe", s); s = pObj.getObjectValueWithTypeDescParam(string); @@ -280,6 +275,7 @@ function testFunctionAssignment() { x = fn(string); } + // Interop functions function getValue(typedesc td) returns td = @java:Method { 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", @@ -287,20 +283,20 @@ function getValue(typedesc td) returns td = @j paramTypes: ["io.ballerina.runtime.api.values.BTypedesc"] } external; -function getAnnotationValue(typedesc y) returns map = +function getAnnotationValue(typedesc y) returns map = @java:Method { - 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", - name: "getAnnotationValue" -} external; + 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", + name: "getAnnotationValue" + } external; function getAnnotationValue2(anydata value, typedesc td = <>, string annotationName = "", - int min = 0, int max = 0) returns td|error = + int min = 0, int max = 0) returns td|error = @java:Method { - 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", - name: "getAnnotationValue2" -} external; + 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", + name: "getAnnotationValue2" + } external; -function getRecord(typedesc td = PersonDTFT) returns td = @java:Method { +function getRecord(typedesc td = Person) returns td = @java:Method { 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", name: "getRecord", paramTypes: ["io.ballerina.runtime.api.values.BTypedesc"] @@ -318,7 +314,7 @@ function getTuple(typedesc td1, typedesc td2, typedesc td1, typedesc td2) returns (td1|td2) = @java:Method { +function getVariedUnion(int x, typedesc td1, typedesc td2) returns (td1|td2) = @java:Method { 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", name: "getVariedUnion", paramTypes: ["long", "io.ballerina.runtime.api.values.BTypedesc", "io.ballerina.runtime.api.values.BTypedesc"] @@ -336,7 +332,7 @@ function getArrayInferred(typedesc td = <>) returns td[] = @java:Method paramTypes: ["io.ballerina.runtime.api.values.BTypedesc"] } external; -function getInvalidValue(typedesc td1, typedesc td2) returns td1 = @java:Method { +function getInvalidValue(typedesc td1, typedesc td2) returns td1 = @java:Method { 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", name: "getInvalidValue", paramTypes: ["io.ballerina.runtime.api.values.BTypedesc", "io.ballerina.runtime.api.values.BTypedesc"] @@ -364,11 +360,8 @@ function getFunction(function (string|int) returns anydata fn, typedesc returns function (param) returns ret = @java:Method { 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", name: "getFunction", - paramTypes: [ - "io.ballerina.runtime.api.values.BFunctionPointer", - "io.ballerina.runtime.api.values.BTypedesc", - "io.ballerina.runtime.api.values.BTypedesc" - ] + paramTypes: ["io.ballerina.runtime.api.values.BFunctionPointer", "io.ballerina.runtime.api.values.BTypedesc", + "io.ballerina.runtime.api.values.BTypedesc"] } external; function getTypedesc(typedesc td) returns typedesc = @java:Method { @@ -432,13 +425,13 @@ var outParameterObject = object OutParameter { function testDependentlyTypedMethodsWithObjectTypeInclusion() { OutParameterClass c1 = new; int|error v1 = c1.get(int); - assert(1234, checkpanic v1); + assert(1234, checkpanic v1); assertSame(c1.c, c1.get(float)); - assert("hello world", checkpanic c1.get(string)); + assert("hello world", checkpanic c1.get(string)); - assert(321, checkpanic outParameterObject.get(int)); + assert(321, checkpanic outParameterObject.get(int)); decimal|error v2 = outParameterObject.get(decimal); - assert(23.45d, checkpanic v2); + assert(23.45d, checkpanic v2); } public class Bar { @@ -516,49 +509,49 @@ public function testSubtypingWithDependentlyTypedMethods() { Baz baz = new; Qux qux = new; - assert(1, checkpanic bar.get(int)); - assert(2, checkpanic baz.get(int)); - assert(3, checkpanic qux.get(int)); + assert(1, checkpanic bar.get(int)); + assert(2, checkpanic baz.get(int)); + assert(3, checkpanic qux.get(int)); decimal|error v2 = bar.get(decimal); - assert(23.45d, checkpanic v2); + assert(23.45d, checkpanic v2); anydata|error v3 = baz.get(decimal); - assert(23.45d, checkpanic v3); + assert(23.45d, checkpanic v3); v2 = qux.get(decimal); - assert(23.45d, checkpanic v2); + assert(23.45d, checkpanic v2); Baz baz1 = bar; Bar bar1 = qux; - assert(1, checkpanic baz1.get(int)); - assert(3, checkpanic bar1.get(int)); + assert(1, checkpanic baz1.get(int)); + assert(3, checkpanic bar1.get(int)); - assert(true, bar is Baz); - assert(true, qux is Bar); - assert(true, bar is Qux); - assert(false, baz is Bar); - assert(false, new Quux() is Qux); - assert(false, qux is Quux); + assert(true, bar is Baz); + assert(true, qux is Bar); + assert(true, bar is Qux); + assert(false, baz is Bar); + assert(false, new Quux() is Qux); + assert(false, qux is Quux); Corge corge = new Grault(); - assert(200, checkpanic corge.get(int, string)); - assert("Hello World!", checkpanic corge.get(string, int)); + assert(200, checkpanic corge.get(int, string)); + assert("Hello World!", checkpanic corge.get(string, int)); Grault grault = new Corge(); - assert(100, checkpanic grault.get(int, string)); - assert("Hello World!", checkpanic grault.get(string, float)); + assert(100, checkpanic grault.get(int, string)); + assert("Hello World!", checkpanic grault.get(string, float)); - assert(true, new Corge() is Grault); - assert(true, new Grault() is Corge); - assert(true, new Corge() is Garply); - assert(true, new Garply() is Corge); - assert(true, new Grault() is Garply); - assert(true, new Garply() is Grault); + assert(true, new Corge() is Grault); + assert(true, new Grault() is Corge); + assert(false, new Corge() is Garply); + assert(false, new Garply() is Corge); + assert(false, new Grault() is Garply); + assert(false, new Garply() is Grault); } function getWithDefaultableParams(int|string x, int|string y = 1, typedesc z = int) returns z = @java:Method { - 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", - name: "getWithDefaultableParams" -} external; + 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", + name: "getWithDefaultableParams" + } external; function testDependentlyTypedFunctionWithDefaultableParams() { int a = getWithDefaultableParams(1); @@ -591,12 +584,12 @@ type IntOrString int|string; public function testStartActionWithDependentlyTypedFunctions() { Client cl = new; - var assert1 = function(future f) { + var assert1 = function (future f) { int|string|error r = wait f; assert(true, r is error); - error e = r; + error e = r; assert("Error!", e.message()); - assert("Union typedesc", checkpanic e.detail()["message"]); + assert("Union typedesc", checkpanic e.detail()["message"]); }; future a = start getWithUnion("", IntOrString); assert1(a); @@ -605,7 +598,7 @@ public function testStartActionWithDependentlyTypedFunctions() { future c = start cl->remoteGet("", IntOrString); assert1(c); - var assert2 = function(future f, int expected) { + var assert2 = function (future f, int expected) { int|error r = wait f; assert(true, r is int); assert(expected, checkpanic r); @@ -619,7 +612,7 @@ public function testStartActionWithDependentlyTypedFunctions() { future g = start cl->remoteGet("hi", int); assert2(g, 2); - var assert3 = function(future f, string expected) { + var assert3 = function (future f, string expected) { string|error r = wait f; assert(true, r is string); assert(expected, checkpanic r); @@ -634,9 +627,9 @@ public function testStartActionWithDependentlyTypedFunctions() { function getWithUnion(int|string x, typedesc y) returns y|error = @java:Method { - 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", - name: "getWithUnion" -} external; + 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", + name: "getWithUnion" + } external; client class Client { function get(int|string x, typedesc y = int) returns y|error = @java:Method { @@ -651,12 +644,12 @@ client class Client { } function getWithRestParam(int i, typedesc j, int... k) returns j|boolean = - @java:Method { - 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType" -} external; + @java:Method { + 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType" + } external; function getWithMultipleTypedescs(int i, typedesc j, typedesc k, typedesc... l) - returns j|k|boolean = @java:Method {'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType"} external; + returns j|k|boolean = @java:Method { 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType" } external; function testArgsForDependentlyTypedFunctionViaTupleRestArg() { [typedesc] a = [string]; @@ -735,7 +728,7 @@ type IJK record {| |}; function testArgsForDependentlyTypedFunctionViaRecordRestArg() { - record {|typedesc y;|} a = {y: string}; + record {| typedesc y; |} a = {y: string}; string|error b = getWithUnion(123, ...a); assert("123", checkpanic b); @@ -747,7 +740,7 @@ function testArgsForDependentlyTypedFunctionViaRecordRestArg() { string|boolean f = getWithRestParam(...e); assert(true, f); - record {|typedesc j = string;|} g = {}; + record {| typedesc j = string; |} g = {}; string|boolean h = getWithRestParam(1, ...g); assert(false, h); @@ -755,11 +748,11 @@ function testArgsForDependentlyTypedFunctionViaRecordRestArg() { int|string|boolean n = getWithMultipleTypedescs(...m); assert(true, n); - record {|typedesc j = string; typedesc k;|} o = {k: int}; + record {| typedesc j = string; typedesc k; |} o = {k: int}; int|string|boolean p = getWithMultipleTypedescs(1, ...o); assert(true, p); - record {|int i; typedesc j = byte; typedesc k;|} q = {i: 1, k: byte}; + record {| int i; typedesc j = byte; typedesc k; |} q = {i: 1, k: byte}; byte|boolean r = getWithMultipleTypedescs(...q); assert(true, r); } @@ -774,29 +767,29 @@ public type TargetType typedesc; public client class ClientWithMethodWithIncludedRecordParamAndDefaultableParams { remote function post(TargetType targetType = int, *ClientActionOptions options) returns @tainted targetType = @java:Method { - 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", - name: "clientPost" - } external; - + 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", + name: "clientPost" + } external; + function calculate(int i, TargetType targetType = int, *ClientActionOptions options) returns @tainted targetType = @java:Method { - 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", - name: "calculate" - } external; + 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", + name: "calculate" + } external; } public client class ClientWithMethodWithIncludedRecordParamAndRequiredParams { remote function post(TargetType targetType, *ClientActionOptions options) returns @tainted targetType = @java:Method { - 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", - name: "clientPost" - } external; + 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", + name: "clientPost" + } external; function calculate(int i, TargetType targetType, *ClientActionOptions options) returns @tainted targetType|error = @java:Method { - 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", - name: "calculate" - } external; + 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", + name: "calculate" + } external; } function testDependentlyTypedFunctionWithIncludedRecordParam() { @@ -892,58 +885,57 @@ function testDependentlyTypedFunctionWithIncludedRecordParam() { client class ClientObjImpl { *ClientObject; - - remote isolated function query(stream strm, typedesc rowType = <>) returns stream = + remote isolated function query(stream strm, typedesc rowType = <>) returns stream = @java:Method { - 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", - name: "getStreamOfRecords", - paramTypes: ["io.ballerina.runtime.api.values.BStream", "io.ballerina.runtime.api.values.BTypedesc"] - } external; + 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", + name: "getStreamOfRecords", + paramTypes: ["io.ballerina.runtime.api.values.BStream", "io.ballerina.runtime.api.values.BTypedesc"] + } external; } public type ClientObject client object { - remote isolated function query(stream strm, typedesc rowType = <>) returns stream; + remote isolated function query(stream strm, typedesc rowType = <>) returns stream ; }; function testDependentlyTypedMethodCallOnObjectType() { ClientObject cl = new ClientObjImpl(); - PersonDTFT p1 = getRecord(); - PersonDTFT p2 = getRecord(); - PersonDTFT[] personList = [p1, p2]; - stream personStream = personList.toStream(); - stream y = cl->query(personStream, PersonDTFT); + Person p1 = getRecord(); + Person p2 = getRecord(); + Person[] personList = [p1, p2]; + stream personStream = personList.toStream(); + stream y = cl->query(personStream, Person); var rec = y.next(); - if (rec is record {|PersonDTFT value;|}) { - PersonDTFT person = rec.value; + if (rec is record {| Person value; |}) { + Person person = rec.value; assert(20, person.age); assert("John Doe", person.name); } rec = y.next(); - assert(true, rec is record {|PersonDTFT value;|}); + assert(true, rec is record {| Person value; |}); } function testDependentlyTypedMethodCallOnObjectTypeWithInferredArgument() { ClientObject cl = new ClientObjImpl(); - PersonDTFT p1 = getRecord(); - PersonDTFT p2 = getRecord(); - PersonDTFT[] personList = [p1, p2]; - stream personStream = personList.toStream(); - stream y = cl->query(personStream); + Person p1 = getRecord(); + Person p2 = getRecord(); + Person[] personList = [p1, p2]; + stream personStream = personList.toStream(); + stream y = cl->query(personStream); var rec = y.next(); - if (rec is record {|PersonDTFT value;|}) { - PersonDTFT person = rec.value; + if (rec is record {| Person value; |}) { + Person person = rec.value; assert(20, person.age); assert("John Doe", person.name); } rec = y.next(); - assert(true, rec is record {|PersonDTFT value;|}); + assert(true, rec is record {| Person value; |}); } function functionWithInferredArgForParamOfTypeReferenceType(TargetType t = <>) returns t = @java:Method { - 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", - name: "functionWithInferredArgForParamOfTypeReferenceType" -} external; + 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", + name: "functionWithInferredArgForParamOfTypeReferenceType" + } external; function testDependentlyTypedFunctionWithInferredArgForParamOfTypeReferenceType() { int a = functionWithInferredArgForParamOfTypeReferenceType(); @@ -971,18 +963,18 @@ function testDependentlyTypedResourceMethods() { ClientWithExternalResourceBody cl = new ClientWithExternalResourceBody(); string|error a = cl->/games/carrom(targetType = string); assert("[\"games\",\"carrom\"]", checkpanic a); - + var cl2 = client object { resource function get [string... path](TargetType targetType = <>) returns targetType|error = @java:Method { - 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", - name: "getResource" - } external; + 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", + name: "getResource" + } external; }; string|error b = cl2->/games/football(targetType = string); assert("[\"games\",\"football\"]", checkpanic b); - + int|error c = cl2->/games/football(); assert(0, checkpanic c); } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/javainterop/inferred_dependently_typed_func_signature.bal b/tests/jballerina-unit-test/src/test/resources/test-src/javainterop/inferred_dependently_typed_func_signature.bal index 06beac3920e1..d1e9afa45b5e 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/javainterop/inferred_dependently_typed_func_signature.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/javainterop/inferred_dependently_typed_func_signature.bal @@ -16,17 +16,18 @@ import ballerina/jballerina.java; -type PersonIDTF record { +type Person record { readonly string name; int age; }; -type EmployeeIDTF record { - *PersonIDTF; +type Employee record { + *Person; string designation; }; -PersonIDTF expPerson = {name: "John Doe", age: 20}; +Person expPerson = {name: "John Doe", age: 20}; + // Test functions @@ -48,11 +49,11 @@ function testSimpleTypes() { } function testRecordVarRef() { - PersonIDTF p = getRecord(); + Person p = getRecord(); assert(expPerson, p); - EmployeeIDTF e = getRecord(td = EmployeeIDTF); - assert({name: "Jane Doe", age: 25, designation: "Software Engineer"}, e); + Employee e = getRecord(td = Employee); + assert({name: "Jane Doe", age: 25, designation: "Software Engineer"}, e); } function testVarRefInMapConstraint() { @@ -68,15 +69,15 @@ function testRuntimeCastError() { error err = m1; assert("{ballerina}TypeCastError", err.message()); - assert("incompatible types: 'map' cannot be cast to 'map'", checkpanic err.detail()["message"]); + assert("incompatible types: 'map' cannot be cast to 'map'", checkpanic err.detail()["message"]); } function testTupleTypes() { - [int, PersonIDTF, float] tup1 = getTuple(int, PersonIDTF); - assert(<[int, PersonIDTF, float]>[150, expPerson, 12.34], tup1); + [int, Person, float] tup1 = getTuple(int, Person); + assert(<[int, Person, float]>[150, expPerson, 12.34], tup1); - [int, PersonIDTF, boolean...] tup2 = getTupleWithRestDesc(int, PersonIDTF); - assert(<[int, PersonIDTF, boolean...]>[150, expPerson, true, true], tup2); + [int, Person, boolean...] tup2 = getTupleWithRestDesc(int, Person); + assert(<[int, Person, boolean...]>[150, expPerson, true, true], tup2); tup2[4] = false; assert(5, tup2.length()); } @@ -87,12 +88,11 @@ function testArrayTypes() { } type XmlComment xml:Comment; - type XmlElement xml:Element; function testXml() { xml:Comment x1 = xml ``; - xml x2 = >x1.concat(xml ``); + xml x2 = > x1.concat(xml ``); xml a = getXml(val = x2); assert(x2, a); assert(2, a.length()); @@ -128,14 +128,14 @@ function testXml() { function testCastingForInvalidValues() { var fn = function() { - int x = getInvalidValue(td2 = PersonIDTF); + int x = getInvalidValue(td2 = Person); }; error? y = trap fn(); assert(true, y is error); - error err = y; + error err = y; assert("{ballerina}TypeCastError", err.message()); - assert("incompatible types: 'PersonIDTF' cannot be cast to 'int'", checkpanic err.detail()["message"]); + assert("incompatible types: 'Person' cannot be cast to 'int'", checkpanic err.detail()["message"]); } function testStream() { @@ -144,21 +144,19 @@ function testStream() { stream newSt = getStream(st); string s = ""; - error? err = newSt.forEach(function(string x) { - s += x; - }); + error? err = newSt.forEach(function (string x) { s += x; }); assert("helloworldfromballerina", s); } function testTable() { - table key(name) tab = table [ - {name: "Chiran", age: 33, designation: "SE"}, - {name: "Mohan", age: 37, designation: "SE"}, - {name: "Gima", age: 38, designation: "SE"}, - {name: "Granier", age: 34, designation: "SE"} + table key(name) tab = table [ + { name: "Chiran", age: 33, designation: "SE" }, + { name: "Mohan", age: 37, designation: "SE" }, + { name: "Gima", age: 38, designation: "SE" }, + { name: "Granier", age: 34, designation: "SE" } ]; - table newTab = getTable(tab); + table newTab = getTable(tab); assert(tab, newTab); } @@ -170,12 +168,12 @@ function testFunctionPointers() { } function testTypedesc() { - typedesc tP = getTypedesc(); - assert(PersonIDTF.toString(), tP.toString()); + typedesc tP = getTypedesc(); + assert(Person.toString(), tP.toString()); } function testFuture() { - var fn = function(string name) returns string => "Hello " + name; + var fn = function (string name) returns string => "Hello " + name; future f = start fn("Pubudu"); future fNew = getFuture(f, string); string res = checkpanic wait fNew; @@ -197,7 +195,7 @@ class PersonObj { type IntStream stream; -type PersonTable table; +type PersonTable table; type IntArray int[]; @@ -211,7 +209,7 @@ function testComplexTypes() { int[] ar = echo([20, 30, 40]); assert([20, 30, 40], ar); - PersonObj pObj = new ("John", "Doe"); + PersonObj pObj = new("John", "Doe"); PersonObj nObj = echo(pObj); assertSame(pObj, nObj); @@ -220,19 +218,17 @@ function testComplexTypes() { stream newSt = echo(st); int tot = 0; - error? err = newSt.forEach(function(int x1) { - tot += x1; - }); + error? err = newSt.forEach(function (int x1) { tot+= x1; }); assert(150, tot); - table key(name) tab = table [ - {name: "Chiran", age: 33}, - {name: "Mohan", age: 37}, - {name: "Gima", age: 38}, - {name: "Granier", age: 34} + table key(name) tab = table [ + { name: "Chiran", age: 33}, + { name: "Mohan", age: 37}, + { name: "Gima", age: 38}, + { name: "Granier", age: 34} ]; - table newTab = echo(tab); + table newTab = echo(tab); assert(tab, newTab); } @@ -248,7 +244,7 @@ function testFunctionAssignment() { error err = v; assert("{ballerina}TypeCastError", err.message()); - assert("incompatible types: 'string' cannot be cast to 'int'", checkpanic err.detail()["message"]); + assert("incompatible types: 'string' cannot be cast to 'int'", checkpanic err.detail()["message"]); } function testUnionTypes() { @@ -265,10 +261,10 @@ function testUnionTypes() { assert("hello", d); int[]|map? e = getComplexUnion(); - assert([1, 2], e); + assert( [1, 2], e); map<[int, string][]>|()|[int, string][] f = getComplexUnion(); - assert(>{entry: [[100, "Hello World"]]}, f); + assert(> {entry: [[100, "Hello World"]]}, f); int|boolean? g = getSimpleUnion(1, int); assert(1, g); @@ -283,47 +279,47 @@ function testUnionTypes() { assert("hello", j); int[]|map? k = getComplexUnion(int); - assert([1, 2], k); + assert( [1, 2], k); map<[int, string][]>|()|[int, string][] l = getComplexUnion(td = [int, string]); - assert(>{entry: [[100, "Hello World"]]}, l); + assert(> {entry: [[100, "Hello World"]]}, l); } function testArgCombinations() { int[] a = funcWithMultipleArgs(1, int, ["hello", "world"]); - assert([2, 1], a); + assert( [2, 1], a); string[] b = funcWithMultipleArgs(td = string, arr = ["hello", "world"], i = 3); - assert(["hello", "world", "3"], b); + assert( ["hello", "world", "3"], b); - record {|string[] arr = ["hello", "world", "Ballerina"]; int i = 123; typedesc td;|} rec1 = {td: int}; + record {| string[] arr = ["hello", "world", "Ballerina"]; int i = 123; typedesc td; |} rec1 = {td: int}; int[] c = funcWithMultipleArgs(...rec1); - assert([3, 123], c); + assert( [3, 123], c); - record {|string[] arr = ["hello", "world"];|} rec2 = {}; + record {| string[] arr = ["hello", "world"]; |} rec2 = {}; int[] d = funcWithMultipleArgs(1234, int, ...rec2); - assert([2, 1234], d); + assert( [2, 1234], d); [int, typedesc, string[]] tup1 = [21, string, ["hello"]]; string[] e = funcWithMultipleArgs(...tup1); - assert(["hello", "21"], e); + assert( ["hello", "21"], e); [string[]] tup2 = [["hello"]]; string[] f = funcWithMultipleArgs(34, string, ...tup2); - assert(["hello", "34"], f); + assert( ["hello", "34"], f); int[] g = funcWithMultipleArgs(1); - assert([0, 1], g); + assert( [0, 1], g); string[] h = funcWithMultipleArgs(101, arr = ["hello", "world"]); - assert(["hello", "world", "101"], h); + assert( ["hello", "world", "101"], h); int[] i = funcWithMultipleArgs(arr = ["hello", "world"], i = 202); - assert([2, 202], i); + assert( [2, 202], i); } function testBuiltInRefType() { - stream strm = ([1, 2, 3]).toStream(); + stream strm = ( [1, 2, 3]).toStream(); readonly|handle|stream a = funcReturningUnionWithBuiltInRefType(strm); assertSame(strm, a); @@ -335,65 +331,65 @@ function testBuiltInRefType() { assertSame(strm, d); stream|readonly e = funcReturningUnionWithBuiltInRefType(strm); assert(true, e is handle); - string? str = java:toString(checkpanic e); + string? str = java:toString( checkpanic e); assert("hello world", str); } function testParameterizedTypeInUnionWithNonParameterizedTypes() { - record {|stream x;|} rec = {x: ([1, 2, 3]).toStream()}; - object {}|record {|stream x;|}|int|error a = getValueWithUnionReturnType(rec); - assert(101, checkpanic a); + record {| stream x; |} rec = {x: ( [1, 2, 3]).toStream()}; + object {}|record {| stream x; |}|int|error a = getValueWithUnionReturnType(rec); + assert(101, checkpanic a); PersonObj pObj = new ("John", "Doe"); - object {}|record {|stream x;|}|string[]|error b = getValueWithUnionReturnType(pObj); + object {}|record {| stream x; |}|string[]|error b = getValueWithUnionReturnType(pObj); assertSame(pObj, b); - error|object {}|record {|stream x;|}|boolean c = getValueWithUnionReturnType(true, boolean); - assert(false, checkpanic c); + error|object {}|record {| stream x; |}|boolean c = getValueWithUnionReturnType(true, boolean); + assert(false, checkpanic c); - error|object {}|record {|stream x;|}|boolean d = getValueWithUnionReturnType(td = boolean, val = false); - assert(true, checkpanic d); + error|object {}|record {| stream x; |}|boolean d = getValueWithUnionReturnType(td = boolean, val = false); + assert(true, checkpanic d); } function testUsageWithVarWithUserSpecifiedArg() { - stream strm = ([1, 2, 3]).toStream(); + stream strm = ( [1, 2, 3]).toStream(); var x = funcReturningUnionWithBuiltInRefType(strm, IntStream); assertSame(strm, x); } -function testFunctionWithAnyFunctionParamType() { - var fn = function(function x, int y) { + function testFunctionWithAnyFunctionParamType() { + var fn = function (function x, int y) { }; function (function, int) z = getFunctionWithAnyFunctionParamType(fn); assertSame(fn, z); -} + } function testUsageWithCasts() { - int a = getValue(); + int a = getValue(); assert(150, a); - var b = getValue(); + var b = getValue(); assert(12.34, b); - any c = getValue(); - assert(23.45d, c); + any c = getValue(); + assert(23.45d, c); - string|xml|float d = getValue(); + string|xml|float d = getValue(); assert("Hello World!", d); - anydata e = getValue(); + anydata e = getValue(); assert(true, e); - anydata f = <[int, PersonIDTF, boolean...]>getTupleWithRestDesc(int, PersonIDTF); - assert(<[int, PersonIDTF, boolean...]>[150, expPerson, true, true], f); + anydata f = <[int, Person, boolean...]> getTupleWithRestDesc(int, Person); + assert(<[int, Person, boolean...]>[150, expPerson, true, true], f); - record {|stream x;|} g = {x: ([1, 2, 3]).toStream()}; - var h = x;|}|int>checkpanic getValueWithUnionReturnType(g); - assert(101, h); + record {| stream x; |} g = {x: ( [1, 2, 3]).toStream()}; + var h = x; |}|int> checkpanic getValueWithUnionReturnType(g); + assert(101, h); PersonObj i = new ("John", "Doe"); - any|error j = x;|}|string[]|error>getValueWithUnionReturnType(i); + any|error j = x; |}|string[]|error> getValueWithUnionReturnType(i); assertSame(i, j); } @@ -424,7 +420,7 @@ function getTuple(typedesc td1, typedesc td2, typedesc td1, typedesc td2, typedesc td3 = <>) returns [td1, td2, td3...] = - @java:Method {'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType"} external; + @java:Method { 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType" } external; function getArray(typedesc td = <>) returns td[] = @java:Method { 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", @@ -434,10 +430,10 @@ function getArray(typedesc td = <>) returns td[] = @java:Method { function getXml(typedesc td = <>, xml val = xml ``) returns xml = @java:Method { - 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType" -} external; + 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType" + } external; -function getInvalidValue(typedesc td1 = <>, typedesc td2 = PersonIDTF) returns td1 = +function getInvalidValue(typedesc td1 = <>, typedesc td2 = Person) returns td1 = @java:Method { 'class: "org.ballerinalang.nativeimpl.jvm.tests.VariableReturnType", name: "getInvalidValue", diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/jvm/objects_subtyping.bal b/tests/jballerina-unit-test/src/test/resources/test-src/jvm/objects_subtyping.bal index 7d9ea39b789a..b0aa1255ab05 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/jvm/objects_subtyping.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/jvm/objects_subtyping.bal @@ -161,7 +161,9 @@ public function testObjectAssignabilityBetweenNonClientAndClientObject() { subtyping:ClientObjectWithoutRemoteMethod o2 = new subtyping:ClientObjectWithoutRemoteMethod("ClientObjectWithoutRemoteMethod"); subtyping:NonClientObject obj3 = o2; + subtyping:ClientObjectWithoutRemoteMethod obj4 = obj1; + assertEquality("NonClientObject", obj4.name); assertEquality("ClientObjectWithoutRemoteMethod", obj3.name); } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/object/ObjectEquivalencyProject/object-equivalency.bal b/tests/jballerina-unit-test/src/test/resources/test-src/object/ObjectEquivalencyProject/object-equivalency.bal index db8c5066fc87..0a9988ceb3b9 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/object/ObjectEquivalencyProject/object-equivalency.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/object/ObjectEquivalencyProject/object-equivalency.bal @@ -654,9 +654,13 @@ client class ClientObjectWithoutRemoteMethod { } function testObjectAssignabilityBetweenNonClientAndClientObject() { - ClientObjectWithoutRemoteMethod obj2 = new ("ClientObjectWithoutRemoteMethod"); + NonClientObject obj1 = new("NonClientObject"); + ClientObjectWithoutRemoteMethod obj2 = new("ClientObjectWithoutRemoteMethod"); NonClientObject obj3 = obj2; + ClientObjectWithoutRemoteMethod obj4 = obj1; + + assertEquality("NonClientObject", obj4.name); assertEquality("ClientObjectWithoutRemoteMethod", obj3.name); } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/query/multiple-order-by-clauses.bal b/tests/jballerina-unit-test/src/test/resources/test-src/query/multiple-order-by-clauses.bal index c6ae94051aa2..9fd7422c55fc 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/query/multiple-order-by-clauses.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/query/multiple-order-by-clauses.bal @@ -14,59 +14,59 @@ // specific language governing permissions and limitations // under the License. -type StudentY record {| - readonly int id; - string? fname; - float fee; - decimal impact; - boolean isUndergrad; +type Student record {| + readonly int id; + string? fname; + float fee; + decimal impact; + boolean isUndergrad; |}; -type PersonY record {| +type Person record {| string firstName; string lastName; int age; string address; |}; -type CustomerY record {| +type Customer record {| readonly int id; readonly string name; int noOfItems; |}; -type CustomerProfileY record {| +type CustomerProfile record {| string name; int age; int noOfItems; string address; |}; -type StudentTableY table key(id); +type StudentTable table key(id); function testQueryExprWithMultipleOrderByClauses() returns boolean { boolean testPassed = true; - StudentY s1 = {id: 1, fname: "John", fee: 2000.56, impact: 0.4, isUndergrad: true}; - StudentY s2 = {id: 2, fname: "John", fee: 2000.56, impact: 0.45, isUndergrad: true}; - StudentY s3 = {id: 2, fname: (), fee: 4000.56, impact: 0.4, isUndergrad: true}; - StudentY s4 = {id: 2, fname: "Kate", fee: 2000.56, impact: 0.4, isUndergrad: true}; - StudentY s5 = {id: 3, fname: "John", fee: 2000.56, impact: 0.45, isUndergrad: true}; + Student s1 = {id: 1, fname: "John", fee: 2000.56, impact: 0.4, isUndergrad: true}; + Student s2 = {id: 2, fname: "John", fee: 2000.56, impact: 0.45, isUndergrad: true}; + Student s3 = {id: 2, fname: (), fee: 4000.56, impact: 0.4, isUndergrad: true}; + Student s4 = {id: 2, fname: "Kate", fee: 2000.56, impact: 0.4, isUndergrad: true}; + Student s5 = {id: 3, fname: "John", fee: 2000.56, impact: 0.45, isUndergrad: true}; - StudentY[] studentList = [s1, s2, s3, s4, s5]; + Student[] studentList = [s1, s2, s3, s4, s5]; - StudentY[] opStudentList = + Student[] opStudentList = from var student in studentList - order by student.fname descending, student.impact - order by student.id descending - select student; + order by student.fname descending, student.impact + order by student.id descending + select student; testPassed = testPassed && opStudentList.length() == 5; - testPassed = testPassed && opStudentList[0] == studentList[4]; - testPassed = testPassed && opStudentList[1] == studentList[3]; - testPassed = testPassed && opStudentList[2] == studentList[1]; - testPassed = testPassed && opStudentList[3] == studentList[2]; - testPassed = testPassed && opStudentList[4] == studentList[0]; + testPassed = testPassed && opStudentList[0] == studentList[4]; + testPassed = testPassed && opStudentList[1] == studentList[3]; + testPassed = testPassed && opStudentList[2] == studentList[1]; + testPassed = testPassed && opStudentList[3] == studentList[2]; + testPassed = testPassed && opStudentList[4] == studentList[0]; return testPassed; } @@ -74,32 +74,32 @@ function testQueryExprWithMultipleOrderByClauses() returns boolean { function testQueryExprWithMultipleFromAndMultipleOrderByClauses() returns boolean { boolean testPassed = true; - CustomerY c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerY c2 = {id: 5, name: "James", noOfItems: 5}; - CustomerY c3 = {id: 7, name: "James", noOfItems: 25}; - CustomerY c4 = {id: 0, name: "James", noOfItems: 25}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 5, name: "James", noOfItems: 5}; + Customer c3 = {id: 7, name: "James", noOfItems: 25}; + Customer c4 = {id: 0, name: "James", noOfItems: 25}; - PersonY p1 = {firstName: "Amy", lastName: "Melina", age: 23, address: "New York"}; - PersonY p2 = {firstName: "Frank", lastName: "James", age: 30, address: "California"}; + Person p1 = {firstName: "Amy", lastName: "Melina", age: 23, address: "New York"}; + Person p2 = {firstName: "Frank", lastName: "James", age: 30, address: "California"}; - CustomerY[] customerList = [c1, c2, c3, c4]; - PersonY[] personList = [p1, p2]; + Customer[] customerList = [c1, c2, c3, c4]; + Person[] personList = [p1, p2]; - CustomerY[] opCustomerList = + Customer[] opCustomerList = from var customer in customerList - from var person in personList - let string customerName = "Johns" - where person.lastName == customer.name - order by customer.id descending - order by person.address - select { - id: customer.id, - name: customerName, - noOfItems: customer.noOfItems - }; + from var person in personList + let string customerName = "Johns" + where person.lastName == customer.name + order by customer.id descending + order by person.address + select { + id: customer.id, + name: customerName, + noOfItems: customer.noOfItems + }; testPassed = testPassed && opCustomerList.length() == 4; - CustomerY cus; + Customer cus; cus = opCustomerList[0]; testPassed = testPassed && cus.id == 7 && cus.noOfItems == 25; cus = opCustomerList[1]; @@ -114,32 +114,32 @@ function testQueryExprWithMultipleFromAndMultipleOrderByClauses() returns boolea function testQueryExprWithJoinAndMultipleOrderByClauses() returns boolean { boolean testPassed = true; - CustomerY c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerY c2 = {id: 2, name: "James", noOfItems: 5}; - CustomerY c3 = {id: 3, name: "James", noOfItems: 25}; - CustomerY c4 = {id: 4, name: "James", noOfItems: 25}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c3 = {id: 3, name: "James", noOfItems: 25}; + Customer c4 = {id: 4, name: "James", noOfItems: 25}; - PersonY p1 = {firstName: "Amy", lastName: "Melina", age: 23, address: "New York"}; - PersonY p2 = {firstName: "Frank", lastName: "James", age: 30, address: "California"}; + Person p1 = {firstName: "Amy", lastName: "Melina", age: 23, address: "New York"}; + Person p2 = {firstName: "Frank", lastName: "James", age: 30, address: "California"}; - CustomerY[] customerList = [c1, c2, c3, c4]; - PersonY[] personList = [p1, p2]; + Customer[] customerList = [c1, c2, c3, c4]; + Person[] personList = [p1, p2]; - CustomerProfileY[] customerProfileList = + CustomerProfile[] customerProfileList = from var customer in customerList - join var person in personList + join var person in personList on customer.name equals person.lastName - order by customer.noOfItems descending - order by person.address - select { - name: person.firstName, - age: person.age, - noOfItems: customer.noOfItems, - address: person.address - }; + order by customer.noOfItems descending + order by person.address + select { + name: person.firstName, + age : person.age, + noOfItems: customer.noOfItems, + address: person.address + }; testPassed = testPassed && customerProfileList.length() == 4; - CustomerProfileY cp; + CustomerProfile cp; cp = customerProfileList[0]; testPassed = testPassed && cp.name == "Frank" && cp.age == 30 && cp.noOfItems == 25 && cp.address == "California"; cp = customerProfileList[1]; @@ -154,40 +154,36 @@ function testQueryExprWithJoinAndMultipleOrderByClauses() returns boolean { function testQueryExprWithInnerQueriesAndMultipleOrderByClauses() returns boolean { boolean testPassed = true; - CustomerY c1 = {id: 1, name: "Melina", noOfItems: 62}; - CustomerY c2 = {id: 5, name: "James", noOfItems: 5}; - CustomerY c3 = {id: 9, name: "James", noOfItems: 25}; - CustomerY c4 = {id: 0, name: "James", noOfItems: 25}; - CustomerY c5 = {id: 2, name: "James", noOfItems: 30}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 62}; + Customer c2 = {id: 5, name: "James", noOfItems: 5}; + Customer c3 = {id: 9, name: "James", noOfItems: 25}; + Customer c4 = {id: 0, name: "James", noOfItems: 25}; + Customer c5 = {id: 2, name: "James", noOfItems: 30}; - PersonY p1 = {firstName: "Jennifer", lastName: "Melina", age: 23, address: "California"}; - PersonY p2 = {firstName: "Frank", lastName: "James", age: 30, address: "New York"}; - PersonY p3 = {firstName: "Zeth", lastName: "James", age: 50, address: "Texas"}; + Person p1 = {firstName: "Jennifer", lastName: "Melina", age: 23, address: "California"}; + Person p2 = {firstName: "Frank", lastName: "James", age: 30, address: "New York"}; + Person p3 = {firstName: "Zeth", lastName: "James", age: 50, address: "Texas"}; - CustomerY[] customerList = [c1, c2, c3, c4, c5]; - PersonY[] personList = [p1, p2, p3]; + Customer[] customerList = [c1, c2, c3, c4, c5]; + Person[] personList = [p1, p2, p3]; - CustomerProfileY[] customerProfileList = + CustomerProfile[] customerProfileList = from var customer in (stream from var c in customerList - order by c.id descending - limit 4 - select c) - join var person in (from var p in personList - order by p.firstName descending - select p) + order by c.id descending limit 4 select c) + join var person in (from var p in personList order by p.firstName descending select p) on customer.name equals person.lastName - order by customer.noOfItems descending - order by person.address - limit 4 - select { - name: person.firstName, - age: person.age, - noOfItems: customer.noOfItems, - address: person.address - }; + order by customer.noOfItems descending + order by person.address + limit 4 + select { + name: person.firstName, + age : person.age, + noOfItems: customer.noOfItems, + address: person.address + }; testPassed = testPassed && customerProfileList.length() == 4; - CustomerProfileY cp; + CustomerProfile cp; cp = customerProfileList[0]; testPassed = testPassed && cp.name == "Jennifer" && cp.age == 23 && cp.noOfItems == 62 && cp.address == "California"; @@ -203,40 +199,37 @@ function testQueryExprWithInnerQueriesAndMultipleOrderByClauses() returns boolea function testQueryExprWithMultipleOrderByAndMultipleLimitClauses() returns boolean { boolean testPassed = true; - CustomerY c1 = {id: 1, name: "Melina", noOfItems: 62}; - CustomerY c2 = {id: 5, name: "James", noOfItems: 5}; - CustomerY c3 = {id: 9, name: "James", noOfItems: 25}; - CustomerY c4 = {id: 0, name: "James", noOfItems: 25}; - CustomerY c5 = {id: 2, name: "James", noOfItems: 30}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 62}; + Customer c2 = {id: 5, name: "James", noOfItems: 5}; + Customer c3 = {id: 9, name: "James", noOfItems: 25}; + Customer c4 = {id: 0, name: "James", noOfItems: 25}; + Customer c5 = {id: 2, name: "James", noOfItems: 30}; - PersonY p1 = {firstName: "Jennifer", lastName: "Melina", age: 23, address: "California"}; - PersonY p2 = {firstName: "Frank", lastName: "James", age: 30, address: "New York"}; - PersonY p3 = {firstName: "Zeth", lastName: "James", age: 50, address: "Texas"}; + Person p1 = {firstName: "Jennifer", lastName: "Melina", age: 23, address: "California"}; + Person p2 = {firstName: "Frank", lastName: "James", age: 30, address: "New York"}; + Person p3 = {firstName: "Zeth", lastName: "James", age: 50, address: "Texas"}; - CustomerY[] customerList = [c1, c2, c3, c4, c5]; - PersonY[] personList = [p1, p2, p3]; + Customer[] customerList = [c1, c2, c3, c4, c5]; + Person[] personList = [p1, p2, p3]; - CustomerProfileY[] customerProfileList = + CustomerProfile[] customerProfileList = from var customer in (stream from var c in customerList - order by c.id descending - select c) - join var person in (from var p in personList - order by p.firstName descending - select p) + order by c.id descending select c) + join var person in (from var p in personList order by p.firstName descending select p) on customer.name equals person.lastName - order by customer.noOfItems descending - limit 5 - order by person.address - limit 2 - select { - name: person.firstName, - age: person.age, - noOfItems: customer.noOfItems, - address: person.address - }; + order by customer.noOfItems descending + limit 5 + order by person.address + limit 2 + select { + name: person.firstName, + age : person.age, + noOfItems: customer.noOfItems, + address: person.address + }; testPassed = testPassed && customerProfileList.length() == 2; - CustomerProfileY cp; + CustomerProfile cp; cp = customerProfileList[0]; testPassed = testPassed && cp.name == "Jennifer" && cp.age == 23 && cp.noOfItems == 62 && cp.address == "California"; @@ -247,41 +240,37 @@ function testQueryExprWithMultipleOrderByAndMultipleLimitClauses() returns boole function testQueryActionWithMultipleOrderByClauses() returns boolean { boolean testPassed = true; - CustomerProfileY[] customerProfileList = []; + CustomerProfile[] customerProfileList = []; - CustomerY c1 = {id: 1, name: "Melina", noOfItems: 62}; - CustomerY c2 = {id: 5, name: "James", noOfItems: 5}; - CustomerY c3 = {id: 9, name: "James", noOfItems: 25}; - CustomerY c4 = {id: 0, name: "James", noOfItems: 25}; - CustomerY c5 = {id: 2, name: "James", noOfItems: 30}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 62}; + Customer c2 = {id: 5, name: "James", noOfItems: 5}; + Customer c3 = {id: 9, name: "James", noOfItems: 25}; + Customer c4 = {id: 0, name: "James", noOfItems: 25}; + Customer c5 = {id: 2, name: "James", noOfItems: 30}; - PersonY p1 = {firstName: "Jennifer", lastName: "Melina", age: 23, address: "California"}; - PersonY p2 = {firstName: "Frank", lastName: "James", age: 30, address: "New York"}; - PersonY p3 = {firstName: "Zeth", lastName: "James", age: 50, address: "Texas"}; + Person p1 = {firstName: "Jennifer", lastName: "Melina", age: 23, address: "California"}; + Person p2 = {firstName: "Frank", lastName: "James", age: 30, address: "New York"}; + Person p3 = {firstName: "Zeth", lastName: "James", age: 50, address: "Texas"}; - CustomerY[] customerList = [c1, c2, c3, c4, c5]; - PersonY[] personList = [p1, p2, p3]; + Customer[] customerList = [c1, c2, c3, c4, c5]; + Person[] personList = [p1, p2, p3]; error? op = from var customer in customerList - join var person in personList + join var person in personList on customer.name equals person.lastName - order by customer.noOfItems descending - limit 5 - order by person.address - limit 2 - do { - CustomerProfileY cp = { - name: person.firstName, - age: person.age, - noOfItems: customer.noOfItems, - address: person.address + order by customer.noOfItems descending + limit 5 + order by person.address + limit 2 + do { + CustomerProfile cp = {name: person.firstName, age : person.age, noOfItems: customer.noOfItems, + address: person.address}; + customerProfileList[customerProfileList.length()] = cp; }; - customerProfileList[customerProfileList.length()] = cp; - }; testPassed = testPassed && customerProfileList.length() == 2; - CustomerProfileY cp; + CustomerProfile cp; cp = customerProfileList[0]; testPassed = testPassed && cp.name == "Jennifer" && cp.age == 23 && cp.noOfItems == 62 && cp.address == "California"; @@ -293,27 +282,27 @@ function testQueryActionWithMultipleOrderByClauses() returns boolean { function testQueryExprWithMultipleOrderByClausesReturnTable() returns boolean { boolean testPassed = true; - StudentY s1 = {id: 1, fname: "John", fee: 2000.56, impact: 0.4, isUndergrad: true}; - StudentY s2 = {id: 2, fname: "John", fee: 2000.56, impact: 0.45, isUndergrad: true}; - StudentY s3 = {id: 9, fname: (), fee: 4000.56, impact: 0.4, isUndergrad: true}; - StudentY s4 = {id: 4, fname: "Kate", fee: 2000.56, impact: 0.4, isUndergrad: true}; - StudentY s5 = {id: 10, fname: "John", fee: 2000.56, impact: 0.45, isUndergrad: true}; + Student s1 = {id: 1, fname: "John", fee: 2000.56, impact: 0.4, isUndergrad: true}; + Student s2 = {id: 2, fname: "John", fee: 2000.56, impact: 0.45, isUndergrad: true}; + Student s3 = {id: 9, fname: (), fee: 4000.56, impact: 0.4, isUndergrad: true}; + Student s4 = {id: 4, fname: "Kate", fee: 2000.56, impact: 0.4, isUndergrad: true}; + Student s5 = {id: 10, fname: "John", fee: 2000.56, impact: 0.45, isUndergrad: true}; - StudentY[] studentList = [s1, s2, s3, s4, s5]; + Student[] studentList = [s1, s2, s3, s4, s5]; - StudentTableY|error opStudentTable = + StudentTable|error opStudentTable = table key(id) from var student in studentList - order by student.fname descending, student.impact - order by student.id descending - select student; - - if (opStudentTable is StudentTableY) { - StudentY[] opStudentList = opStudentTable.toArray(); - testPassed = testPassed && opStudentList[0] == studentList[4]; - testPassed = testPassed && opStudentList[1] == studentList[2]; - testPassed = testPassed && opStudentList[2] == studentList[3]; - testPassed = testPassed && opStudentList[3] == studentList[1]; - testPassed = testPassed && opStudentList[4] == studentList[0]; + order by student.fname descending, student.impact + order by student.id descending + select student; + + if (opStudentTable is StudentTable) { + Student[] opStudentList = opStudentTable.toArray(); + testPassed = testPassed && opStudentList[0] == studentList[4]; + testPassed = testPassed && opStudentList[1] == studentList[2]; + testPassed = testPassed && opStudentList[2] == studentList[3]; + testPassed = testPassed && opStudentList[3] == studentList[1]; + testPassed = testPassed && opStudentList[4] == studentList[0]; } return testPassed; } @@ -321,23 +310,23 @@ function testQueryExprWithMultipleOrderByClausesReturnTable() returns boolean { function testQueryExprWithMultipleOrderByClausesReturnStream() returns boolean { boolean testPassed = true; - StudentY s1 = {id: 1, fname: "John", fee: 2000.56, impact: 0.4, isUndergrad: true}; - StudentY s2 = {id: 2, fname: "John", fee: 2000.56, impact: 0.45, isUndergrad: true}; - StudentY s3 = {id: 9, fname: (), fee: 4000.56, impact: 0.4, isUndergrad: true}; - StudentY s4 = {id: 4, fname: "Kate", fee: 2000.56, impact: 0.4, isUndergrad: true}; - StudentY s5 = {id: 10, fname: "John", fee: 2000.56, impact: 0.45, isUndergrad: true}; + Student s1 = {id: 1, fname: "John", fee: 2000.56, impact: 0.4, isUndergrad: true}; + Student s2 = {id: 2, fname: "John", fee: 2000.56, impact: 0.45, isUndergrad: true}; + Student s3 = {id: 9, fname: (), fee: 4000.56, impact: 0.4, isUndergrad: true}; + Student s4 = {id: 4, fname: "Kate", fee: 2000.56, impact: 0.4, isUndergrad: true}; + Student s5 = {id: 10, fname: "John", fee: 2000.56, impact: 0.45, isUndergrad: true}; - StudentY[] studentList = [s1, s2, s3, s4, s5]; + Student[] studentList = [s1, s2, s3, s4, s5]; - stream opStudentStream = + stream opStudentStream = stream from var student in studentList - order by student.fname descending, student.impact - order by student.id descending - select student; + order by student.fname descending, student.impact + order by student.id descending + select student; - StudentY[] opStudentList = []; - record {|StudentY value;|}|error? v = opStudentStream.next(); - while (v is record {|StudentY value;|}) { + Student[] opStudentList = []; + record {| Student value; |}|error? v = opStudentStream.next(); + while (v is record {| Student value; |}) { opStudentList.push(v.value); v = opStudentStream.next(); } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/query/order-by-clause.bal b/tests/jballerina-unit-test/src/test/resources/test-src/query/order-by-clause.bal index 8bda7094c615..f1edb6added6 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/query/order-by-clause.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/query/order-by-clause.bal @@ -22,13 +22,13 @@ type Student record {| boolean isUndergrad; |}; -type PersonPos record {| +type Person record {| string firstName; string lastName; int age; |}; -type CustomerPos record {| +type Customer record {| readonly int id; readonly string name; int noOfItems; @@ -57,25 +57,25 @@ type PaymentInfo record {| string modeOfPayment; |}; -type CustomerTable table key(id, name); +type CustomerTable table key(id, name); type CustomerValue record {| - CustomerPos value; + Customer value; |}; type PersonValue record {| - PersonPos value; + Person value; |}; -function getCustomer(record {|CustomerPos value;|}? returnedVal) returns CustomerPos? { +function getCustomer(record {| Customer value; |}? returnedVal) returns Customer? { if (returnedVal is CustomerValue) { - return returnedVal.value; + return returnedVal.value; } else { - return (); + return (); } } -function getPersonValue((record {|PersonPos value;|}|error?)|(record {|PersonPos value;|}?) returnedVal) +function getPersonValue((record {| Person value; |}|error?)|(record {| Person value; |}?) returnedVal) returns PersonValue? { var result = returnedVal; if (result is PersonValue) { @@ -96,13 +96,13 @@ function testQueryExprWithOrderByClause() returns boolean { Student[] studentList = [s1, s2, s3, s4]; Student[] opStudentList = from var student in studentList - order by student.fname descending, student.impact - select student; + order by student.fname descending, student.impact + select student; - testPassed = testPassed && opStudentList[0] == studentList[3]; - testPassed = testPassed && opStudentList[1] == studentList[0]; - testPassed = testPassed && opStudentList[2] == studentList[1]; - testPassed = testPassed && opStudentList[3] == studentList[2]; + testPassed = testPassed && opStudentList[0] == studentList[3]; + testPassed = testPassed && opStudentList[1] == studentList[0]; + testPassed = testPassed && opStudentList[2] == studentList[1]; + testPassed = testPassed && opStudentList[3] == studentList[2]; return testPassed; } @@ -118,71 +118,71 @@ function testQueryExprWithOrderByClause2() returns boolean { Student[] studentList = [s1, s2, s3, s4]; Student[] opStudentList = from var student in studentList - order by student.isUndergrad ascending, student.fee - select student; + order by student.isUndergrad ascending, student.fee + select student; - testPassed = testPassed && opStudentList[0] == studentList[1]; - testPassed = testPassed && opStudentList[1] == studentList[2]; - testPassed = testPassed && opStudentList[2] == studentList[0]; - testPassed = testPassed && opStudentList[3] == studentList[3]; + testPassed = testPassed && opStudentList[0] == studentList[1]; + testPassed = testPassed && opStudentList[1] == studentList[2]; + testPassed = testPassed && opStudentList[2] == studentList[0]; + testPassed = testPassed && opStudentList[3] == studentList[3]; return testPassed; } -function testQueryExprWithOrderByClause3() returns CustomerPos[] { - CustomerPos c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerPos c2 = {id: 5, name: "James", noOfItems: 5}; - CustomerPos c3 = {id: 7, name: "James", noOfItems: 25}; - CustomerPos c4 = {id: 0, name: "James", noOfItems: 25}; - - PersonPos p1 = {firstName: "Amy", lastName: "Melina", age: 23}; - PersonPos p2 = {firstName: "Frank", lastName: "James", age: 30}; - - CustomerPos[] customerList = [c1, c2, c3, c4]; - PersonPos[] personList = [p1, p2]; - - CustomerPos[] opCustomerList = from var customer in customerList - from var person in personList - let string customerName = "Johns" - where person.lastName == "James" - order by customer.id descending - select { - id: customer.id, - name: customerName, - noOfItems: customer.noOfItems - }; - - return opCustomerList; +function testQueryExprWithOrderByClause3() returns Customer[] { + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 5, name: "James", noOfItems: 5}; + Customer c3 = {id: 7, name: "James", noOfItems: 25}; + Customer c4 = {id: 0, name: "James", noOfItems: 25}; + + Person p1 = {firstName: "Amy", lastName: "Melina", age: 23}; + Person p2 = {firstName: "Frank", lastName: "James", age: 30}; + + Customer[] customerList = [c1, c2, c3, c4]; + Person[] personList = [p1, p2]; + + Customer[] opCustomerList = from var customer in customerList + from var person in personList + let string customerName = "Johns" + where person.lastName == "James" + order by customer.id descending + select { + id: customer.id, + name: customerName, + noOfItems: customer.noOfItems + }; + + return opCustomerList; } function testQueryExprWithOrderByClauseReturnTable() returns boolean { boolean testPassed = true; - CustomerPos c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerPos c2 = {id: 2, name: "James", noOfItems: 5}; - CustomerPos c3 = {id: 3, name: "James", noOfItems: 25}; - CustomerPos c4 = {id: 4, name: "James", noOfItems: 25}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c3 = {id: 3, name: "James", noOfItems: 25}; + Customer c4 = {id: 4, name: "James", noOfItems: 25}; - PersonPos p1 = {firstName: "Amy", lastName: "Melina", age: 23}; - PersonPos p2 = {firstName: "Frank", lastName: "James", age: 30}; + Person p1 = {firstName: "Amy", lastName: "Melina", age: 23}; + Person p2 = {firstName: "Frank", lastName: "James", age: 30}; - CustomerPos[] customerList = [c1, c2, c3, c4]; - PersonPos[] personList = [p1, p2]; + Customer[] customerList = [c1, c2, c3, c4]; + Person[] personList = [p1, p2]; CustomerTable|error customerTable = table key(id, name) from var customer in customerList - from var person in personList - where person.firstName == "Frank" - order by customer.noOfItems descending, customer.id - limit 3 - select { - id: customer.id, - name: customer.name, - noOfItems: customer.noOfItems - }; + from var person in personList + where person.firstName == "Frank" + order by customer.noOfItems descending, customer.id + limit 3 + select { + id: customer.id, + name: customer.name, + noOfItems: customer.noOfItems + }; if (customerTable is CustomerTable) { var itr = customerTable.iterator(); - CustomerPos? customer = getCustomer(itr.next()); + Customer? customer = getCustomer(itr.next()); testPassed = testPassed && customer == customerList[2]; customer = getCustomer(itr.next()); testPassed = testPassed && customer == customerList[3]; @@ -198,19 +198,19 @@ function testQueryExprWithOrderByClauseReturnTable() returns boolean { function testQueryExprWithOrderByClauseReturnStream() returns boolean { boolean testPassed = true; - PersonPos p1 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonPos p2 = {firstName: "John", lastName: "David", age: 33}; - PersonPos p3 = {firstName: "John", lastName: "Fonseka", age: 28}; - PersonPos p4 = {firstName: "John", lastName: "Fonseka", age: 30}; - PersonPos p5 = {firstName: "John", lastName: "Fonseka", age: 20}; + Person p1 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p2 = {firstName: "John", lastName: "David", age: 33}; + Person p3 = {firstName: "John", lastName: "Fonseka", age: 28}; + Person p4 = {firstName: "John", lastName: "Fonseka", age: 30}; + Person p5 = {firstName: "John", lastName: "Fonseka", age: 20}; - CustomerPos c1 = {id: 1, name: "John", noOfItems: 25}; - CustomerPos c2 = {id: 2, name: "Frank", noOfItems: 20}; + Customer c1 = {id: 1, name: "John", noOfItems: 25}; + Customer c2 = {id: 2, name: "Frank", noOfItems: 20}; - PersonPos[] personList = [p1, p2, p3, p4, p5]; - CustomerPos[] customerList = [c1, c2]; + Person[] personList = [p1, p2, p3, p4, p5]; + Customer[] customerList = [c1, c2]; - stream outputPersonStream = stream from var person in personList.toStream() + stream outputPersonStream = stream from var person in personList.toStream() from var customer in customerList let string newLastName = "Turin" let string newFirstName = "Johnas" @@ -223,7 +223,7 @@ function testQueryExprWithOrderByClauseReturnStream() returns boolean { age: person.age }; - record {|PersonPos value;|}? person = getPersonValue(outputPersonStream.next()); + record {| Person value; |}? person = getPersonValue(outputPersonStream.next()); testPassed = testPassed && person?.value?.firstName == "Johnas" && person?.value?.lastName == "Turin" && person?.value?.age == 30; @@ -246,26 +246,26 @@ function testQueryExprWithOrderByClauseReturnStream() returns boolean { } function testQueryExprWithOrderByClauseAndJoin() returns CustomerProfile[] { - CustomerPos c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerPos c2 = {id: 2, name: "James", noOfItems: 5}; - CustomerPos c3 = {id: 3, name: "James", noOfItems: 25}; - CustomerPos c4 = {id: 4, name: "James", noOfItems: 25}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c3 = {id: 3, name: "James", noOfItems: 25}; + Customer c4 = {id: 4, name: "James", noOfItems: 25}; - PersonPos p1 = {firstName: "Amy", lastName: "Melina", age: 23}; - PersonPos p2 = {firstName: "Frank", lastName: "James", age: 30}; + Person p1 = {firstName: "Amy", lastName: "Melina", age: 23}; + Person p2 = {firstName: "Frank", lastName: "James", age: 30}; - CustomerPos[] customerList = [c1, c2, c3, c4]; - PersonPos[] personList = [p1, p2]; + Customer[] customerList = [c1, c2, c3, c4]; + Person[] personList = [p1, p2]; CustomerProfile[] customerProfileList = from var customer in customerList - join var person in personList - on customer.name equals person.lastName - order by customer.noOfItems - select { - name: person.firstName, - age: person.age, - noOfItems: customer.noOfItems - }; + join var person in personList + on customer.name equals person.lastName + order by customer.noOfItems + select { + name: person.firstName, + age : person.age, + noOfItems: customer.noOfItems + }; return customerProfileList; } @@ -273,30 +273,14 @@ function testQueryExprWithOrderByClauseAndJoin() returns CustomerProfile[] { function testQueryExprWithOrderByClauseHavingUserDefinedOrderKeyFunction() returns boolean { boolean testPassed = true; - Employee e1 = { - name: "Frank", - address: {unitNo: 111, street: "Main Street"}, - tokens: {one: 1, two: 2, three: 3}, - noOfShifts: [1, 2, 3] - }; - Employee e2 = { - name: "James", - address: {unitNo: 222, street: "Main Street"}, - tokens: {one: 1, two: 2, three: 3}, - noOfShifts: [1, 2, 3] - }; - Employee e3 = { - name: "James", - address: {unitNo: 222, street: "Cross Street"}, - tokens: {one: 1, two: 2, three: 3}, - noOfShifts: [1, 2, 3] - }; - Employee e4 = { - name: "Frank", - address: {unitNo: 111, street: "Cross Street"}, - tokens: {one: 1, two: 2, three: 3}, - noOfShifts: [1, 2, 3] - }; + Employee e1 = {name: "Frank", address: {unitNo: 111, street: "Main Street"}, tokens: {one:1, two:2, three:3}, + noOfShifts: [1, 2, 3]}; + Employee e2 = {name: "James", address: {unitNo: 222, street: "Main Street"}, tokens: {one:1, two:2, three:3}, + noOfShifts: [1, 2, 3]}; + Employee e3 = {name: "James", address: {unitNo: 222, street: "Cross Street"}, tokens: {one:1, two:2, three:3}, + noOfShifts: [1, 2, 3]}; + Employee e4 = {name: "Frank", address: {unitNo: 111, street: "Cross Street"}, tokens: {one:1, two:2, three:3}, + noOfShifts: [1, 2, 3]}; Employee[] empList = [e1, e2, e3, e4]; @@ -304,10 +288,10 @@ function testQueryExprWithOrderByClauseHavingUserDefinedOrderKeyFunction() retur order by emp.address.unitNo descending, emp.address.street.toLowerAscii() select emp; - testPassed = testPassed && opEmpList[0] == empList[2]; - testPassed = testPassed && opEmpList[1] == empList[1]; - testPassed = testPassed && opEmpList[2] == empList[3]; - testPassed = testPassed && opEmpList[3] == empList[0]; + testPassed = testPassed && opEmpList[0] == empList[2]; + testPassed = testPassed && opEmpList[1] == empList[1]; + testPassed = testPassed && opEmpList[2] == empList[3]; + testPassed = testPassed && opEmpList[3] == empList[0]; return testPassed; } @@ -315,36 +299,16 @@ function testQueryExprWithOrderByClauseHavingUserDefinedOrderKeyFunction() retur function testQueryExprWithOrderByClauseHavingUserDefinedOrderKeyFunction2() returns boolean { boolean testPassed = true; - Employee e1 = { - name: "Frank", - address: {unitNo: 111, street: "Main Street"}, - tokens: {one: 1, two: 2, three: 3}, - noOfShifts: [1, 2, 3] - }; - Employee e2 = { - name: "James", - address: {unitNo: 222, street: "Main Street"}, - tokens: {one: 11, two: 2, three: 3}, - noOfShifts: [1, 2, 3] - }; - Employee e3 = { - name: "James", - address: {unitNo: 222, street: "Cross Street"}, - tokens: {one: 111, two: 2, three: 3}, - noOfShifts: [1, 2, 3] - }; - Employee e4 = { - name: "Frank", - address: {unitNo: 111, street: "Cross Street"}, - tokens: {one: 1111, two: 2, three: 3}, - noOfShifts: [1, 2, 3] - }; - Employee e5 = { - name: "Frank", - address: {unitNo: 111, street: "Cross Street"}, - tokens: {one: 1111, two: 2, three: 3}, - noOfShifts: [3, 2, 3] - }; + Employee e1 = {name: "Frank", address: {unitNo: 111, street: "Main Street"}, tokens: {one:1, two:2, three:3}, + noOfShifts: [1, 2, 3]}; + Employee e2 = {name: "James", address: {unitNo: 222, street: "Main Street"}, tokens: {one:11, two:2, three:3}, + noOfShifts: [1, 2, 3]}; + Employee e3 = {name: "James", address: {unitNo: 222, street: "Cross Street"}, tokens: {one:111, two:2, three:3}, + noOfShifts: [1, 2, 3]}; + Employee e4 = {name: "Frank", address: {unitNo: 111, street: "Cross Street"}, tokens: {one:1111, two:2, three:3}, + noOfShifts: [1, 2, 3]}; + Employee e5 = {name: "Frank", address: {unitNo: 111, street: "Cross Street"}, tokens: {one:1111, two:2, three:3}, + noOfShifts: [3, 2, 3]}; Employee[] empList = [e1, e2, e3, e4, e5]; @@ -352,36 +316,36 @@ function testQueryExprWithOrderByClauseHavingUserDefinedOrderKeyFunction2() retu order by emp.name, emp.tokens["one"] descending, emp.noOfShifts[0] descending select emp; - testPassed = testPassed && opEmpList[0] == empList[4]; - testPassed = testPassed && opEmpList[1] == empList[3]; - testPassed = testPassed && opEmpList[2] == empList[0]; - testPassed = testPassed && opEmpList[3] == empList[2]; - testPassed = testPassed && opEmpList[4] == empList[1]; + testPassed = testPassed && opEmpList[0] == empList[4]; + testPassed = testPassed && opEmpList[1] == empList[3]; + testPassed = testPassed && opEmpList[2] == empList[0]; + testPassed = testPassed && opEmpList[3] == empList[2]; + testPassed = testPassed && opEmpList[4] == empList[1]; return testPassed; } function testQueryExprWithOrderByClauseHavingUserDefinedOrderKeyFunction3() returns CustomerProfile[] { - CustomerPos c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerPos c2 = {id: 2, name: "James", noOfItems: 5}; - CustomerPos c3 = {id: 3, name: "James", noOfItems: 25}; - CustomerPos c4 = {id: 4, name: "James", noOfItems: 25}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c3 = {id: 3, name: "James", noOfItems: 25}; + Customer c4 = {id: 4, name: "James", noOfItems: 25}; - PersonPos p1 = {firstName: "Amy", lastName: "Melina", age: 23}; - PersonPos p2 = {firstName: "Frank", lastName: "James", age: 30}; + Person p1 = {firstName: "Amy", lastName: "Melina", age: 23}; + Person p2 = {firstName: "Frank", lastName: "James", age: 30}; - CustomerPos[] customerList = [c1, c2, c3, c4]; - PersonPos[] personList = [p1, p2]; + Customer[] customerList = [c1, c2, c3, c4]; + Person[] personList = [p1, p2]; CustomerProfile[] customerProfileList = from var customer in customerList - join var person in personList - on customer.name equals person.lastName - order by incrementCount(0), customer.noOfItems descending - select { - name: person.firstName, - age: person.age, - noOfItems: customer.noOfItems - }; + join var person in personList + on customer.name equals person.lastName + order by incrementCount(0), customer.noOfItems descending + select { + name: person.firstName, + age : person.age, + noOfItems: customer.noOfItems + }; return customerProfileList; } @@ -389,56 +353,20 @@ function testQueryExprWithOrderByClauseHavingUserDefinedOrderKeyFunction3() retu function testQueryExprWithOrderByClauseHavingNaNNilValues() returns boolean { boolean testPassed = true; - Employee e1 = { - name: "Frank", - address: {unitNo: 111, street: "Main Street"}, - tokens: {one: 1, two: 2, three: 3}, - noOfShifts: [1, 2, 3] - }; - Employee e2 = { - name: "James", - address: {unitNo: 222, street: "Main Street"}, - tokens: {one: 11, two: (), three: 3}, - noOfShifts: [1, 2, 3] - }; - Employee e3 = { - name: "James", - address: {unitNo: 222, street: "Cross Street"}, - tokens: { - one: 11, - two: (0.0 / 0.0), - three: 3 - }, - noOfShifts: [1, 2, 3] - }; - Employee e4 = { - name: "Frank", - address: {unitNo: 111, street: "Cross Street"}, - tokens: {one: 11, two: 4, three: 3}, - noOfShifts: [1, 2, 3] - }; - Employee e5 = { - name: "Frank", - address: {unitNo: 111, street: "Cross Street"}, - tokens: {one: 11, two: 4, three: ()}, - noOfShifts: [1, 2, 3] - }; - Employee e6 = { - name: "Frank", - address: {unitNo: 111, street: "Cross Street"}, - tokens: { - one: 11, - two: 4, - three: (0.0 / 0.0) - }, - noOfShifts: [1, 2, 3] - }; - Employee e7 = { - name: "Frank", - address: {unitNo: 111, street: "Cross Street"}, - tokens: {one: 11, two: 4, three: 55}, - noOfShifts: [1, 2, 3] - }; + Employee e1 = {name: "Frank", address: {unitNo: 111, street: "Main Street"}, tokens: {one:1, two:2, three:3}, + noOfShifts: [1, 2, 3]}; + Employee e2 = {name: "James", address: {unitNo: 222, street: "Main Street"}, tokens: {one:11, two:(), three:3}, + noOfShifts: [1, 2, 3]}; + Employee e3 = {name: "James", address: {unitNo: 222, street: "Cross Street"}, tokens: {one:11, two:(0.0/0.0), + three:3}, noOfShifts: [1, 2, 3]}; + Employee e4 = {name: "Frank", address: {unitNo: 111, street: "Cross Street"}, tokens: {one:11, two:4, three:3}, + noOfShifts: [1, 2, 3]}; + Employee e5 = {name: "Frank", address: {unitNo: 111, street: "Cross Street"}, tokens: {one:11, two:4, three:()}, + noOfShifts: [1, 2, 3]}; + Employee e6 = {name: "Frank", address: {unitNo: 111, street: "Cross Street"}, tokens: {one:11, two:4, + three:(0.0/0.0)}, noOfShifts: [1, 2, 3]}; + Employee e7 = {name: "Frank", address: {unitNo: 111, street: "Cross Street"}, tokens: {one:11, two:4, three:55}, + noOfShifts: [1, 2, 3]}; Employee[] empList = [e1, e2, e3, e4, e5, e6, e7]; @@ -446,30 +374,30 @@ function testQueryExprWithOrderByClauseHavingNaNNilValues() returns boolean { order by emp.tokens["two"] descending, emp.tokens["three"] ascending select emp; - testPassed = testPassed && opEmpList[0] == empList[3]; - testPassed = testPassed && opEmpList[1] == empList[6]; - testPassed = testPassed && opEmpList[2] == empList[5]; - testPassed = testPassed && opEmpList[3] == empList[4]; - testPassed = testPassed && opEmpList[4] == empList[0]; - testPassed = testPassed && opEmpList[5] == empList[2]; - testPassed = testPassed && opEmpList[6] == empList[1]; + testPassed = testPassed && opEmpList[0] == empList[3]; + testPassed = testPassed && opEmpList[1] == empList[6]; + testPassed = testPassed && opEmpList[2] == empList[5]; + testPassed = testPassed && opEmpList[3] == empList[4]; + testPassed = testPassed && opEmpList[4] == empList[0]; + testPassed = testPassed && opEmpList[5] == empList[2]; + testPassed = testPassed && opEmpList[6] == empList[1]; return testPassed; } function testQueryExprWithOrderByClauseReturnString() returns string { - PersonPos p1 = {firstName: "Amy", lastName: "Melina", age: 34}; - PersonPos p2 = {firstName: "Frank", lastName: "James", age: 30}; - PersonPos p3 = {firstName: "Melina", lastName: "Kodel", age: 72}; - PersonPos p4 = {firstName: "Terrence", lastName: "Lewis", age: 19}; - PersonPos p5 = {firstName: "Meghan", lastName: "Markle", age: 55}; + Person p1 = {firstName: "Amy", lastName: "Melina", age: 34}; + Person p2 = {firstName: "Frank", lastName: "James", age: 30}; + Person p3 = {firstName: "Melina", lastName: "Kodel", age: 72}; + Person p4 = {firstName: "Terrence", lastName: "Lewis", age: 19}; + Person p5 = {firstName: "Meghan", lastName: "Markle", age: 55}; - PersonPos[] personList = [p1, p2, p3, p4, p5]; + Person[] personList = [p1, p2, p3, p4, p5]; string outputNameString = from var person in personList - order by person.age descending - limit 3 - select person.firstName + " " + person.lastName + ","; + order by person.age descending + limit 3 + select person.firstName+" "+person.lastName+","; return outputNameString; } @@ -491,58 +419,53 @@ function testQueryExprWithOrderByClauseReturnXML() returns xml { `; xml authors = from var book in bookStore// - order by book.toString() - limit 2 - select book; + order by book.toString() + limit 2 + select book; - return authors; + return authors; } function testQueryExprWithOrderByClauseAndInnerQueries() returns CustomerProfile[] { - CustomerPos c1 = {id: 1, name: "Melina", noOfItems: 62}; - CustomerPos c2 = {id: 5, name: "James", noOfItems: 5}; - CustomerPos c3 = {id: 9, name: "James", noOfItems: 25}; - CustomerPos c4 = {id: 0, name: "James", noOfItems: 25}; - CustomerPos c5 = {id: 2, name: "James", noOfItems: 30}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 62}; + Customer c2 = {id: 5, name: "James", noOfItems: 5}; + Customer c3 = {id: 9, name: "James", noOfItems: 25}; + Customer c4 = {id: 0, name: "James", noOfItems: 25}; + Customer c5 = {id: 2, name: "James", noOfItems: 30}; - PersonPos p1 = {firstName: "Jennifer", lastName: "Melina", age: 23}; - PersonPos p2 = {firstName: "Frank", lastName: "James", age: 30}; - PersonPos p3 = {firstName: "Zeth", lastName: "James", age: 50}; + Person p1 = {firstName: "Jennifer", lastName: "Melina", age: 23}; + Person p2 = {firstName: "Frank", lastName: "James", age: 30}; + Person p3 = {firstName: "Zeth", lastName: "James", age: 50}; - CustomerPos[] customerList = [c1, c2, c3, c4, c5]; - PersonPos[] personList = [p1, p2, p3]; + Customer[] customerList = [c1, c2, c3, c4, c5]; + Person[] personList = [p1, p2, p3]; CustomerProfile[] customerProfileList = from var customer in (stream from var c in customerList - order by c.id descending - limit 4 - select c) - join var person in (from var p in personList - order by p.firstName descending - limit 2 - select p) - on customer.name equals person.lastName - order by incrementCount(0), customer.noOfItems descending - limit 3 - select { - name: person.firstName, - age: person.age, - noOfItems: customer.noOfItems - }; + order by c.id descending limit 4 select c) + join var person in (from var p in personList order by p.firstName descending limit 2 select p) + on customer.name equals person.lastName + order by incrementCount(0), customer.noOfItems descending + limit 3 + select { + name: person.firstName, + age : person.age, + noOfItems: customer.noOfItems + }; return customerProfileList; } function testQueryExprWithOrderByClauseAndInnerQueries2() returns CustomerProfile[] { - CustomerPos c1 = {id: 1, name: "Melina", noOfItems: 62}; - CustomerPos c2 = {id: 5, name: "James", noOfItems: 5}; - CustomerPos c3 = {id: 9, name: "James", noOfItems: 25}; - CustomerPos c4 = {id: 0, name: "James", noOfItems: 25}; - CustomerPos c5 = {id: 2, name: "James", noOfItems: 30}; - CustomerPos c6 = {id: 3, name: "Melina", noOfItems: 20}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 62}; + Customer c2 = {id: 5, name: "James", noOfItems: 5}; + Customer c3 = {id: 9, name: "James", noOfItems: 25}; + Customer c4 = {id: 0, name: "James", noOfItems: 25}; + Customer c5 = {id: 2, name: "James", noOfItems: 30}; + Customer c6 = {id: 3, name: "Melina", noOfItems: 20}; - PersonPos p1 = {firstName: "Jennifer", lastName: "Melina", age: 23}; - PersonPos p2 = {firstName: "Frank", lastName: "James", age: 30}; - PersonPos p3 = {firstName: "Zeth", lastName: "James", age: 50}; + Person p1 = {firstName: "Jennifer", lastName: "Melina", age: 23}; + Person p2 = {firstName: "Frank", lastName: "James", age: 30}; + Person p3 = {firstName: "Zeth", lastName: "James", age: 50}; PaymentInfo i1 = {custId: 1, modeOfPayment: "cash"}; PaymentInfo i2 = {custId: 9, modeOfPayment: "debit card"}; @@ -553,8 +476,8 @@ function testQueryExprWithOrderByClauseAndInnerQueries2() returns CustomerProfil PaymentInfo i7 = {custId: 2, modeOfPayment: "cash"}; PaymentInfo i8 = {custId: 3, modeOfPayment: "cash"}; - CustomerPos[] customerList = [c1, c2, c3, c4, c5, c6]; - PersonPos[] personList = [p1, p2, p3]; + Customer[] customerList = [c1, c2, c3, c4, c5, c6]; + Person[] personList = [p1, p2, p3]; PaymentInfo[] paymentList = [i1, i2, i3, i4, i5, i6, i7, i8]; CustomerProfile[] customerProfileList = from var customer in (stream from var c in customerList diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/query/query-expr-with-query-construct-type.bal b/tests/jballerina-unit-test/src/test/resources/test-src/query/query-expr-with-query-construct-type.bal index 0145356cd7ca..3cf3bc40fafe 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/query/query-expr-with-query-construct-type.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/query/query-expr-with-query-construct-type.bal @@ -14,23 +14,23 @@ // specific language governing permissions and limitations // under the License. -type PersonX record {| +type Person record {| string firstName; string lastName; int age; |}; -type EmployeeX record {| +type Employee record {| string firstName; string lastName; string dept; |}; -type DepartmentX record { +type Department record { string dept; }; -type EmpProfileX record {| +type EmpProfile record {| string firstName; string lastName; int age; @@ -38,67 +38,67 @@ type EmpProfileX record {| string status; |}; -type PersonValueX record {| - PersonX value; +type PersonValue record {| + Person value; |}; -type EmployeeValueX record {| - EmployeeX value; +type EmployeeValue record {| + Employee value; |}; -type EmpProfileValueX record {| - EmpProfileX value; +type EmpProfileValue record {| + EmpProfile value; |}; -type CustomerX record {| +type Customer record {| readonly int id; readonly string name; int noOfItems; |}; -type CustomerTableX table key(id, name); +type CustomerTable table key(id, name); -type CustomerKeyLessTableX table; +type CustomerKeyLessTable table; -type CustomerValueX record {| - CustomerX value; +type CustomerValue record {| + Customer value; |}; -function getPersonValue((record {|PersonX value;|}|error?)|(record {|PersonX value;|}?) returnedVal) -returns PersonValueX? { +function getPersonValue((record {| Person value; |}|error?)|(record {| Person value; |}?) returnedVal) +returns PersonValue? { var result = returnedVal; - if (result is PersonValueX) { + if (result is PersonValue) { return result; } else { return (); } } -function getEmployeeValue((record {|EmployeeX value;|}|error?)|(record {|EmployeeX value;|}?) returnedVal) -returns EmployeeValueX? { +function getEmployeeValue((record {| Employee value; |}|error?)|(record {| Employee value; |}?) returnedVal) +returns EmployeeValue? { var result = returnedVal; - if (result is EmployeeValueX) { + if (result is EmployeeValue) { return result; } else { return (); } } -function getEmpProfileValue((record {|EmpProfileX value;|}|error?)|(record {|EmpProfileX value;|}?) returnedVal) -returns EmpProfileValueX? { +function getEmpProfileValue((record {| EmpProfile value; |}|error?)|(record {| EmpProfile value; |}?) returnedVal) +returns EmpProfileValue? { var result = returnedVal; - if (result is EmpProfileValueX) { + if (result is EmpProfileValue) { return result; } else { return (); } } -function getCustomer(record {|CustomerX value;|}? returnedVal) returns CustomerX? { - if (returnedVal is CustomerValueX) { - return returnedVal.value; +function getCustomer(record {| Customer value; |}? returnedVal) returns Customer? { + if (returnedVal is CustomerValue) { + return returnedVal.value; } else { - return (); + return (); } } @@ -107,13 +107,13 @@ function getCustomer(record {|CustomerX value;|}? returnedVal) returns CustomerX function testSimpleQueryReturnStream() returns boolean { boolean testPassed = true; - PersonX p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonX p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonX p3 = {firstName: "John", lastName: "David", age: 33}; + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p3 = {firstName: "John", lastName: "David", age: 33}; - PersonX[] personList = [p1, p2, p3]; + Person[] personList = [p1, p2, p3]; - stream outputPersonStream = stream from var person in personList + stream outputPersonStream = stream from var person in personList where person.firstName == "John" let int newAge = 34 select { @@ -122,7 +122,7 @@ function testSimpleQueryReturnStream() returns boolean { age: newAge }; - record {|PersonX value;|}? person = getPersonValue(outputPersonStream.next()); + record {| Person value; |}? person = getPersonValue(outputPersonStream.next()); testPassed = testPassed && person?.value?.firstName == "John" && person?.value?.lastName == "David" && person?.value?.age == 34; @@ -135,11 +135,11 @@ function testSimpleQueryReturnStream() returns boolean { function testSimpleQueryReturnStream2() { boolean testPassed = true; - PersonX p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonX p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonX p3 = {firstName: "John", lastName: "David", age: 33}; + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p3 = {firstName: "John", lastName: "David", age: 33}; - PersonX[] personList = [p1, p2, p3]; + Person[] personList = [p1, p2, p3]; var outputPersonStream = stream from var person in personList where person.firstName == "John" @@ -150,10 +150,10 @@ function testSimpleQueryReturnStream2() { age: newAge }; - assertTrue(outputPersonStream is stream); - stream _ = outputPersonStream; + assertTrue(outputPersonStream is stream); + stream _ = outputPersonStream; - record {|PersonX value;|}? person = getPersonValue(outputPersonStream.next()); + record {| Person value; |}? person = getPersonValue(outputPersonStream.next()); testPassed = testPassed && person?.value?.firstName == "John" && person?.value?.lastName == "David" && person?.value?.age == 34; @@ -163,39 +163,37 @@ function testSimpleQueryReturnStream2() { assertTrue(testPassed); } -type ValueRecordX record {| +type ValueRecord record {| string value; |}; -type TestStreamX stream; +type TestStream stream; -class TestGeneratorX { - public isolated function next() returns ValueRecordX|error? { +class TestGenerator { + public isolated function next() returns ValueRecord|error? { return {value: "Ballerina"}; } } function testSimpleQueryReturnStream3() { - TestGeneratorX generator = new (); - TestStreamX testStream = new (generator); + TestGenerator generator = new (); + TestStream testStream = new (generator); - var outputIntPersonStream = stream from var _ in testStream - select 1; + var outputIntPersonStream = stream from var _ in testStream select 1; assertTrue(outputIntPersonStream is stream); stream _ = outputIntPersonStream; - (record {|int value;|}|error)? x1 = outputIntPersonStream.next(); - if (x1 is record {|int value;|}) { + (record {| int value; |}|error)? x1 = outputIntPersonStream.next(); + if (x1 is record {| int value; |}) { assertEqual(x1.value, 1); } else { assertTrue(false); } - var outputStringPersonStream = stream from var _ in testStream - select "ABCD"; + var outputStringPersonStream = stream from var _ in testStream select "ABCD"; assertTrue(outputStringPersonStream is stream); stream _ = outputStringPersonStream; - (record {|string value;|}|error)? x2 = outputStringPersonStream.next(); - if (x2 is record {|string value;|}) { + (record {| string value; |}|error)? x2 = outputStringPersonStream.next(); + if (x2 is record {| string value; |}) { assertEqual(x2.value, "ABCD"); } else { assertTrue(false); @@ -205,30 +203,30 @@ function testSimpleQueryReturnStream3() { function testStreamInFromClauseWithReturnStream() returns boolean { boolean testPassed = true; - PersonX p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonX p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonX p3 = {firstName: "John", lastName: "David", age: 33}; - - PersonX[] personList = [p1, p2, p3]; - - stream outputEmployeeStream = stream from var {firstName, lastName, dept} in - >personList.toStream().filter(function(PersonX person) returns boolean { - return person.firstName == "John"; - }).'map(function(PersonX person) returns EmployeeX { - EmployeeX employee = { - firstName: person.firstName, - lastName: person.lastName, - dept: "Engineering" - }; - return employee; - }) - select { - firstName: firstName, - lastName: lastName, - dept: dept - }; - - record {|EmployeeX value;|}? employee = getEmployeeValue(outputEmployeeStream.next()); + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p3 = {firstName: "John", lastName: "David", age: 33}; + + Person[] personList = [p1, p2, p3]; + + stream outputEmployeeStream = stream from var {firstName, lastName, dept} in + >personList.toStream().filter(function (Person person) returns boolean { + return person.firstName == "John"; + }).'map(function (Person person) returns Employee { + Employee employee = { + firstName: person.firstName, + lastName: person.lastName, + dept: "Engineering" + }; + return employee; + }) + select { + firstName: firstName, + lastName: lastName, + dept: dept + }; + + record {| Employee value; |}? employee = getEmployeeValue(outputEmployeeStream.next()); testPassed = testPassed && employee?.value?.firstName == "John" && employee?.value?.lastName == "David" && employee?.value?.dept == "Engineering"; @@ -241,33 +239,33 @@ function testStreamInFromClauseWithReturnStream() returns boolean { function testStreamInFromClauseWithReturnStream2() { boolean testPassed = true; - PersonX p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonX p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonX p3 = {firstName: "John", lastName: "David", age: 33}; + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p3 = {firstName: "John", lastName: "David", age: 33}; - PersonX[] personList = [p1, p2, p3]; + Person[] personList = [p1, p2, p3]; var outputEmployeeStream = stream from var {firstName, lastName, dept} in - >personList.toStream().filter(function(PersonX person) returns boolean { - return person.firstName == "John"; - }).'map(function(PersonX person) returns EmployeeX { - EmployeeX employee = { - firstName: person.firstName, - lastName: person.lastName, - dept: "Engineering" - }; - return employee; - }) - select { - firstName: firstName, - lastName: lastName, - dept: dept - }; - - assertTrue(outputEmployeeStream is stream); - stream _ = outputEmployeeStream; - - record {|EmployeeX value;|}? employee = getEmployeeValue(outputEmployeeStream.next()); + >personList.toStream().filter(function (Person person) returns boolean { + return person.firstName == "John"; + }).'map(function (Person person) returns Employee { + Employee employee = { + firstName: person.firstName, + lastName: person.lastName, + dept: "Engineering" + }; + return employee; + }) + select { + firstName: firstName, + lastName: lastName, + dept: dept + }; + + assertTrue(outputEmployeeStream is stream); + stream _ = outputEmployeeStream; + + record {| Employee value; |}? employee = getEmployeeValue(outputEmployeeStream.next()); testPassed = testPassed && employee?.value?.firstName == "John" && employee?.value?.lastName == "David" && employee?.value?.dept == "Engineering"; @@ -279,28 +277,28 @@ function testStreamInFromClauseWithReturnStream2() { function testMultipleFromWhereAndLetReturnStream() returns boolean { boolean testPassed = true; - EmployeeX e1 = {firstName: "John", lastName: "Fonseka", dept: "Engineering"}; - EmployeeX e2 = {firstName: "John", lastName: "David", dept: "HR"}; + Employee e1 = {firstName: "John", lastName: "Fonseka", dept: "Engineering"}; + Employee e2 = {firstName: "John", lastName: "David", dept: "HR"}; - DepartmentX d1 = {dept: "Support"}; - DepartmentX d2 = {dept: "Dev"}; + Department d1 = {dept: "Support"}; + Department d2 = {dept: "Dev"}; - EmployeeX[] employeeList = [e1, e2]; - DepartmentX[] departmentList = [d1, d2]; + Employee[] employeeList = [e1, e2]; + Department[] departmentList = [d1, d2]; - stream outputEmployeeStream = stream from var emp in employeeList - from var department in departmentList - where emp.firstName == "John" - where emp.dept == "Engineering" - let string fname = "Johns" - let string deptName = "Research" - select { - firstName: fname, - lastName: emp.lastName, - dept: deptName - }; + stream outputEmployeeStream = stream from var emp in employeeList + from var department in departmentList + where emp.firstName == "John" + where emp.dept == "Engineering" + let string fname = "Johns" + let string deptName = "Research" + select { + firstName: fname, + lastName: emp.lastName, + dept: deptName + }; - record {|EmployeeX value;|}? employee = getEmployeeValue(outputEmployeeStream.next()); + record {| Employee value; |}? employee = getEmployeeValue(outputEmployeeStream.next()); testPassed = testPassed && employee?.value?.firstName == "Johns" && employee?.value?.lastName == "Fonseka" && employee?.value?.dept == "Research"; @@ -317,31 +315,31 @@ function testMultipleFromWhereAndLetReturnStream() returns boolean { function testMultipleFromWhereAndLetReturnStream2() { boolean testPassed = true; - EmployeeX e1 = {firstName: "John", lastName: "Fonseka", dept: "Engineering"}; - EmployeeX e2 = {firstName: "John", lastName: "David", dept: "HR"}; + Employee e1 = {firstName: "John", lastName: "Fonseka", dept: "Engineering"}; + Employee e2 = {firstName: "John", lastName: "David", dept: "HR"}; - DepartmentX d1 = {dept: "Support"}; - DepartmentX d2 = {dept: "Dev"}; + Department d1 = {dept: "Support"}; + Department d2 = {dept: "Dev"}; - EmployeeX[] employeeList = [e1, e2]; - DepartmentX[] departmentList = [d1, d2]; + Employee[] employeeList = [e1, e2]; + Department[] departmentList = [d1, d2]; var outputEmployeeStream = stream from var emp in employeeList - from var department in departmentList - where emp.firstName == "John" - where emp.dept == "Engineering" - let string fname = "Johns" - let string deptName = "Research" - select { - firstName: fname, - lastName: emp.lastName, - dept: deptName - }; - - assertTrue(outputEmployeeStream is stream); - stream _ = outputEmployeeStream; - - record {|EmployeeX value;|}? employee = getEmployeeValue(outputEmployeeStream.next()); + from var department in departmentList + where emp.firstName == "John" + where emp.dept == "Engineering" + let string fname = "Johns" + let string deptName = "Research" + select { + firstName: fname, + lastName: emp.lastName, + dept: deptName + }; + + assertTrue(outputEmployeeStream is stream); + stream _ = outputEmployeeStream; + + record {| Employee value; |}? employee = getEmployeeValue(outputEmployeeStream.next()); testPassed = testPassed && employee?.value?.firstName == "Johns" && employee?.value?.lastName == "Fonseka" && employee?.value?.dept == "Research"; @@ -354,90 +352,85 @@ function testMultipleFromWhereAndLetReturnStream2() { assertTrue(testPassed); } -type Employee2X record { +type Employee2 record { readonly string name; int salary; }; -type TblX table key(name); +type Tbl table key(name); function testConstructTablesWithRecords() { - table key(name) t = table [ - {name: "John", salary: 100}, - {name: "Jane", salary: 200} + table key(name) t = table [ + { name: "John", salary: 100 }, + { name: "Jane", salary: 200 } ]; - var ct = from Employee2X e in t - select e; - assertTrue(ct is table); - table a = ct; + var ct = from Employee2 e in t select e; + assertTrue(ct is table); + table a = ct; assertEqual(a.toString(), "[{\"name\":\"John\",\"salary\":100},{\"name\":\"Jane\",\"salary\":200}]"); - table key(name) t2 = table [ - {name: "John", salary: 100}, - {name: "Jane", salary: 200} - ]; + table key(name) t2 = table [ + { name: "John", salary: 100 }, + { name: "Jane", salary: 200 } + ]; - var ct2 = from record {readonly string name; int salary;} e in t2 - select e; - assertTrue(ct2 is table); - table a2 = ct2; + var ct2 = from record { readonly string name; int salary; } e in t2 select e; + assertTrue(ct2 is table); + table a2 = ct2; assertEqual(a2.toString(), "[{\"name\":\"John\",\"salary\":100},{\"name\":\"Jane\",\"salary\":200}]"); - var ct3 = from Employee2X e in t - select {name: e.name}; + var ct3 = from Employee2 e in t select {name: e.name}; assertTrue(ct3 is table); table a3 = ct3; assertEqual(a3.toString(), "[{\"name\":\"John\"},{\"name\":\"Jane\"}]"); - TblX t3 = table [ - {name: "John", salary: 100}, - {name: "Jane", salary: 200} + Tbl t3 = table [ + { name: "John", salary: 100 }, + { name: "Jane", salary: 200 } ]; - var ct4 = from Employee2X e in t3 - select e; - assertTrue(ct4 is table); - table a4 = ct4; + var ct4 = from Employee2 e in t3 select e; + assertTrue(ct4 is table); + table a4 = ct4; assertEqual(a4.toString(), "[{\"name\":\"John\",\"salary\":100},{\"name\":\"Jane\",\"salary\":200}]"); } function testConstructMapsWithTuples() { map a = {"a": 1, "b": 2}; - var cm = map from var i in a - select ["A", 1]; - assertTrue(cm is map); - map cm2 = cm; - assertEqual(cm2, {"A": 1}); + var cm = map from var i in a select ["A",1]; + assertTrue(cm is map); + map cm2 = cm; + assertEqual(cm2, {"A": 1}); } function testInnerJoinAndLimitReturnStream() returns boolean { boolean testPassed = true; - PersonX p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonX p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - EmployeeX e1 = {firstName: "Alex", lastName: "George", dept: "Engineering"}; - EmployeeX e2 = {firstName: "John", lastName: "David", dept: "HR"}; - EmployeeX e3 = {firstName: "Ranjan", lastName: "Fonseka", dept: "Operations"}; + Employee e1 = {firstName: "Alex", lastName: "George", dept: "Engineering"}; + Employee e2 = {firstName: "John", lastName: "David", dept: "HR"}; + Employee e3 = {firstName: "Ranjan", lastName: "Fonseka", dept: "Operations"}; - PersonX[] personList = [p1, p2]; - EmployeeX[] employeeList = [e1, e2, e3]; + Person[] personList = [p1, p2]; + Employee[] employeeList = [e1, e2, e3]; - stream outputEmpProfileStream = stream from var person in personList.toStream() - join EmployeeX employee in employeeList.toStream() + stream outputEmpProfileStream = stream from var person in personList.toStream() + join Employee employee in employeeList.toStream() on person.firstName equals employee.firstName - limit 1 - select { - firstName: employee.firstName, - lastName: employee.lastName, - age: person.age, - dept: employee.dept, - status: "Permanent" - }; + limit 1 + select { + firstName: employee.firstName, + lastName: employee.lastName, + age: person.age, + dept: employee.dept, + status: "Permanent" + }; - record {|EmpProfileX value;|}? empProfile = getEmpProfileValue(outputEmpProfileStream.next()); + record {| EmpProfile value; |}? empProfile = getEmpProfileValue(outputEmpProfileStream.next()); testPassed = testPassed && empProfile?.value?.firstName == "Alex" && empProfile?.value?.lastName == "George" && empProfile?.value?.age == 23 && empProfile?.value?.dept == "Engineering" && empProfile?.value?.status == "Permanent"; @@ -451,32 +444,32 @@ function testInnerJoinAndLimitReturnStream() returns boolean { function testInnerJoinAndLimitReturnStream2() { boolean testPassed = true; - PersonX p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonX p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - EmployeeX e1 = {firstName: "Alex", lastName: "George", dept: "Engineering"}; - EmployeeX e2 = {firstName: "John", lastName: "David", dept: "HR"}; - EmployeeX e3 = {firstName: "Ranjan", lastName: "Fonseka", dept: "Operations"}; + Employee e1 = {firstName: "Alex", lastName: "George", dept: "Engineering"}; + Employee e2 = {firstName: "John", lastName: "David", dept: "HR"}; + Employee e3 = {firstName: "Ranjan", lastName: "Fonseka", dept: "Operations"}; - PersonX[] personList = [p1, p2]; - EmployeeX[] employeeList = [e1, e2, e3]; + Person[] personList = [p1, p2]; + Employee[] employeeList = [e1, e2, e3]; var outputEmpProfileStream = stream from var person in personList.toStream() - join EmployeeX employee in employeeList.toStream() + join Employee employee in employeeList.toStream() on person.firstName equals employee.firstName - limit 1 - select { - firstName: employee.firstName, - lastName: employee.lastName, - age: person.age, - dept: employee.dept, - status: "Permanent" - }; + limit 1 + select { + firstName: employee.firstName, + lastName: employee.lastName, + age: person.age, + dept: employee.dept, + status: "Permanent" + }; - assertTrue(outputEmpProfileStream is stream); - stream _ = outputEmpProfileStream; + assertTrue(outputEmpProfileStream is stream); + stream _ = outputEmpProfileStream; - record {|EmpProfileX value;|}? empProfile = getEmpProfileValue(outputEmpProfileStream.next()); + record {| EmpProfile value; |}? empProfile = getEmpProfileValue(outputEmpProfileStream.next()); testPassed = testPassed && empProfile?.value?.firstName == "Alex" && empProfile?.value?.lastName == "George" && empProfile?.value?.age == 23 && empProfile?.value?.dept == "Engineering" && empProfile?.value?.status == "Permanent"; @@ -491,22 +484,22 @@ function testInnerJoinAndLimitReturnStream2() { function testSimpleQueryExprReturnTable() returns boolean { boolean testPassed = true; - CustomerX c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerX c2 = {id: 2, name: "James", noOfItems: 5}; - CustomerX c3 = {id: 3, name: "Anne", noOfItems: 20}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c3 = {id: 3, name: "Anne", noOfItems: 20}; - CustomerX[] customerList = [c1, c2, c3]; + Customer[] customerList = [c1, c2, c3]; - CustomerTableX customerTable = table key(id, name) from var customer in customerList + CustomerTable customerTable = table key(id, name) from var customer in customerList select { id: customer.id, name: customer.name, noOfItems: customer.noOfItems }; - if (customerTable is CustomerTableX) { + if (customerTable is CustomerTable) { var itr = customerTable.iterator(); - CustomerX? customer = getCustomer(itr.next()); + Customer? customer = getCustomer(itr.next()); testPassed = testPassed && customer == customerList[0]; customer = getCustomer(itr.next()); testPassed = testPassed && customer == customerList[1]; @@ -522,11 +515,11 @@ function testSimpleQueryExprReturnTable() returns boolean { function testSimpleQueryExprReturnTable2() { boolean testPassed = true; - CustomerX c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerX c2 = {id: 2, name: "James", noOfItems: 5}; - CustomerX c3 = {id: 3, name: "Anne", noOfItems: 20}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c3 = {id: 3, name: "Anne", noOfItems: 20}; - CustomerX[] customerList = [c1, c2, c3]; + Customer[] customerList = [c1, c2, c3]; var customerTable = table key(id, name) from var customer in customerList select { @@ -535,12 +528,12 @@ function testSimpleQueryExprReturnTable2() { noOfItems: customer.noOfItems }; - assertTrue(customerTable is CustomerTableX); - CustomerTableX _ = customerTable; + assertTrue(customerTable is CustomerTable); + CustomerTable _ = customerTable; - if (customerTable is CustomerTableX) { + if (customerTable is CustomerTable) { var itr = customerTable.iterator(); - CustomerX? customer = getCustomer(itr.next()); + Customer? customer = getCustomer(itr.next()); testPassed = testPassed && customer == customerList[0]; customer = getCustomer(itr.next()); testPassed = testPassed && customer == customerList[1]; @@ -554,29 +547,26 @@ function testSimpleQueryExprReturnTable2() { } function testTableWithDuplicateKeys() { - CustomerX c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerX c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; - CustomerX[] customerList = [c1, c2, c1]; + Customer[] customerList = [c1, c2, c1]; - CustomerTableX customerTable = table key(id, name) from var customer in customerList + CustomerTable customerTable = table key(id, name) from var customer in customerList select { id: customer.id, name: customer.name, noOfItems: customer.noOfItems }; - assertEqual(customerTable, table key(id, name) [ - {"id": 1, "name": "Melina", "noOfItems": 12}, - {"id": 2, "name": "James", "noOfItems": 5} - ]); + assertEqual(customerTable, table key(id,name) [{"id":1,"name":"Melina","noOfItems":12},{"id":2,"name":"James","noOfItems":5}]); } function testTableWithDuplicateKeys2() { - CustomerX c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerX c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; - CustomerX[] customerList = [c1, c2, c1]; + Customer[] customerList = [c1, c2, c1]; var customerTable = table key(id, name) from var customer in customerList select { @@ -585,26 +575,23 @@ function testTableWithDuplicateKeys2() { noOfItems: customer.noOfItems }; - assertTrue(customerTable is CustomerTableX); - CustomerTableX _ = customerTable; + assertTrue(customerTable is CustomerTable); + CustomerTable _ = customerTable; - assertEqual(customerTable, table key(id, name) [ - {"id": 1, "name": "Melina", "noOfItems": 12}, - {"id": 2, "name": "James", "noOfItems": 5} - ]); + assertEqual(customerTable, table key(id,name) [{"id":1,"name":"Melina","noOfItems":12},{"id":2,"name":"James","noOfItems":5}]); } function testTableNoDuplicatesAndOnConflictReturnTable() returns boolean { boolean testPassed = true; error onConflictError = error("Key Conflict", message = "cannot insert."); - CustomerX c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerX c2 = {id: 2, name: "James", noOfItems: 5}; - CustomerX c3 = {id: 3, name: "Anne", noOfItems: 20}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c3 = {id: 3, name: "Anne", noOfItems: 20}; - CustomerX[] customerList = [c1, c2, c3]; + Customer[] customerList = [c1, c2, c3]; - CustomerTableX|error customerTable = table key(id, name) from var customer in customerList + CustomerTable|error customerTable = table key(id, name) from var customer in customerList select { id: customer.id, name: customer.name, @@ -612,9 +599,9 @@ function testTableNoDuplicatesAndOnConflictReturnTable() returns boolean { } on conflict onConflictError; - if (customerTable is CustomerTableX) { + if (customerTable is CustomerTable) { var itr = customerTable.iterator(); - CustomerX? customer = getCustomer(itr.next()); + Customer? customer = getCustomer(itr.next()); testPassed = testPassed && customer == customerList[0]; customer = getCustomer(itr.next()); testPassed = testPassed && customer == customerList[1]; @@ -628,113 +615,113 @@ function testTableNoDuplicatesAndOnConflictReturnTable() returns boolean { } function testTableWithDuplicatesAndOnConflictReturnTable() { - error onConflictError = error("Key Conflict", message = "cannot insert."); + error onConflictError = error("Key Conflict", message = "cannot insert."); - CustomerX c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerX c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; - CustomerX[] customerList = [c1, c2, c1]; + Customer[] customerList = [c1, c2, c1]; - CustomerTableX|error customerTable = table key(id, name) from var customer in customerList - select { - id: customer.id, - name: customer.name, - noOfItems: customer.noOfItems - } - on conflict onConflictError; + CustomerTable|error customerTable = table key(id, name) from var customer in customerList + select { + id: customer.id, + name: customer.name, + noOfItems: customer.noOfItems + } + on conflict onConflictError; - validateKeyConflictError(customerTable); + validateKeyConflictError(customerTable); } function testQueryExprWithOtherClausesReturnTable() { - error onConflictError = error("Key Conflict", message = "cannot insert."); + error onConflictError = error("Key Conflict", message = "cannot insert."); - CustomerX c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerX c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; - PersonX p1 = {firstName: "Amy", lastName: "Melina", age: 23}; - PersonX p2 = {firstName: "Frank", lastName: "James", age: 30}; + Person p1 = {firstName: "Amy", lastName: "Melina", age: 23}; + Person p2 = {firstName: "Frank", lastName: "James", age: 30}; - CustomerX[] customerList = [c1, c2, c1]; - PersonX[] personList = [p1, p2]; + Customer[] customerList = [c1, c2, c1]; + Person[] personList = [p1, p2]; - CustomerTableX|error customerTable = table key(id, name) from var customer in customerList - from var person in personList - let int items = 25 - let string customerName = "Bini" - where customer.id == 1 - where person.firstName == "Amy" - select { - id: customer.id, - name: customerName, - noOfItems: items - } - on conflict onConflictError; + CustomerTable|error customerTable = table key(id, name) from var customer in customerList + from var person in personList + let int items = 25 + let string customerName = "Bini" + where customer.id == 1 + where person.firstName == "Amy" + select { + id: customer.id, + name: customerName, + noOfItems: items + } + on conflict onConflictError; - validateKeyConflictError(customerTable); + validateKeyConflictError(customerTable); } function validateKeyConflictError(any|error value) { - if (value is error) { - any|error detailMessage = value.detail()["message"]; - if (value.message() == "Key Conflict" + if (value is error) { + any|error detailMessage = value.detail()["message"]; + if (value.message() == "Key Conflict" && detailMessage is string && detailMessage == "cannot insert.") { - return; - } - panic error("Assertion error"); - } - panic error("Expected error, found: " + (typeof value).toString()); + return; + } + panic error("Assertion error"); + } + panic error("Expected error, found: " + (typeof value).toString()); } function testQueryExprWithJoinClauseReturnTable() { - error onConflictError = error("Key Conflict", message = "cannot insert."); + error onConflictError = error("Key Conflict", message = "cannot insert."); - CustomerX c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerX c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; - PersonX p1 = {firstName: "Amy", lastName: "Melina", age: 23}; - PersonX p2 = {firstName: "Frank", lastName: "James", age: 30}; + Person p1 = {firstName: "Amy", lastName: "Melina", age: 23}; + Person p2 = {firstName: "Frank", lastName: "James", age: 30}; - CustomerX[] customerList = [c1, c2, c1]; - PersonX[] personList = [p1, p2]; + Customer[] customerList = [c1, c2, c1]; + Person[] personList = [p1, p2]; - CustomerTableX|error customerTable = table key(id, name) from var customer in customerList - join var person in personList - on customer.name equals person.lastName - select { - id: customer.id, - name: person.firstName, - noOfItems: customer.noOfItems - } - on conflict onConflictError; + CustomerTable|error customerTable = table key(id, name) from var customer in customerList + join var person in personList + on customer.name equals person.lastName + select { + id: customer.id, + name: person.firstName, + noOfItems: customer.noOfItems + } + on conflict onConflictError; - validateKeyConflictError(customerTable); + validateKeyConflictError(customerTable); } function testQueryExprWithLimitClauseReturnTable() returns boolean { - boolean testPassed = true; - error onConflictError = error("Key Conflict", message = "cannot insert."); - - CustomerX c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerX c2 = {id: 2, name: "James", noOfItems: 5}; - CustomerX c3 = {id: 3, name: "Melina", noOfItems: 25}; - - CustomerX[] customerList = [c1, c2, c3]; - - CustomerTableX|error customerTable = table key(id, name) from var customer in customerList.toStream() - where customer.name == "Melina" - limit 1 - select { - id: customer.id, - name: customer.name, - noOfItems: customer.noOfItems - } - on conflict onConflictError; - - if (customerTable is CustomerTableX) { + boolean testPassed = true; + error onConflictError = error("Key Conflict", message = "cannot insert."); + + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c3 = {id: 3, name: "Melina", noOfItems: 25}; + + Customer[] customerList = [c1, c2, c3]; + + CustomerTable|error customerTable = table key(id, name) from var customer in customerList.toStream() + where customer.name == "Melina" + limit 1 + select { + id: customer.id, + name: customer.name, + noOfItems: customer.noOfItems + } + on conflict onConflictError; + + if (customerTable is CustomerTable) { var itr = customerTable.iterator(); - CustomerX? customer = getCustomer(itr.next()); + Customer? customer = getCustomer(itr.next()); testPassed = testPassed && customer == customerList[0]; customer = getCustomer(itr.next()); testPassed = testPassed && customer == (); @@ -746,22 +733,22 @@ function testQueryExprWithLimitClauseReturnTable() returns boolean { function testKeyLessTableWithReturnTable() returns boolean { boolean testPassed = true; - CustomerX c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerX c2 = {id: 2, name: "James", noOfItems: 5}; - CustomerX c3 = {id: 3, name: "Anne", noOfItems: 20}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c3 = {id: 3, name: "Anne", noOfItems: 20}; - CustomerX[] customerList = [c1, c2, c3]; + Customer[] customerList = [c1, c2, c3]; - CustomerKeyLessTableX customerTable = table key(id, name) from var customer in customerList + CustomerKeyLessTable customerTable = table key(id, name) from var customer in customerList select { id: customer.id, name: customer.name, noOfItems: customer.noOfItems }; - if (customerTable is CustomerKeyLessTableX) { + if (customerTable is CustomerKeyLessTable) { var itr = customerTable.iterator(); - CustomerX? customer = getCustomer(itr.next()); + Customer? customer = getCustomer(itr.next()); testPassed = testPassed && customer == customerList[0]; customer = getCustomer(itr.next()); testPassed = testPassed && customer == customerList[1]; @@ -774,7 +761,7 @@ function testKeyLessTableWithReturnTable() returns boolean { return testPassed; } -type UserX record { +type User record { readonly int id; string firstName; string lastName; @@ -782,67 +769,67 @@ type UserX record { }; function testQueryConstructingTableUpdateKeyPanic1() returns error? { - table key(id) users = table [ + table key(id) users = table [ {id: 1, firstName: "John", lastName: "Doe", age: 25} ]; var result = table key(id, name) from var user in users - where user.age > 21 && user.age < 60 - select {id: user.id, name: user.firstName, user}; + where user.age > 21 && user.age < 60 + select {id: user.id, name: user.firstName, user}; var r2 = result[1, "John"]; + User user; + }> result[1, "John"]; r2.id = 1; } -type NewUserX record {| +type NewUser record {| readonly int id; readonly string name; - UserX user; + User user; |}; function testQueryConstructingTableUpdateKeyPanic2() returns error? { - table key(id) users = table [ + table key(id) users = table [ {id: 1, firstName: "John", lastName: "Doe", age: 25} ]; - table key(id, name) result = - table key(id, name) from var user in users - where user.age > 21 && user.age < 60 - select {id: user.id, name: user.firstName, user}; + table key(id, name) result = + table key(id, name) from var user in users + where user.age > 21 && user.age < 60 + select {id: user.id, name: user.firstName, user}; var r2 = result[1, "John"]; + User user; + }> result[1, "John"]; r2.id = 2; } -type CustomErrorDetailX record {| +type CustomErrorDetail record {| string message; int code; |}; -type CustomErrorX error; +type CustomError error; function testTableOnConflict() { error? onConflictError1 = error("Key Conflict", message = "cannot insert."); error|null onConflictError2 = (); error|null onConflictError3 = null; - CustomErrorX? onConflictError4 = error("error msg 1", message = "error 1", code = 500); - CustomErrorX? onConflictError5 = error("error msg 2", message = "error 2", code = 500); + CustomError? onConflictError4 = error ("error msg 1", message = "error 1", code = 500); + CustomError? onConflictError5 = error ("error msg 2", message = "error 2", code = 500); - CustomerX c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerX c2 = {id: 1, name: "James", noOfItems: 5}; - CustomerX c3 = {id: 3, name: "Anne", noOfItems: 20}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 1, name: "James", noOfItems: 5}; + Customer c3 = {id: 3, name: "Anne", noOfItems: 20}; - CustomerX[] customerList = [c1, c2, c3]; + Customer[] customerList = [c1, c2, c3]; var customerTable1 = table key(id) from var customer in customerList select { @@ -862,10 +849,7 @@ function testTableOnConflict() { } on conflict onConflictError2; - assertEqual(customerTable2, table key(id) [ - {"id": 1, "name": "James", "noOfItems": 5}, - {"id": 3, "name": "Anne", "noOfItems": 20} - ]); + assertEqual(customerTable2, table key(id) [{"id":1,"name":"James","noOfItems":5},{"id":3,"name":"Anne","noOfItems":20}]); var customerTable3 = table key(id) from var customer in customerList select { @@ -875,10 +859,7 @@ function testTableOnConflict() { } on conflict onConflictError3; - assertEqual(customerTable3, table key(id) [ - {"id": 1, "name": "James", "noOfItems": 5}, - {"id": 3, "name": "Anne", "noOfItems": 20} - ]); + assertEqual(customerTable3, table key(id) [{"id":1,"name":"James","noOfItems":5},{"id":3,"name":"Anne","noOfItems":20}]); var customerTable4 = table key(id) from var customer in customerList select { @@ -908,10 +889,7 @@ function testTableOnConflict() { } on conflict null; - assertEqual(customerTable6, table key(id) [ - {"id": 1, "name": "James", "noOfItems": 5}, - {"id": 3, "name": "Anne", "noOfItems": 20} - ]); + assertEqual(customerTable6, table key(id) [{"id":1,"name":"James","noOfItems":5},{"id":3,"name":"Anne","noOfItems":20}]); var customerTable7 = table key(id) from var customer in customerList select { @@ -921,10 +899,7 @@ function testTableOnConflict() { } on conflict (); - assertEqual(customerTable7, table key(id) [ - {"id": 1, "name": "James", "noOfItems": 5}, - {"id": 3, "name": "Anne", "noOfItems": 20} - ]); + assertEqual(customerTable7, table key(id) [{"id":1,"name":"James","noOfItems":5},{"id":3,"name":"Anne","noOfItems":20}]); } type Token record {| @@ -936,8 +911,7 @@ type TokenTable table key(idx); function testQueryConstructingTableWithOnConflictClauseHavingNonTableQueryInLetClause() { TokenTable|error tbl1 = table key(idx) from int i in 1 ... 3 - let int[] arr = from var j in 1 ... 3 - select j + let int[] arr = from var j in 1 ... 3 select j select { idx: arr[i - 1], value: "A" + i.toString() @@ -945,10 +919,10 @@ function testQueryConstructingTableWithOnConflictClauseHavingNonTableQueryInLetC on conflict error("Duplicate Key"); TokenTable expectedTbl = table [ - {"idx": 1, "value": "A1"}, - {"idx": 2, "value": "A2"}, - {"idx": 3, "value": "A3"} - ]; + {"idx": 1, "value": "A1"}, + {"idx": 2, "value": "A2"}, + {"idx": 3, "value": "A3"} + ]; assertEqual(true, tbl1 is TokenTable); if tbl1 is TokenTable { @@ -956,8 +930,7 @@ function testQueryConstructingTableWithOnConflictClauseHavingNonTableQueryInLetC } TokenTable|error tbl2 = table key(idx) from int i in [1, 2, 1] - let int[] arr = from var j in 1 ... 3 - select j + let int[] arr = from var j in 1 ... 3 select j select { idx: arr[i], value: "A" + i.toString() @@ -973,8 +946,7 @@ function testQueryConstructingTableWithOnConflictClauseHavingNonTableQueryInLetC function testQueryConstructingTableWithOnConflictClauseHavingNonTableQueryInWhereClause() { TokenTable|error tbl1 = table key(idx) from int i in 1 ... 3 let int[] arr = [1, 2, 3] - where arr == from int j in 1 ... 3 - select j + where arr == from int j in 1...3 select j select { idx: i, value: "A" + i.toString() @@ -982,10 +954,10 @@ function testQueryConstructingTableWithOnConflictClauseHavingNonTableQueryInWher on conflict error("Duplicate Key"); TokenTable expectedTbl = table [ - {"idx": 1, "value": "A1"}, - {"idx": 2, "value": "A2"}, - {"idx": 3, "value": "A3"} - ]; + {"idx": 1, "value": "A1"}, + {"idx": 2, "value": "A2"}, + {"idx": 3, "value": "A3"} + ]; assertEqual(true, tbl1 is TokenTable); if tbl1 is TokenTable { @@ -994,8 +966,7 @@ function testQueryConstructingTableWithOnConflictClauseHavingNonTableQueryInWher TokenTable|error tbl2 = table key(idx) from int i in [1, 2, 1] let int[] arr = [1, 2, 3] - where arr == from int j in 1 ... 3 - select j + where arr == from int j in 1...3 select j select { idx: i, value: "A" + i.toString() @@ -1009,7 +980,7 @@ function testQueryConstructingTableWithOnConflictClauseHavingNonTableQueryInWher } function testQueryConstructingTableWithOnConflictsWithVarRef() { - TokenTable|error tbl1 = table key(idx) from int i in [1, 2, 3, 1, 2, 3] + TokenTable|error tbl1 = table key(idx) from int i in [1, 2, 3, 1, 2, 3] let string value = "A" + i.toString() select { idx: i, @@ -1033,13 +1004,13 @@ function testQueryConstructingTableWithOnConflictsWithVarRef() { } function testMapConstructingQueryExpr() { - CustomerX c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerX c2 = {id: 2, name: "James", noOfItems: 5}; - CustomerX c3 = {id: 3, name: "Anne", noOfItems: 20}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c3 = {id: 3, name: "Anne", noOfItems: 20}; - CustomerX[] list1 = [c1, c2, c3]; + Customer[] list1 = [c1, c2, c3]; - map map1 = map from var customer in list1 + map map1 = map from var customer in list1 select [customer.id.toString(), customer]; assertEqual(map1, {"1": {id: 1, name: "Melina", noOfItems: 12}, "2": {id: 2, name: "James", noOfItems: 5}, "3": {id: 3, name: "Anne", noOfItems: 20}}); @@ -1074,37 +1045,37 @@ function testMapConstructingQueryExpr() { map map4 = map from var item in list4 select [item[0], item[1]]; - map expectedMap = {"a": 123, "b": 123, "c": error("Error"), "zero": 0}; + map expectedMap = {"a":123,"b":123,"c":error("Error"),"zero":0}; - assertEqual(expectedMap.length(), (>map4).length()); + assertEqual(expectedMap.length(), (> map4).length()); foreach var key in expectedMap.keys() { - assertEqual(expectedMap[key], (>map4)[key]); + assertEqual(expectedMap[key], (> map4)[key]); } } function testMapConstructingQueryExpr2() { map map1 = map from var e in map from var e in [1, 2, 10, 3, 5, 20] - order by e descending - select [e.toString(), e] - order by e ascending - select [e.toString(), e]; - assertEqual(map1, {"1": 1, "2": 2, "3": 3, "5": 5, "10": 10, "20": 20}); + order by e descending + select [e.toString(), e] + order by e ascending + select [e.toString(), e]; + assertEqual(map1, {"1":1,"2":2,"3":3,"5":5,"10":10,"20":20}); map map2 = map from var e in (from var e in [1, 2, 5, 4] - let int f = e / 2 - order by f ascending - select f) - order by e descending - select [e.toString(), e]; - assertEqual(map2, {"2": 2, "1": 1, "0": 0}); + let int f = e / 2 + order by f ascending + select f) + order by e descending + select [e.toString(), e]; + assertEqual(map2, {"2":2,"1":1,"0":0}); } function testMapConstructingQueryExprWithDuplicateKeys() { - CustomerX c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerX c2 = {id: 2, name: "James", noOfItems: 5}; - CustomerX c3 = {id: 3, name: "Anne", noOfItems: 20}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c3 = {id: 3, name: "Anne", noOfItems: 20}; - CustomerX[] list1 = [c1, c2, c3, c1, c2, c3]; + Customer[] list1 = [c1, c2, c3, c1, c2, c3]; var map1 = map from var customer in list1 select [customer.id.toString(), customer]; @@ -1133,12 +1104,12 @@ function testMapConstructingQueryExprWithDuplicateKeys() { } function testMapConstructingQueryExprWithOnConflict() { - CustomerX c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerX c2 = {id: 2, name: "James", noOfItems: 5}; - CustomerX c3 = {id: 3, name: "Anne", noOfItems: 20}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c3 = {id: 3, name: "Anne", noOfItems: 20}; ()|error conflictMsg1 = (); - CustomerX[] list1 = [c1, c2, c3, c1, c2, c3]; + Customer[] list1 = [c1, c2, c3, c1, c2, c3]; var mapWithOnConflict1 = map from var customer in list1 select [customer.id.toString(), customer] @@ -1165,7 +1136,7 @@ function testMapConstructingQueryExprWithOnConflict() { [string:Char, int:Signed16] t5 = ["b", 123]; [string, int] t6 = ["c", -123]; [string, int:Unsigned32] t7 = ["zero", 0]; - CustomErrorX? onConflictError4 = error("error msg 1", message = "Error 2", code = 500); + CustomError? onConflictError4 = error("error msg 1", message = "Error 2", code = 500); [string, int][] list3 = [t4, t5, t4, t6, t6, t7, t7, t4]; map|error map3 = map from var item in list3 @@ -1184,14 +1155,14 @@ function testMapConstructingQueryExprWithOnConflict() { function testMapConstructingQueryExprWithOtherClauses() { error onConflictError = error("Key Conflict", message = "cannot insert."); - CustomerX c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerX c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; - PersonX p1 = {firstName: "Amy", lastName: "Melina", age: 23}; - PersonX p2 = {firstName: "Frank", lastName: "James", age: 30}; + Person p1 = {firstName: "Amy", lastName: "Melina", age: 23}; + Person p2 = {firstName: "Frank", lastName: "James", age: 30}; - CustomerX[] customerList1 = [c1, c2, c2]; - PersonX[] personList = [p1, p2]; + Customer[] customerList1 = [c1, c2, c2]; + Person[] personList = [p1, p2]; var selectedCustomers1 = map from var customer in customerList1 from var person in personList @@ -1209,14 +1180,14 @@ function testMapConstructingQueryExprWithOtherClauses() { on conflict onConflictError; assertEqual(selectedCustomers1, {"Amy Melina": {"id": 1, "name": "Amy Melina"}}); - CustomerX c3 = {id: 1, name: "Melina", noOfItems: 22}; - CustomerX c4 = {id: 2, name: "James", noOfItems: 15}; - CustomerX c5 = {id: 1, name: "Melina", noOfItems: 10}; - CustomerX c6 = {id: 2, name: "James", noOfItems: 11}; + Customer c3 = {id: 1, name: "Melina", noOfItems: 22}; + Customer c4 = {id: 2, name: "James", noOfItems: 15}; + Customer c5 = {id: 1, name: "Melina", noOfItems: 10}; + Customer c6 = {id: 2, name: "James", noOfItems: 11}; - CustomerX[] customerList2 = [c1, c2, c3, c4, c5, c6]; + Customer[] customerList2 = [c1, c2, c3, c4, c5, c6]; - map|error selectedCustomers2 = map from var customer in customerList2 + map|error selectedCustomers2 = map from var customer in customerList2 from var person in personList let string fullName = person.firstName + " " + person.lastName where customer.name == person.lastName @@ -1253,218 +1224,195 @@ function testMapConstructingQueryExprWithOtherClauses() { function testMapConstructingQueryExprWithJoinClause() { error onConflictError = error("Key Conflict", message = "cannot insert."); - CustomerX c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerX c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; - PersonX p1 = {firstName: "Amy", lastName: "Melina", age: 23}; - PersonX p2 = {firstName: "Frank", lastName: "James", age: 30}; + Person p1 = {firstName: "Amy", lastName: "Melina", age: 23}; + Person p2 = {firstName: "Frank", lastName: "James", age: 30}; - CustomerX[] customerList1 = [c1, c2, c1]; - PersonX[] personList = [p1, p2]; + Customer[] customerList1 = [c1, c2, c1]; + Person[] personList = [p1, p2]; var customerMap1 = map from var customer in customerList1 join var person in personList on customer.name equals person.lastName - select [ - customer.id.toString(), - { - id: customer.id, - name: person.firstName, - age: person.age, - noOfItems: customer.noOfItems - } - ] + select [customer.id.toString(), { + id: customer.id, + name: person.firstName, + age: person.age, + noOfItems: customer.noOfItems + }] on conflict onConflictError; assertEqual(customerMap1, onConflictError); - CustomerX[] customerList2 = [c1, c2]; + Customer[] customerList2 = [c1, c2]; var customerMap2 = map from var customer in customerList2 join var person in personList on customer.name equals person.lastName - select [ - customer.id.toString(), - { - id: customer.id, - name: person.firstName, - age: person.age, - noOfItems: customer.noOfItems - } - ] + select [customer.id.toString(), { + id: customer.id, + name: person.firstName, + age: person.age, + noOfItems: customer.noOfItems + }] on conflict onConflictError; - assertEqual(customerMap2, {"1": {"id": 1, "name": "Amy", "age": 23, "noOfItems": 12}, "2": {"id": 2, "name": "Frank", "age": 30, "noOfItems": 5}}); + assertEqual(customerMap2, {"1":{"id":1,"name":"Amy","age":23,"noOfItems":12},"2":{"id":2,"name":"Frank","age":30,"noOfItems":5}}); } function testMapConstructingQueryExprWithLimitClause() { error onConflictError = error("Key Conflict", message = "cannot insert."); - CustomerX c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerX c2 = {id: 2, name: "James", noOfItems: 5}; - CustomerX c3 = {id: 3, name: "Melina", noOfItems: 25}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c3 = {id: 3, name: "Melina", noOfItems: 25}; - CustomerX[] customerList = [c1, c2, c3]; + Customer[] customerList = [c1, c2, c3]; - map|error customerMap1 = map from var customer in customerList.toStream() + map|error customerMap1 = map from var customer in customerList.toStream() where customer.name == "Melina" limit 1 - select [ - customer.name, - { - id: customer.id, - name: customer.name, - noOfItems: customer.noOfItems - } - ] + select [customer.name, { + id: customer.id, + name: customer.name, + noOfItems: customer.noOfItems + }] on conflict onConflictError; - assertEqual(customerMap1, {"Melina": {"id": 1, "name": "Melina", "noOfItems": 12}}); + assertEqual(customerMap1, {"Melina":{"id":1,"name":"Melina","noOfItems":12}}); } function testMapConstructingQueryExprWithOrderByClause() { map sorted1 = map from var e in [1, 2, 10, 3, 5, 20] - order by e ascending - select [e.toString(), e]; - assertEqual(sorted1, {"1": 1, "2": 2, "3": 3, "5": 5, "10": 10, "20": 20}); + order by e ascending + select [e.toString(), e]; + assertEqual(sorted1, {"1":1,"2":2,"3":3,"5":5,"10":10,"20":20}); map sorted2 = map from var e in [1, 2, 10, 3, 5, 20] - order by e descending - select [e.toString(), e]; - assertEqual(sorted2, {"20": 20, "10": 10, "5": 5, "3": 3, "2": 2, "1": 1}); + order by e descending + select [e.toString(), e]; + assertEqual(sorted2, {"20":20,"10":10,"5":5,"3":3,"2":2,"1":1}); var sorted3 = map from var e in ["1", "2", "10", "3", "5", "20"] - order by e ascending - select [e, e] - on conflict (); - assertEqual(sorted3, {"1": "1", "10": "10", "2": "2", "20": "20", "3": "3", "5": "5"}); + order by e ascending + select [e, e] on conflict (); + assertEqual(sorted3, {"1":"1","10":"10","2":"2","20":"20","3":"3","5":"5"}); var sorted4 = map from var e in [1, 2, 5, 4] - let int f = e / 2 - order by f ascending - select [f.toString(), e] - on conflict error("Error"); + let int f = e / 2 + order by f ascending + select [f.toString(), e] on conflict error("Error"); assertEqual(sorted4, error("Error")); } type Error error; - type Json json; - type IntOrString int|string; - type ZeroOrOne 1|0; type MapOfJsonOrError map|Error; - type MapOfIntOrError map|Error; - type ErrorOrMapOfZeroOrOne Error|map; function testMapConstructingQueryExprWithReferenceTypes() { map sorted1 = map from var e in [1, 0, 1, 0, 1, 1] - order by e ascending - select [e.toString(), e]; - assertEqual(sorted1, {"0": 0, "1": 1}); + order by e ascending + select [e.toString(), e]; + assertEqual(sorted1, {"0":0,"1":1}); ErrorOrMapOfZeroOrOne sorted2 = map from var e in [1, 0, 1, 0, 0, 0] - order by e ascending - select [e.toString(), e]; - assertEqual(sorted2, {"0": 0, "1": 1}); + order by e ascending + select [e.toString(), e]; + assertEqual(sorted2, {"0":0,"1":1}); map sorted3 = map from var e in ["1", "2", "10", "3", "5", "20"] - order by e ascending - select [e, e] - on conflict (); - assertEqual(sorted3, {"1": "1", "10": "10", "2": "2", "20": "20", "3": "3", "5": "5"}); + order by e ascending + select [e, e] on conflict (); + assertEqual(sorted3, {"1":"1","10":"10","2":"2","20":"20","3":"3","5":"5"}); MapOfJsonOrError sorted4 = map from var e in ["1", "2", "10", "3", "5", "20"] - order by e ascending - select [e, e] - on conflict error("Error"); - assertEqual(sorted4, {"1": "1", "10": "10", "2": "2", "20": "20", "3": "3", "5": "5"}); + order by e ascending + select [e, e] on conflict error("Error"); + assertEqual(sorted4, {"1":"1","10":"10","2":"2","20":"20","3":"3","5":"5"}); MapOfIntOrError sorted5 = map from var e in [1, 2, 5, 4] - let int f = e / 2 - order by f ascending - select [f.toString(), e] - on conflict error("Error"); + let int f = e / 2 + order by f ascending + select [f.toString(), e] on conflict error("Error"); assertEqual(sorted5, error("Error")); } function testReadonlyTable() { - CustomerX c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerX c2 = {id: 2, name: "James", noOfItems: 5}; - CustomerX c3 = {id: 3, name: "Anne", noOfItems: 20}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c3 = {id: 3, name: "Anne", noOfItems: 20}; - CustomerX[] customerList1 = [c1, c2, c3]; + Customer[] customerList1 = [c1, c2, c3]; - CustomerKeyLessTableX & readonly customerTable1 = table key(id, name) from var customer in customerList1 + CustomerKeyLessTable & readonly customerTable1 = table key(id, name) from var customer in customerList1 select { id: customer.id, name: customer.name, noOfItems: customer.noOfItems }; - any _ = customerTable1; - assertEqual((typeof (customerTable1)).toString(), "typedesc [{\"id\":1,\"name\":\"Melina\",\"noOfItems\":12},{\"id\":2,\"name\":\"James\",\"noOfItems\":5},{\"id\":3,\"name\":\"Anne\",\"noOfItems\":20}]"); - assertEqual(customerTable1.toString(), [{"id": 1, "name": "Melina", "noOfItems": 12}, {"id": 2, "name": "James", "noOfItems": 5}, {"id": 3, "name": "Anne", "noOfItems": 20}].toString()); + any _ = customerTable1; + assertEqual((typeof(customerTable1)).toString(), "typedesc [{\"id\":1,\"name\":\"Melina\",\"noOfItems\":12},{\"id\":2,\"name\":\"James\",\"noOfItems\":5},{\"id\":3,\"name\":\"Anne\",\"noOfItems\":20}]"); + assertEqual(customerTable1.toString(), [{"id":1,"name":"Melina","noOfItems":12},{"id":2,"name":"James","noOfItems":5},{"id":3,"name":"Anne","noOfItems":20}].toString()); - CustomerX[] & readonly customerList2 = [c1, c2, c3].cloneReadOnly(); + Customer[] & readonly customerList2 = [c1, c2, c3].cloneReadOnly(); - CustomerKeyLessTableX & readonly|error customerTable2 = table key(id, name) from var customer in customerList2 + CustomerKeyLessTable & readonly|error customerTable2 = table key(id, name) from var customer in customerList2 select { id: customer.id, name: customer.name, noOfItems: customer.noOfItems - } - on conflict error("Error"); - any _ = (checkpanic customerTable2); - assertEqual((typeof (checkpanic customerTable2)).toString(), "typedesc [{\"id\":1,\"name\":\"Melina\",\"noOfItems\":12},{\"id\":2,\"name\":\"James\",\"noOfItems\":5},{\"id\":3,\"name\":\"Anne\",\"noOfItems\":20}]"); - assertEqual((checkpanic customerTable2).toString(), [{"id": 1, "name": "Melina", "noOfItems": 12}, {"id": 2, "name": "James", "noOfItems": 5}, {"id": 3, "name": "Anne", "noOfItems": 20}].toString()); + } on conflict error("Error"); + any _ = (checkpanic customerTable2); + assertEqual((typeof(checkpanic customerTable2)).toString(), "typedesc [{\"id\":1,\"name\":\"Melina\",\"noOfItems\":12},{\"id\":2,\"name\":\"James\",\"noOfItems\":5},{\"id\":3,\"name\":\"Anne\",\"noOfItems\":20}]"); + assertEqual((checkpanic customerTable2).toString(), [{"id":1,"name":"Melina","noOfItems":12},{"id":2,"name":"James","noOfItems":5},{"id":3,"name":"Anne","noOfItems":20}].toString()); - CustomerKeyLessTableX customerTable3 = table key(id, name) from var customer in customerList2 + CustomerKeyLessTable customerTable3 = table key(id, name) from var customer in customerList2 select { id: customer.id, name: customer.name, noOfItems: customer.noOfItems - } - on conflict (); - assertEqual((typeof (customerTable3)).toString(), "typedesc table key(id, name)"); - assertEqual(customerTable3.toString(), [{"id": 1, "name": "Melina", "noOfItems": 12}, {"id": 2, "name": "James", "noOfItems": 5}, {"id": 3, "name": "Anne", "noOfItems": 20}].toString()); + } on conflict (); + assertEqual((typeof(customerTable3)).toString(), "typedesc table key(id, name)"); + assertEqual(customerTable3.toString(), [{"id":1,"name":"Melina","noOfItems":12},{"id":2,"name":"James","noOfItems":5},{"id":3,"name":"Anne","noOfItems":20}].toString()); } function testReadonlyTable2() { - CustomerX c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerX c2 = {id: 2, name: "James", noOfItems: 5}; - CustomerX c3 = {id: 3, name: "Anne", noOfItems: 20}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c3 = {id: 3, name: "Anne", noOfItems: 20}; - CustomerX[] customerList1 = [c1, c2, c3]; + Customer[] customerList1 = [c1, c2, c3]; - CustomerTableX & readonly customerTable1 = table key(id, name) from var customer in customerList1 + CustomerTable & readonly customerTable1 = table key(id, name) from var customer in customerList1 select { id: customer.id, name: customer.name, noOfItems: customer.noOfItems }; - any _ = customerTable1; + any _ = customerTable1; assertEqual((typeof customerTable1).toString(), "typedesc [{\"id\":1,\"name\":\"Melina\",\"noOfItems\":12},{\"id\":2,\"name\":\"James\",\"noOfItems\":5},{\"id\":3,\"name\":\"Anne\",\"noOfItems\":20}]"); - assertEqual(customerTable1.toString(), [{"id": 1, "name": "Melina", "noOfItems": 12}, {"id": 2, "name": "James", "noOfItems": 5}, {"id": 3, "name": "Anne", "noOfItems": 20}].toString()); + assertEqual(customerTable1.toString(), [{"id":1,"name":"Melina","noOfItems":12},{"id":2,"name":"James","noOfItems":5},{"id":3,"name":"Anne","noOfItems":20}].toString()); - CustomerX[] customerList2 = [c1, c2, c3]; + Customer[] customerList2 = [c1, c2, c3]; - CustomerTableX & readonly|error customerTable2 = table key(id, name) from var customer in customerList2 - select customer.cloneReadOnly() - on conflict error("Error"); - any _ = (checkpanic customerTable2); - assertEqual((typeof (checkpanic customerTable2)).toString(), "typedesc [{\"id\":1,\"name\":\"Melina\",\"noOfItems\":12},{\"id\":2,\"name\":\"James\",\"noOfItems\":5},{\"id\":3,\"name\":\"Anne\",\"noOfItems\":20}]"); - assertEqual((checkpanic customerTable2).toString(), [{"id": 1, "name": "Melina", "noOfItems": 12}, {"id": 2, "name": "James", "noOfItems": 5}, {"id": 3, "name": "Anne", "noOfItems": 20}].toString()); + CustomerTable & readonly|error customerTable2 = table key(id, name) from var customer in customerList2 + select customer.cloneReadOnly() on conflict error("Error"); + any _ = (checkpanic customerTable2); + assertEqual((typeof(checkpanic customerTable2)).toString(), "typedesc [{\"id\":1,\"name\":\"Melina\",\"noOfItems\":12},{\"id\":2,\"name\":\"James\",\"noOfItems\":5},{\"id\":3,\"name\":\"Anne\",\"noOfItems\":20}]"); + assertEqual((checkpanic customerTable2).toString(), [{"id":1,"name":"Melina","noOfItems":12},{"id":2,"name":"James","noOfItems":5},{"id":3,"name":"Anne","noOfItems":20}].toString()); - CustomerTableX customerTable3 = table key(id, name) from var customer in customerList2 + CustomerTable customerTable3 = table key(id, name) from var customer in customerList2 select { id: customer.id, name: customer.name, noOfItems: customer.noOfItems - } - on conflict (); - assertEqual((typeof (customerTable3)).toString(), "typedesc table key(id, name)"); - assertEqual(customerTable3.toString(), [{"id": 1, "name": "Melina", "noOfItems": 12}, {"id": 2, "name": "James", "noOfItems": 5}, {"id": 3, "name": "Anne", "noOfItems": 20}].toString()); + } on conflict (); + assertEqual((typeof(customerTable3)).toString(), "typedesc table key(id, name)"); + assertEqual(customerTable3.toString(), [{"id":1,"name":"Melina","noOfItems":12},{"id":2,"name":"James","noOfItems":5},{"id":3,"name":"Anne","noOfItems":20}].toString()); } type IdRec record {| @@ -1472,89 +1420,76 @@ type IdRec record {| |}; function testReadonlyTable3() { - table key(id) & readonly|error tbl = table key(id) from var i in [1, 2, 3, 4, 2, 3] - select { - id: i - } - on conflict (); + table key(id) & readonly|error tbl = table key(id) from var i in [1, 2, 3, 4, 2, 3] + select { + id: i + } on conflict (); - assertEqual((typeof (tbl)).toString(), "typedesc [{\"id\":1},{\"id\":2},{\"id\":3},{\"id\":4}]"); - assertEqual(tbl, table key(id) [ - {"id": 1}, - {"id": 2}, - {"id": 3}, - {"id": 4} - ]); - - if tbl !is error { - IdRec? member1 = tbl[1]; - assertEqual(member1, {"id": 1}); - } + assertEqual((typeof(tbl)).toString(), "typedesc [{\"id\":1},{\"id\":2},{\"id\":3},{\"id\":4}]"); + assertEqual(tbl, table key(id) [{"id":1},{"id":2},{"id":3},{"id":4}]); - table & readonly tbl2 = table key() from var i in [1, 2, 3, 4, 2, 3] - select { - id: i - }; + if tbl !is error { + IdRec? member1 = tbl[1]; + assertEqual(member1, {"id":1}); + } + + table & readonly tbl2 = table key() from var i in [1, 2, 3, 4, 2, 3] + select { + id: i + }; - assertEqual((typeof (tbl2)).toString(), "typedesc [{\"id\":1},{\"id\":2},{\"id\":3},{\"id\":4},{\"id\":2},{\"id\":3}]"); - assertEqual(tbl2, table key() [ - {"id": 1}, - {"id": 2}, - {"id": 3}, - {"id": 4}, - {"id": 2}, - {"id": 3} - ]); + assertEqual((typeof(tbl2)).toString(), "typedesc [{\"id\":1},{\"id\":2},{\"id\":3},{\"id\":4},{\"id\":2},{\"id\":3}]"); + assertEqual(tbl2, table key() [{"id":1},{"id":2},{"id":3},{"id":4},{"id":2},{"id":3}]); } function testConstructingListOfTablesUsingQueryWithReadonly() { - table key(id) & readonly users1 = table [ + table key(id) & readonly users1 = table [ {id: 1, firstName: "John", lastName: "Doe", age: 25} ]; - (table key(id))[] uList = [users1]; + (table key(id))[] uList = [users1]; - (table key(id))[] & readonly result = from var user in uList - select user.cloneReadOnly(); - assertEqual((typeof (result)).toString(), "typedesc [[{\"id\":1,\"firstName\":\"John\",\"lastName\":\"Doe\",\"age\":25}]]"); - assertEqual(result, [table key(id) [{"id": 1, "firstName": "John", "lastName": "Doe", "age": 25}]]); + (table key(id))[] & readonly result = from var user in uList + select user.cloneReadOnly(); + assertEqual((typeof(result)).toString(), "typedesc [[{\"id\":1,\"firstName\":\"John\",\"lastName\":\"Doe\",\"age\":25}]]"); + assertEqual(result, [table key(id) [{"id":1,"firstName":"John","lastName":"Doe","age":25}]]); } function testConstructingListOfRecordsUsingQueryWithReadonly() { - EmployeeX emp1 = {firstName: "A1", lastName: "B1", dept: "C1"}; - EmployeeX emp2 = {firstName: "A2", lastName: "B2", dept: "C2"}; - EmployeeX emp3 = {firstName: "A3", lastName: "B3", dept: "C3"}; + Employee emp1 = {firstName: "A1", lastName: "B1", dept: "C1"}; + Employee emp2 = {firstName: "A2", lastName: "B2", dept: "C2"}; + Employee emp3 = {firstName: "A3", lastName: "B3", dept: "C3"}; - (EmployeeX & readonly)[] & readonly result = from var user in [emp1, emp2, emp3] - select user.cloneReadOnly(); - assertEqual((typeof (result)).toString(), "typedesc [{\"firstName\":\"A1\",\"lastName\":\"B1\",\"dept\":\"C1\"},{\"firstName\":\"A2\",\"lastName\":\"B2\",\"dept\":\"C2\"},{\"firstName\":\"A3\",\"lastName\":\"B3\",\"dept\":\"C3\"}]"); - assertEqual(result, [{"firstName": "A1", "lastName": "B1", "dept": "C1"}, {"firstName": "A2", "lastName": "B2", "dept": "C2"}, {"firstName": "A3", "lastName": "B3", "dept": "C3"}]); + (Employee & readonly)[] & readonly result = from var user in [emp1, emp2, emp3] + select user.cloneReadOnly(); + assertEqual((typeof(result)).toString(), "typedesc [{\"firstName\":\"A1\",\"lastName\":\"B1\",\"dept\":\"C1\"},{\"firstName\":\"A2\",\"lastName\":\"B2\",\"dept\":\"C2\"},{\"firstName\":\"A3\",\"lastName\":\"B3\",\"dept\":\"C3\"}]"); + assertEqual(result, [{"firstName":"A1","lastName":"B1","dept":"C1"},{"firstName":"A2","lastName":"B2","dept":"C2"},{"firstName":"A3","lastName":"B3","dept":"C3"}]); } function testConstructingListOfXMLsUsingQueryWithReadonly() { xml a = xml ` 1 John `; (xml & readonly)[] & readonly result = from var user in a - select user.cloneReadOnly(); - assertEqual((typeof (result)).toString(), "typedesc [` 1 `,` `,` John `]"); - assertEqual(result, [xml ` 1 `, xml ` `, xml ` John `]); + select user.cloneReadOnly(); + assertEqual((typeof(result)).toString(), "typedesc [` 1 `,` `,` John `]"); + assertEqual(result, [xml` 1 `,xml` `,xml` John `]); } type Type1 int[]|string; function testConstructingListOfListsUsingQueryWithReadonly() { Type1[] & readonly result = from var user in [[1, 2], "a", "b", [-1, int:MAX_VALUE]] - select user.cloneReadOnly(); - assertEqual((typeof (result)).toString(), "typedesc [[1,2],\"a\",\"b\",[-1,9223372036854775807]]"); - assertEqual(result, [[1, 2], "a", "b", [-1, 9223372036854775807]]); + select user.cloneReadOnly(); + assertEqual((typeof(result)).toString(), "typedesc [[1,2],\"a\",\"b\",[-1,9223372036854775807]]"); + assertEqual(result, [[1,2],"a","b",[-1,9223372036854775807]]); } function testConstructingListOfMapsUsingQueryWithReadonly() { map[] & readonly result = from var item in [[1, 2], "a", "b", [-1, int:MAX_VALUE]] - select {item: item}.cloneReadOnly(); + select {item: item}.cloneReadOnly(); - assertEqual((typeof (result)).toString(), "typedesc [{\"item\":[1,2]},{\"item\":\"a\"},{\"item\":\"b\"},{\"item\":[-1,9223372036854775807]}]"); - assertEqual(result, [{"item": [1, 2]}, {"item": "a"}, {"item": "b"}, {"item": [-1, 9223372036854775807]}]); + assertEqual((typeof(result)).toString(), "typedesc [{\"item\":[1,2]},{\"item\":\"a\"},{\"item\":\"b\"},{\"item\":[-1,9223372036854775807]}]"); + assertEqual(result, [{"item":[1,2]},{"item":"a"},{"item":"b"},{"item":[-1,9223372036854775807]}]); } type T record { @@ -1562,9 +1497,8 @@ type T record { }; function testConstructingListInRecordsUsingQueryWithReadonly() { - T rec1 = {params: from var s in ["a", "b", "c", "abc"] - select s}; - assertEqual(rec1, {"params": ["a", "b", "c", "abc"]}); + T rec1 = { params: from var s in ["a", "b", "c", "abc"] select s }; + assertEqual(rec1, {"params":["a","b","c","abc"]}); } type DepartmentDetails record { @@ -1579,77 +1513,69 @@ type ErrorOrImmutableMapOfInt ImmutableMapOfInt|error; function testReadonlyMap1() { map & readonly mp1 = map from var item in [["1", 1], ["2", 2], ["3", 3], ["4", 4]] - select item; - any _ = mp1; - assertEqual((typeof (mp1)).toString(), "typedesc {\"1\":1,\"2\":2,\"3\":3,\"4\":4}"); - assertEqual(mp1, {"1": 1, "2": 2, "3": 3, "4": 4}); + select item; + any _ = mp1; + assertEqual((typeof(mp1)).toString(), "typedesc {\"1\":1,\"2\":2,\"3\":3,\"4\":4}"); + assertEqual(mp1, {"1":1,"2":2,"3":3,"4":4}); ImmutableMapOfInt mp2 = map from var item in [["1", 1], ["2", 2], ["3", 3], ["4", 4]] - select item; - any _ = mp2; - assertEqual((typeof (mp2)).toString(), "typedesc {\"1\":1,\"2\":2,\"3\":3,\"4\":4}"); - assertEqual(mp2, {"1": 1, "2": 2, "3": 3, "4": 4}); + select item; + any _ = mp2; + assertEqual((typeof(mp2)).toString(), "typedesc {\"1\":1,\"2\":2,\"3\":3,\"4\":4}"); + assertEqual(mp2, {"1":1,"2":2,"3":3,"4":4}); + ImmutableMapOfDept mp3 = map from var item in ["ABC", "DEF", "XY"] - let DepartmentDetails & readonly dept = {dept: item} - select [item, dept]; - any _ = mp3; - assertEqual((typeof (mp3)).toString(), "typedesc {\"ABC\":{\"dept\":\"ABC\"},\"DEF\":{\"dept\":\"DEF\"},\"XY\":{\"dept\":\"XY\"}}"); - assertEqual(mp3, {"ABC": {"dept": "ABC"}, "DEF": {"dept": "DEF"}, "XY": {"dept": "XY"}}); + let DepartmentDetails & readonly dept = {dept: item} + select [item, dept]; + any _ = mp3; + assertEqual((typeof(mp3)).toString(), "typedesc {\"ABC\":{\"dept\":\"ABC\"},\"DEF\":{\"dept\":\"DEF\"},\"XY\":{\"dept\":\"XY\"}}"); + assertEqual(mp3, {"ABC":{"dept":"ABC"},"DEF":{"dept":"DEF"},"XY":{"dept":"XY"}}); ErrorOrImmutableMapOfInt mp4 = map from var item in [["1", 1], ["2", 2], ["3", 3], ["4", 4]] - where item[1] > 1 - select item; - any _ = (checkpanic mp4); - assertEqual((typeof (mp4)).toString(), "typedesc {\"2\":2,\"3\":3,\"4\":4}"); - assertEqual(mp4, {"2": 2, "3": 3, "4": 4}); + where item[1] > 1 + select item; + any _ = (checkpanic mp4); + assertEqual((typeof(mp4)).toString(), "typedesc {\"2\":2,\"3\":3,\"4\":4}"); + assertEqual(mp4, {"2":2,"3":3,"4":4}); [string:Char, int[]][] & readonly list = [["a", [1, 2]], ["b", [3, 4]], ["c", [4]], ["c", [3]]]; - map|error mp5 = map from var item in list - select item; - assertEqual(mp5, {"a": [1, 2], "b": [3, 4], "c": [3]}); - - map & readonly|error mp6 = map from var item in list - select item; - assertEqual(mp6, {"a": [1, 2], "b": [3, 4], "c": [3]}); - any _ = (checkpanic mp6); - - map & readonly|error mp7 = map from var item in list - select item - on conflict error("Error"); + map|error mp5 = map from var item in list select item; + assertEqual(mp5, {"a":[1,2],"b":[3,4],"c":[3]}); + + map & readonly|error mp6 = map from var item in list select item; + assertEqual(mp6, {"a":[1,2],"b":[3,4],"c":[3]}); + any _ = (checkpanic mp6); + + map & readonly|error mp7 = map from var item in list select item on conflict error("Error"); assertEqual(mp7, error("Error")); } function testReadonlyMap2() { map & readonly mp1 = map from var item in [["1", 1], ["2", 2], ["2", 3], ["4", 4]] - select [item[0], item[1] * 2] - on conflict (); - assertEqual(mp1, {"1": 2, "2": 6, "4": 8}); + select [item[0], item[1] * 2] on conflict (); + assertEqual(mp1, {"1":2,"2":6,"4":8}); ImmutableMapOfInt|error mp2 = map from var item in [["1", 1], ["2", 2], ["2", 3], ["4", 4]] - select item - on conflict error("Error 1"); + select item on conflict error("Error 1"); assertEqual(mp2, error("Error 1")); error? conflictMsg = error("Error 2"); ImmutableMapOfDept|error mp3 = map from var item in ["ABC", "DEF", "XY", "ABC"] - let DepartmentDetails & readonly dept = {dept: item} - select [item, dept] - on conflict conflictMsg; + let DepartmentDetails & readonly dept = {dept: item} + select [item, dept] on conflict conflictMsg; assertEqual(mp3, error("Error 2")); conflictMsg = null; ErrorOrImmutableMapOfInt mp4 = map from var item in [["1", 1], ["2", 2], ["3", 3], ["1", 4]] - where item[1] > 1 - select item - on conflict conflictMsg; - assertEqual(mp4, {"2": 2, "3": 3, "1": 4}); + where item[1] > 1 + select item on conflict conflictMsg; + assertEqual(mp4, {"2":2,"3":3,"1":4}); } class EvenNumberGenerator { int i = 0; - - public isolated function next() returns record {|int value;|}|error { + public isolated function next() returns record {| int value; |}|error { return error("Greater than 20!"); } } @@ -1664,19 +1590,19 @@ type NumberRecord record {| |}; function testQueryConstructingMapsAndTablesWithClausesMayCompleteSEarlyWithError() { - EvenNumberGenerator evenGen = new (); - stream evenNumberStream = new (evenGen); + EvenNumberGenerator evenGen = new(); + stream evenNumberStream = new(evenGen); map|error map1 = map from var item in evenNumberStream - select [item.toBalString(), item]; + select [item.toBalString(), item]; assertEqual(map1, error("Greater than 20!")); table|error table1 = table key() from var item in evenNumberStream - select {value: item}; + select {value: item}; assertEqual(table1, error("Greater than 20!")); table key(id)|error table2 = table key(id) from var item in evenNumberStream - select {id: item, value: item.toBalString()}; + select {id: item, value: item.toBalString()}; assertEqual(table2, error("Greater than 20!")); // Enable following tests after fixing issue - lang/#36746 @@ -1699,18 +1625,16 @@ function testQueryConstructingMapsAndTablesWithClausesMayCompleteSEarlyWithError // assertEqual(table4, error("Greater than 20!")); map|error map3 = map from var firstNo in [1, 4, 4, 10] - select [firstNo.toBalString(), firstNo] - on conflict error("Error"); + select [firstNo.toBalString(), firstNo] on conflict error("Error"); assertEqual(map3, error("Error")); table key(id)|error table6 = table key(id) from var firstNo in [1, 4, 4, 10] - select {id: firstNo, value: firstNo.toBalString()} - on conflict error("Error"); + select {id: firstNo, value: firstNo.toBalString()} on conflict error("Error"); assertEqual(table6, error("Error")); } function testQueryConstructingMapWithOnConflictsWithVarRef() { - map|error mp1 = map from int i in [1, 2, 3, 1, 2, 3] + map|error mp1 = map from int i in [1, 2, 3, 1, 2, 3] let string value = "A" + i.toString() select [i.toString(), value] on conflict error(string `Duplicate Key: ${i} Value: ${value}`); @@ -1728,124 +1652,98 @@ function testQueryConstructingMapWithOnConflictsWithVarRef() { } function testQueryConstructingMapsAndTablesWithClausesMayCompleteSEarlyWithError2() { - EvenNumberGenerator evenGen = new (); - stream evenNumberStream = new (evenGen); + EvenNumberGenerator evenGen = new(); + stream evenNumberStream = new(evenGen); - map|error map1 = map from var item in (stream from var integer in evenNumberStream - select integer) - select [item.toBalString(), item]; + map|error map1 = map from var item in (stream from var integer in evenNumberStream select integer) + select [item.toBalString(), item]; assertEqual(map1, error("Greater than 20!")); - table|error table1 = table key() from var item in (stream from var integer in evenNumberStream - select integer) - select {value: item}; + table|error table1 = table key() from var item in (stream from var integer in evenNumberStream select integer) + select {value: item}; assertEqual(table1, error("Greater than 20!")); - table key(id)|error table2 = table key(id) from var item in (stream from var integer in evenNumberStream - select integer) - select {id: item, value: item.toBalString()}; + table key(id)|error table2 = table key(id) from var item in (stream from var integer in evenNumberStream select integer) + select {id: item, value: item.toBalString()}; assertEqual(table2, error("Greater than 20!")); - map|error map3 = map from var item in (stream from var integer in (stream from var integer in evenNumberStream - select integer) - select integer) - select [item.toBalString(), item]; + map|error map3 = map from var item in (stream from var integer in (stream from var integer in evenNumberStream select integer) select integer) + select [item.toBalString(), item]; assertEqual(map3, error("Greater than 20!")); table|error table4 = table key() from var item in - (stream from var integer in (stream from var integer in evenNumberStream - select integer) - select integer) - select {value: item}; + (stream from var integer in (stream from var integer in evenNumberStream select integer) select integer) + select {value: item}; assertEqual(table4, error("Greater than 20!")); } type FooBar1 ("foo"|"bar"|string)[2]; - type FooBar2 ("foo"|"bar")[2]; - type FooBar3 "foo"|"bar"; - type FooBar4 "foo"|"bar"|string:Char; - type FooBar5 "foo"|"bar"|string; function testMapConstructingQueryExprWithStringSubtypes() { FooBar1[] list1 = [["key1", "foo"], ["key2", "foo"], ["key3", "foo"]]; - map|error mp1 = map from var item in list1 - select item; - assertEqual(mp1, {"key1": "foo", "key2": "foo", "key3": "foo"}); + map|error mp1 = map from var item in list1 select item; + assertEqual(mp1, {"key1":"foo","key2":"foo","key3":"foo"}); FooBar2[] list2 = [["foo", "foo"], ["bar", "foo"], ["foo", "foo"]]; - map|error mp2 = map from var item in list2 - select item; - assertEqual(mp2, {"foo": "foo", "bar": "foo"}); + map|error mp2 = map from var item in list2 select item; + assertEqual(mp2, {"foo":"foo","bar":"foo"}); FooBar3[][2] list3 = [["foo", "bar"], ["bar", "foo"], ["foo", "bar"]]; - map|error mp3 = map from var item in list3 - select item; - assertEqual(mp3, {"foo": "bar", "bar": "foo"}); + map|error mp3 = map from var item in list3 select item; + assertEqual(mp3, {"foo":"bar","bar":"foo"}); FooBar4[][2] list4 = [["foo", "4"], ["bar", "2"], ["foo", "3"]]; - map|error mp4 = map from var item in list4 - select item; - assertEqual(mp4, {"foo": "3", "bar": "2"}); - map|error mp5 = map from var item in list4 - select item - on conflict error("Error"); + map|error mp4 = map from var item in list4 select item; + assertEqual(mp4, {"foo":"3","bar":"2"}); + map|error mp5 = map from var item in list4 select item on conflict error("Error"); assertEqual(mp5, error("Error")); FooBar5[][2] list5 = [["key1", "1.4"], ["key2", "2"], ["key3", "3"]]; - map|error mp6 = map from var item in list5 - select item; - assertEqual(mp6, {"key1": "1.4", "key2": "2", "key3": "3"}); + map|error mp6 = map from var item in list5 select item; + assertEqual(mp6, {"key1":"1.4","key2":"2","key3":"3"}); [FooBar3, int|float][] list6 = [["foo", 1.4], ["bar", 2], ["foo", 3]]; - map|error mp7 = map from var item in list6 - select item; - assertEqual(mp7, {"foo": 3, "bar": 2}); - map|error mp8 = map from var item in list6 - select item - on conflict error("Error"); + map|error mp7 = map from var item in list6 select item; + assertEqual(mp7, {"foo":3,"bar":2}); + map|error mp8 = map from var item in list6 select item on conflict error("Error"); assertEqual(mp8, error("Error")); [FooBar4, int|float][] list7 = [["foo", 1.4], ["bar", 2], ["foo", 3]]; - map|error mp9 = map from var item in list7 - select item; - assertEqual(mp9, {"foo": 3, "bar": 2}); - map|error mp10 = map from var item in list7 - select item - on conflict error("Error"); + map|error mp9 = map from var item in list7 select item; + assertEqual(mp9, {"foo":3,"bar":2}); + map|error mp10 = map from var item in list7 select item on conflict error("Error"); assertEqual(mp10, error("Error")); [FooBar5, int|float][] list8 = [["key1", 1.4], ["key2", 2], ["key3", 3]]; - map|error mp11 = map from var item in list8 - select item; - assertEqual(mp11, {"key1": 1.4, "key2": 2, "key3": 3}); + map|error mp11 = map from var item in list8 select item; + assertEqual(mp11, {"key1":1.4,"key2":2,"key3":3}); } function testDiffQueryConstructsUsedAsFuncArgs() returns error? { - CustomerX c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerX c2 = {id: 2, name: "James", noOfItems: 5}; - CustomerX c3 = {id: 3, name: "Anne", noOfItems: 20}; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c3 = {id: 3, name: "Anne", noOfItems: 20}; - CustomerX[] customerList = [c1, c2, c3]; + Customer[] customerList = [c1, c2, c3]; int tblLength = getTableLength(table key(id, name) from var customer in customerList - select { - id: customer.id, - name: customer.name, - noOfItems: customer.noOfItems - }); + select { + id: customer.id, + name: customer.name, + noOfItems: customer.noOfItems + }); assertEqual(tblLength, 3); FooBar1[] list1 = [["key1", "foo"], ["key2", "foo"], ["key3", "foo"]]; - int mapLength = getMapLength(map from var item in list1 - select item); + int mapLength = getMapLength(map from var item in list1 select item); assertEqual(mapLength, 3); } -function getTableLength(CustomerTableX tbl) returns int { +function getTableLength(CustomerTable tbl) returns int { return tbl.length(); } @@ -1939,9 +1837,9 @@ function testJoinedQueryExprConstructingMapWithRegExp() { let string:RegExp a = re `AB*(A|B|[ab-fgh]+(?im-x:[cdeg-k]??${v})|)|^|PQ?` select [re1.toString() + "1", re1.toString() + a.toString()]; assertEqual({ - A1: "AAB*(A|B|[ab-fgh]+(?im-x:[cdeg-k]??1)|)|^|PQ?", - B1: "BAB*(A|B|[ab-fgh]+(?im-x:[cdeg-k]??1)|)|^|PQ?" - }, arr3); + A1: "AAB*(A|B|[ab-fgh]+(?im-x:[cdeg-k]??1)|)|^|PQ?", + B1: "BAB*(A|B|[ab-fgh]+(?im-x:[cdeg-k]??1)|)|^|PQ?" + }, arr3); } type ModuleDecls [string, FuncDecl...]; @@ -1968,69 +1866,67 @@ function testInnerQueryConstructedWithCEP() { select [name, sig] ]; - assertEqual([["01", ["func1", ["foo", ["int", "string"], "boolean"]]], ["02"]], decl); + assertEqual([["01",["func1",["foo",["int","string"],"boolean"]]],["02"]], decl); } error onConflictError = error("Key Conflict", message = "cannot insert."); function testTableConstructQueryWithNonConflictingKeys() { - CustomerX c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerX c2 = {id: 2, name: "James", noOfItems: 5}; - CustomerX c3 = {id: 3, name: "Anne", noOfItems: 20}; - CustomerX[] customerList = [c1, c2, c3]; - CustomerTableX|error customerTable = getQueryResult(onConflictError, customerList); - assertEqual(true, customerTable is CustomerTableX); - CustomerTableX expectedTableValue = table [ - {id: 1, name: "Melina", noOfItems: 12}, - {id: 2, name: "James", noOfItems: 5}, - {id: 3, name: "Anne", noOfItems: 20} - ]; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c3 = {id: 3, name: "Anne", noOfItems: 20}; + Customer[] customerList = [c1, c2, c3]; + CustomerTable|error customerTable = getQueryResult(onConflictError, customerList); + assertEqual(true, customerTable is CustomerTable); + CustomerTable expectedTableValue = table [{id: 1, name: "Melina", noOfItems: 12}, + {id: 2, name: "James", noOfItems: 5}, + {id: 3, name: "Anne", noOfItems: 20}]; assertEqual(customerTable, expectedTableValue); } function testTableConstructQueryWithConflictingKeys() { - CustomerX c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerX c2 = {id: 2, name: "James", noOfItems: 5}; - CustomerX c3 = {id: 3, name: "Anne", noOfItems: 20}; - CustomerX[] customerList = [c1, c2, c3, c1]; - CustomerTableX|error customerTable = getQueryResult(onConflictError, customerList); + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c3 = {id: 3, name: "Anne", noOfItems: 20}; + Customer[] customerList = [c1, c2, c3, c1]; + CustomerTable|error customerTable = getQueryResult(onConflictError, customerList); assertEqual(customerTable is error, true); assertEqual((customerTable).message(), "Key Conflict"); } -function getQueryResult(error onConflictError, CustomerX[] customerList) returns CustomerTableX|error { - return table key(id, name) from var customer in customerList - select { +function getQueryResult(error onConflictError, Customer[] customerList) returns CustomerTable|error { + return table key(id, name) from var customer in customerList + select { id: customer.id, name: customer.name, noOfItems: customer.noOfItems - } - on conflict onConflictError; + } + on conflict onConflictError; } function testMapConstructNestedQueryWithConflictingKeys() { - CustomerX c1 = {id: 1, name: "Melina", noOfItems: 12}; - CustomerX c2 = {id: 2, name: "James", noOfItems: 5}; - CustomerX c3 = {id: 3, name: "Anne", noOfItems: 20}; - CustomerX[] customerList = [c1, c2, c3, c1]; + Customer c1 = {id: 1, name: "Melina", noOfItems: 12}; + Customer c2 = {id: 2, name: "James", noOfItems: 5}; + Customer c3 = {id: 3, name: "Anne", noOfItems: 20}; + Customer[] customerList = [c1, c2, c3, c1]; (anydata|error)[] result = from var i in [1] select table key(id, name) from var customer in customerList - select { - id: customer.id, - name: customer.name, - noOfItems: customer.noOfItems - } - on conflict error(string `Error key: ${customer.id} iteration: ${i}`); + select { + id: customer.id, + name: customer.name, + noOfItems: customer.noOfItems + } + on conflict error(string `Error key: ${customer.id} iteration: ${i}`); assertEqual(result[0] is error, true); assertEqual((result[0]).message(), "Error key: 1 iteration: 1"); } function testMapConstructQueryWithConflictingKeys() { - CustomerX c1 = {id: 1, name: "Abba", noOfItems: 10}; - CustomerX c2 = {id: 2, name: "Jim", noOfItems: 20}; - CustomerX c3 = {id: 3, name: "James", noOfItems: 30}; - CustomerX c4 = {id: 3, name: "Abba", noOfItems: 40}; - CustomerX[] customerList = [c1, c2, c3, c4]; + Customer c1 = {id: 1, name: "Abba", noOfItems: 10}; + Customer c2 = {id: 2, name: "Jim", noOfItems: 20}; + Customer c3 = {id: 3, name: "James", noOfItems: 30}; + Customer c4 = {id: 3, name: "Abba", noOfItems: 40}; + Customer[] customerList = [c1, c2, c3, c4]; anydata|error result = map from var {name, noOfItems} in customerList group by name select [name, [noOfItems]] diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/query/simple-query-with-defined-type.bal b/tests/jballerina-unit-test/src/test/resources/test-src/query/simple-query-with-defined-type.bal index 344c163bc83b..10b35e903ead 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/query/simple-query-with-defined-type.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/query/simple-query-with-defined-type.bal @@ -14,7 +14,7 @@ // specific language governing permissions and limitations // under the License. -type PersonK record {| +type Person record {| string firstName; string lastName; int age; @@ -33,35 +33,35 @@ type Employee record {| |}; type Person1 record {| - string firstName; - string lastName; - string deptAccess; - Address address; + string firstName; + string lastName; + string deptAccess; + Address address; |}; -type Address record {| +type Address record{| string city; string country; |}; -type Student record {| +type Student record{| string firstName; string lastName; float score; |}; -type Teacher1 record { - //record type referencing - *Person1; - Student[] classStudents?; - //anonymous record type - record {| - int duration; - string qualitifications; - |} experience; +type Teacher1 record{ + //record type referencing + *Person1; + Student[] classStudents?; + //anonymous record type + record {| + int duration; + string qualitifications; + |} experience; }; -type Subscription record {| +type Subscription record{| string firstName; string lastName; float score; @@ -70,7 +70,6 @@ type Subscription record {| class NumberGenerator { int i = 0; - public isolated function next() returns record {|int value;|}|error? { //closes the stream after 5 events if (self.i == 5) { @@ -83,7 +82,6 @@ class NumberGenerator { class NumberGeneratorWithError { int i = 0; - public isolated function next() returns record {|int value;|}|error? { if (self.i == 2) { return error("Custom error thrown explicitly."); @@ -95,7 +93,6 @@ class NumberGeneratorWithError { class NumberGeneratorWithError2 { int i = 0; - public isolated function next() returns record {|int value;|}|error { if (self.i == 2) { return error("Custom error thrown explicitly."); @@ -109,7 +106,6 @@ type ErrorR1 error>; class NumberGeneratorWithCustomError { int i = 0; - public isolated function next() returns record {|int value;|}|ErrorR1? { if (self.i == 3) { return error ErrorR1("Custom error", x = 1); @@ -120,10 +116,10 @@ class NumberGeneratorWithCustomError { } type ResultValue record {| - PersonK value; + Person value; |}; -function getRecordValue((record {|PersonK value;|}|error?)|(record {|PersonK value;|}?) returnedVal) returns PersonK? { +function getRecordValue((record {| Person value; |}|error?)|(record {| Person value; |}?) returnedVal) returns Person? { if (returnedVal is ResultValue) { return returnedVal.value; } else { @@ -131,97 +127,97 @@ function getRecordValue((record {|PersonK value;|}|error?)|(record {|PersonK val } } -function testSimpleSelectQueryWithSimpleVariable() returns PersonK[] { +function testSimpleSelectQueryWithSimpleVariable() returns Person[] { - PersonK p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonK p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonK p3 = {firstName: "John", lastName: "David", age: 33}; + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p3 = {firstName: "John", lastName: "David", age: 33}; - PersonK[] personList = [p1, p2, p3]; + Person[] personList = [p1, p2, p3]; - PersonK[] outputPersonList = + Person[] outputPersonList = from var person in personList - select { - firstName: person.firstName, - lastName: person.lastName, - age: person.age - }; + select { + firstName: person.firstName, + lastName: person.lastName, + age: person.age + }; return outputPersonList; } -function testSimpleSelectQueryWithRecordVariable() returns PersonK[] { +function testSimpleSelectQueryWithRecordVariable() returns Person[] { - PersonK p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonK p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonK p3 = {firstName: "John", lastName: "David", age: 33}; + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p3 = {firstName: "John", lastName: "David", age: 33}; - PersonK[] personList = [p1, p2, p3]; + Person[] personList = [p1, p2, p3]; - PersonK[] outputPersonList = - from var {firstName: nm1, lastName: nm2, age: a} in personList - select { - firstName: nm1, - lastName: nm2, - age: a - }; + Person[] outputPersonList = + from var { firstName: nm1, lastName: nm2, age: a } in personList + select { + firstName: nm1, + lastName: nm2, + age: a + }; return outputPersonList; } -function testSimpleSelectQueryWithRecordVariableV2() returns PersonK[] { +function testSimpleSelectQueryWithRecordVariableV2() returns Person[] { - PersonK p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonK p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonK p3 = {firstName: "John", lastName: "David", age: 33}; + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p3 = {firstName: "John", lastName: "David", age: 33}; - PersonK[] personList = [p1, p2, p3]; + Person[] personList = [p1, p2, p3]; - PersonK[] outputPersonList = - from var {firstName, lastName, age} in personList - select { - firstName: firstName, - lastName: lastName, - age: age - }; + Person[] outputPersonList = + from var { firstName, lastName, age } in personList + select { + firstName: firstName, + lastName: lastName, + age: age + }; return outputPersonList; } function testSimpleSelectQueryWithRecordVariableV3() returns Teacher[] { - PersonK p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonK p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonK p3 = {firstName: "John", lastName: "David", age: 33}; + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p3 = {firstName: "John", lastName: "David", age: 33}; - PersonK[] personList = [p1, p2, p3]; + Person[] personList = [p1, p2, p3]; Teacher[] outputPersonList = - from var {firstName, lastName, age} in personList - select { - firstName, - lastName - }; + from var { firstName, lastName, age } in personList + select { + firstName, + lastName + }; return outputPersonList; } -function testSimpleSelectQueryWithWhereClause() returns PersonK[] { +function testSimpleSelectQueryWithWhereClause() returns Person[] { - PersonK p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonK p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonK p3 = {firstName: "John", lastName: "David", age: 33}; + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p3 = {firstName: "John", lastName: "David", age: 33}; - PersonK[] personList = [p1, p2, p3]; + Person[] personList = [p1, p2, p3]; - PersonK[] outputPersonList = + Person[] outputPersonList = from var person in personList - where person.age >= 30 - select { - firstName: person.firstName, - lastName: person.lastName, - age: person.age - }; + where person.age >= 30 + select { + firstName: person.firstName, + lastName: person.lastName, + age: person.age + }; return outputPersonList; } @@ -231,8 +227,8 @@ function testQueryExpressionForPrimitiveType() returns boolean { int[] outputIntList = from var value in intList - where value > 20 - select value; + where value > 20 + select value; return outputIntList == [21, 25]; } @@ -243,123 +239,123 @@ function testQueryExpressionWithSelectExpression() returns boolean { string[] stringOutput = from var value in intList - select value.toString(); + select value.toString(); - return stringOutput == ["1", "2", "3"]; + return stringOutput == ["1","2", "3"]; } -function testFilteringNullElements() returns PersonK[] { +function testFilteringNullElements() returns Person[] { - PersonK p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonK p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonK?[] personList = [p1, (), p2]; + Person?[] personList = [p1, (), p2]; - PersonK[] outputPersonList = - from var person in personList - where (person is PersonK) - select { - firstName: person.firstName, - lastName: person.lastName, - age: person.age - }; + Person[] outputPersonList = + from var person in personList + where (person is Person) + select { + firstName: person.firstName, + lastName: person.lastName, + age: person.age + }; return outputPersonList; } function testMapWithArity() returns boolean { map m = {a: "1A", b: "2B", c: "3C", d: "4D"}; string[] val = from var v in m - where v == "1A" - select v; + where v == "1A" + select v; return val == ["1A"]; } function testJSONArrayWithArity() returns boolean { json[] jdata = [{name: "bob", age: 10}, {name: "tom", age: 16}]; string[] val = from var v in jdata - select checkpanic v.name; + select checkpanic v.name; return val == ["bob", "tom"]; } function testArrayWithTuple() returns boolean { [int, string][] arr = [[1, "A"], [2, "B"], [3, "C"]]; string[] val = from var [i, v] in arr - where i == 3 - select v; + where i == 3 + select v; return val == ["C"]; } -function testFromClauseWithStream() returns PersonK[] { - PersonK p1 = {firstName: "Alex", lastName: "George", age: 30}; - PersonK p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 40}; - PersonK p3 = {firstName: "John", lastName: "David", age: 50}; +function testFromClauseWithStream() returns Person[] { + Person p1 = {firstName: "Alex", lastName: "George", age: 30}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 40}; + Person p3 = {firstName: "John", lastName: "David", age: 50}; - PersonK[] personList = [p1, p2, p3]; - stream streamedPersons = personList.toStream(); + Person[] personList = [p1, p2, p3]; + stream streamedPersons = personList.toStream(); - PersonK[] outputPersonList = + Person[] outputPersonList = from var person in streamedPersons - where person.age == 40 - select person; + where person.age == 40 + select person; return outputPersonList; } function testSimpleSelectQueryWithLetClause() returns Employee[] { - PersonK p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonK p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonK p3 = {firstName: "John", lastName: "David", age: 33}; + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p3 = {firstName: "John", lastName: "David", age: 33}; - PersonK[] personList = [p1, p2, p3]; + Person[] personList = [p1, p2, p3]; Employee[] outputPersonList = from var person in personList - let string depName = "HR", string companyName = "WSO2" - where person.age >= 30 - select { - firstName: person.firstName, - lastName: person.lastName, - department: depName, - company: companyName - }; + let string depName = "HR", string companyName = "WSO2" + where person.age >= 30 + select { + firstName: person.firstName, + lastName: person.lastName, + department: depName, + company: companyName + }; return outputPersonList; } -function testFunctionCallInVarDeclLetClause() returns PersonK[] { +function testFunctionCallInVarDeclLetClause() returns Person[] { - PersonK p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonK p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonK[] personList = [p1, p2]; + Person[] personList = [p1, p2]; var outputPersonList = - from PersonK person in personList - let int twiceAge = mutiplyBy2(person.age) - select { - firstName: person.firstName, - lastName: person.lastName, - age: twiceAge - }; + from Person person in personList + let int twiceAge = mutiplyBy2(person.age) + select { + firstName: person.firstName, + lastName: person.lastName, + age: twiceAge + }; return outputPersonList; } -function testUseOfLetInWhereClause() returns PersonK[] { +function testUseOfLetInWhereClause() returns Person[] { - PersonK p1 = {firstName: "Alex", lastName: "George", age: 18}; - PersonK p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 22}; + Person p1 = {firstName: "Alex", lastName: "George", age: 18}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 22}; - PersonK[] personList = [p1, p2]; + Person[] personList = [p1, p2]; var outputPersonList = from var person in personList - let int twiceAge = mutiplyBy2(person.age) - where twiceAge > 40 - select { - firstName: person.firstName, - lastName: person.lastName, - age: twiceAge - }; + let int twiceAge = mutiplyBy2(person.age) + where twiceAge > 40 + select { + firstName: person.firstName, + lastName: person.lastName, + age: twiceAge + }; return outputPersonList; } @@ -373,8 +369,8 @@ public function testQueryWithStream() returns boolean { var numberStream = new stream(numGen); int[]|error oddNumberList = from int num in numberStream - where (num % 2 == 1) - select num; + where (num % 2 == 1) + select num; if (oddNumberList is error) { return false; } else { @@ -382,13 +378,14 @@ public function testQueryWithStream() returns boolean { } } + public function testQueryStreamWithError() { NumberGeneratorWithError numGen = new; var numberStream = new stream(numGen); int[]|error oddNumberList = from int num in numberStream - where (num % 2 == 1) - select num; + where (num % 2 == 1) + select num; if (oddNumberList is error) { return; } @@ -455,10 +452,10 @@ public function testQueryStreamWithDifferentCompletionTypes() { } } -function testOthersAssociatedWithRecordTypes() returns Teacher1[] { +function testOthersAssociatedWithRecordTypes() returns Teacher1[]{ - Person1 p1 = {firstName: "Alex", lastName: "George", deptAccess: "XYZ", address: {city: "NY", country: "America"}}; - Person1 p2 = {firstName: "Ranjan", lastName: "Fonseka", deptAccess: "XYZ", address: {city: "NY", country: "America"}}; + Person1 p1 = {firstName: "Alex", lastName: "George", deptAccess: "XYZ", address:{city:"NY", country:"America"}}; + Person1 p2 = {firstName: "Ranjan", lastName: "Fonseka", deptAccess: "XYZ", address:{city:"NY", country:"America"}}; Student s1 = {firstName: "Alex", lastName: "George", score: 82.5}; Student s2 = {firstName: "Ranjan", lastName: "Fonseka", score: 90.6}; @@ -467,142 +464,142 @@ function testOthersAssociatedWithRecordTypes() returns Teacher1[] { Student[] studentList = [s1, s2]; Teacher1[] outputteacherList = - from var person in personList - let int period = 10, string degree = "B.Sc." - select { - //change order of the record fields - firstName: person.firstName, - address: person.address, - //optional field - classStudents: studentList, - deptAccess: person.deptAccess, - //member access - lastName: person["lastName"], - //values for anonymous record fields - experience: { - duration: period, - qualitifications: degree - } - }; - - return outputteacherList; + from var person in personList + let int period = 10, string degree = "B.Sc." + select{ + //change order of the record fields + firstName:person.firstName, + address: person.address, + //optional field + classStudents: studentList, + deptAccess: person.deptAccess, + //member access + lastName:person["lastName"], + //values for anonymous record fields + experience: { + duration: period, + qualitifications: degree + } + }; + + return outputteacherList; } function testQueryExprTupleTypedBinding2() returns boolean { - [int, int][] arr1 = [[1, 2], [2, 3], [3, 4]]; - [int, int] arr2 = [1, 2]; + [int,int][] arr1 = [[1,2],[2,3],[3,4]]; + [int,int] arr2 = [1,2]; int[] ouputList = - from [int, int] [a, b] in arr1 - let [int, int] [d1, d2] = arr2, int x = d1 + d2 - where b > x - select a; + from [int,int] [a,b] in arr1 + let [int,int] [d1,d2] = arr2, int x=d1+d2 + where b > x + select a; - return ouputList == [3]; + return ouputList == [3]; } -function testQueryExprWithTypeConversion() returns Person1[] { +function testQueryExprWithTypeConversion() returns Person1[]{ - Person1 p1 = {firstName: "Alex", lastName: "George", deptAccess: "XYZ", address: {city: "NY", country: "America"}}; - Person1 p2 = {firstName: "Ranjan", lastName: "Fonseka", deptAccess: "XYZ", address: {city: "NY", country: "America"}}; + Person1 p1 = {firstName: "Alex", lastName: "George", deptAccess: "XYZ", address:{city:"NY", country:"America"}}; + Person1 p2 = {firstName: "Ranjan", lastName: "Fonseka", deptAccess: "XYZ", address:{city:"NY", country:"America"}}; - map m = {city: "New York", country: "America"}; + map m = {city:"New York", country:"America"}; - Person1[] personList = [p1, p2]; + Person1[] personList = [p1, p2]; - Person1[] outputPersonList = - from var person in personList - select { - firstName: person.firstName, - lastName: person.lastName, - deptAccess: person.deptAccess, - address: checkpanic m.cloneWithType(Address) - }; + Person1[] outputPersonList = + from var person in personList + select{ + firstName: person.firstName, + lastName: person.lastName, + deptAccess: person.deptAccess, + address: checkpanic m.cloneWithType(Address) + }; - return outputPersonList; + return outputPersonList; } -function testQueryExprWithStreamMapAndFilter() returns Subscription[] { +function testQueryExprWithStreamMapAndFilter() returns Subscription[]{ Student s1 = {firstName: "Alex", lastName: "George", score: 82.5}; Student s2 = {firstName: "Ranjan", lastName: "Fonseka", score: 90.6}; Student[] studentList = [s1, s2]; - Subscription[] outputSubscriptionList = - from var subs in >studentList.toStream().filter(function(Student student) returns boolean { - return student.score > 85.3; - }).'map(function(Student student) returns Subscription { - Subscription subscription = { - firstName: student.firstName, - lastName: student.lastName, - score: student.score, - degree: "Bachelor of Medicine" - }; - return subscription; - }) - select subs; + Subscription[] outputSubscriptionList = + from var subs in >studentList.toStream().filter(function (Student student) returns boolean { + return student.score > 85.3; + }).'map(function (Student student) returns Subscription { + Subscription subscription = { + firstName: student.firstName, + lastName: student.lastName, + score: student.score, + degree: "Bachelor of Medicine" + }; + return subscription; + }) + select subs; - return outputSubscriptionList; + return outputSubscriptionList; } function testSimpleSelectQueryReturnStream() returns boolean { boolean testPassed = true; - PersonK p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonK p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonK p3 = {firstName: "John", lastName: "David", age: 33}; + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p3 = {firstName: "John", lastName: "David", age: 33}; - PersonK[] personList = [p1, p2, p3]; + Person[] personList = [p1, p2, p3]; - stream outputPersonStream = stream from var person in personList - select { - firstName: person.firstName, - lastName: person.lastName, - age: person.age - }; - PersonK? returnedVal = getRecordValue(outputPersonStream.next()); - testPassed = testPassed && (returnedVal is PersonK) && (returnedVal == p1); + stream outputPersonStream = stream from var person in personList + select { + firstName: person.firstName, + lastName: person.lastName, + age: person.age + }; + Person? returnedVal = getRecordValue(outputPersonStream.next()); + testPassed = testPassed && (returnedVal is Person) && (returnedVal == p1); returnedVal = getRecordValue(outputPersonStream.next()); - testPassed = testPassed && (returnedVal is PersonK) && (returnedVal == p2); + testPassed = testPassed && (returnedVal is Person) && (returnedVal == p2); returnedVal = getRecordValue(outputPersonStream.next()); - testPassed = testPassed && (returnedVal is PersonK) && (returnedVal == p3); + testPassed = testPassed && (returnedVal is Person) && (returnedVal == p3); return testPassed; } function testQueryWithRecordVarInLetClause() returns Person1[] { - PersonK p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonK p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonK p3 = {firstName: "John", lastName: "David", age: 33}; + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p3 = {firstName: "John", lastName: "David", age: 33}; Address address = {city: "Colombo", country: "SL"}; - PersonK[] personList = [p1, p2, p3]; + Person[] personList = [p1, p2, p3]; var outputPersonList = from var person in personList - let Address {city: town, country: state} = address - where person.age >= 30 - select { - firstName: person.firstName, - lastName: person.lastName, - deptAccess: "XYZ", - address: {city: town, country: state} - }; + let Address {city: town, country: state } = address + where person.age >= 30 + select { + firstName: person.firstName, + lastName: person.lastName, + deptAccess: "XYZ", + address: {city: town, country: state} + }; return outputPersonList; } function testForeachStream() returns boolean { - PersonK p1 = {firstName: "Alex", lastName: "George", age: 30}; - PersonK p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 40}; - PersonK p3 = {firstName: "John", lastName: "David", age: 50}; + Person p1 = {firstName: "Alex", lastName: "George", age: 30}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 40}; + Person p3 = {firstName: "John", lastName: "David", age: 50}; - PersonK[] personList = [p1, p2, p3]; - stream streamedPersons = personList.toStream(); + Person[] personList = [p1, p2, p3]; + stream streamedPersons = personList.toStream(); - PersonK[] outputPersonList = []; - foreach PersonK person in streamedPersons { + Person[] outputPersonList = []; + foreach Person person in streamedPersons { if (person.age == 40) { outputPersonList.push(person); } @@ -617,8 +614,8 @@ function testForeachStream() returns boolean { function testTypeTestInWhereClause() { int?[] v = [1, 2, (), 3]; int[] result = from var i in v - where i is int - select i; + where i is int + select i; assertEquality(3, result.length()); assertEquality(1, result[0]); assertEquality(2, result[1]); @@ -721,16 +718,16 @@ function testJoinedQueryExprWithRegExp() { let string:RegExp a = re `AB*[^abc-efg](?:A|B|[ab-fgh]+(?im-x:[cdeg-k]??${v})|)|^|PQ?` select re1.toString() + a.toString(); assertEquality(true, [ - "AAB*[^abc-efg](?:A|B|[ab-fgh]+(?im-x:[cdeg-k]??1)|)|^|PQ?", - "BAB*[^abc-efg](?:A|B|[ab-fgh]+(?im-x:[cdeg-k]??1)|)|^|PQ?" - ] == arr3); + "AAB*[^abc-efg](?:A|B|[ab-fgh]+(?im-x:[cdeg-k]??1)|)|^|PQ?", + "BAB*[^abc-efg](?:A|B|[ab-fgh]+(?im-x:[cdeg-k]??1)|)|^|PQ?" + ] == arr3); } function testQueryExprWithLangLibCallsWithArrowFunctions() { - PersonK p1 = {firstName: "Alex", lastName: "George", age: 30}; - PersonK p2 = {firstName: "Anne", lastName: "Frank", age: 40}; - PersonK p3 = {firstName: "John", lastName: "David", age: 50}; - PersonK[] personList = [p1, p2, p3]; + Person p1 = {firstName: "Alex", lastName: "George", age: 30}; + Person p2 = {firstName: "Anne", lastName: "Frank", age: 40}; + Person p3 = {firstName: "John", lastName: "David", age: 50}; + Person[] personList = [p1, p2, p3]; int[] ageList = [50, 60]; int[] filteredAges = from int age in ageList @@ -747,7 +744,7 @@ function testQueryExprWithLangLibCallsWithArrowFunctions() { select ["John", "Frank"].filter(names => names == firstName).pop(); assertEquality(true, filteredNames2 == ["John"]); - PersonK[][] filteredPersons = from int age in [50] + Person[][] filteredPersons = from int age in [50] let string name = personList.filter(person => person.age == age).pop().firstName select personList.filter(person => person.firstName == name); assertEquality(true, filteredPersons == [[{"firstName":"John", "lastName":"David", "age":50}]]); diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/query/simple-query-with-var-type.bal b/tests/jballerina-unit-test/src/test/resources/test-src/query/simple-query-with-var-type.bal index 48af7090ea13..401b7a68af22 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/query/simple-query-with-var-type.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/query/simple-query-with-var-type.bal @@ -14,13 +14,13 @@ // specific language governing permissions and limitations // under the License. -type PersonQT record {| +type Person record {| string firstName; string lastName; int age; |}; -type TeacherQT record {| +type Teacher record {| string firstName; string lastName; int age; @@ -34,7 +34,7 @@ type EmployeeEntity record { int age; }; -type EmployeeQT record {| +type Employee record {| string fname; string lname; int age; @@ -42,7 +42,6 @@ type EmployeeQT record {| class NumberGenerator { int i = 0; - public isolated function next() returns record {|int value;|}|error? { //closes the stream after 5 events if (self.i == 5) { @@ -54,104 +53,104 @@ class NumberGenerator { } type ResultValue record {| - PersonQT value; + Person value; |}; -function getRecordValue((record {|PersonQT value;|}|error?)|(record {|PersonQT value;|}?) returnedVal) returns PersonQT? { - if (returnedVal is ResultValue) { - return returnedVal.value; - } else { - return (); - } +function getRecordValue((record {| Person value; |}|error?)|(record {| Person value; |}?) returnedVal) returns Person? { + if (returnedVal is ResultValue) { + return returnedVal.value; + } else { + return (); + } } -function testSimpleSelectQueryWithSimpleVariable() returns PersonQT[] { - PersonQT p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonQT p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonQT p3 = {firstName: "John", lastName: "David", age: 33}; +function testSimpleSelectQueryWithSimpleVariable() returns Person[] { + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p3 = {firstName: "John", lastName: "David", age: 33}; - PersonQT[] personList = [p1, p2, p3]; + Person[] personList = [p1, p2, p3]; - PersonQT[] outputPersonList = + Person[] outputPersonList = from var person in personList - select { - firstName: person.firstName, - lastName: person.lastName, - age: person.age - }; + select { + firstName: person.firstName, + lastName: person.lastName, + age: person.age + }; return outputPersonList; } -function testSimpleSelectQueryWithRecordVariable() returns PersonQT[] { - PersonQT p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonQT p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonQT p3 = {firstName: "John", lastName: "David", age: 33}; +function testSimpleSelectQueryWithRecordVariable() returns Person[] { + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p3 = {firstName: "John", lastName: "David", age: 33}; - PersonQT[] personList = [p1, p2, p3]; + Person[] personList = [p1, p2, p3]; - PersonQT[] outputPersonList = - from var {firstName: nm1, lastName: nm2, age: a} in personList - select { - firstName: nm1, - lastName: nm2, - age: a - }; + Person[] outputPersonList = + from var { firstName: nm1, lastName: nm2, age: a } in personList + select { + firstName: nm1, + lastName: nm2, + age: a + }; return outputPersonList; } -function testSimpleSelectQueryWithRecordVariableV2() returns PersonQT[] { - PersonQT p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonQT p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonQT p3 = {firstName: "John", lastName: "David", age: 33}; +function testSimpleSelectQueryWithRecordVariableV2() returns Person[] { + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p3 = {firstName: "John", lastName: "David", age: 33}; - PersonQT[] personList = [p1, p2, p3]; + Person[] personList = [p1, p2, p3]; var outputPersonList = - from var {firstName, lastName, age} in personList - select { - firstName: firstName, - lastName: lastName, - age: age - }; + from var { firstName, lastName, age } in personList + select { + firstName: firstName, + lastName: lastName, + age: age + }; return outputPersonList; } -function testSimpleSelectQueryWithRecordVariableV3() returns PersonQT[] { - TeacherQT p1 = {firstName: "Alex", lastName: "George", age: 23, teacherId: "XYZ01"}; - TeacherQT p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30, teacherId: "ABC01"}; - TeacherQT p3 = {firstName: "John", lastName: "David", age: 33, teacherId: "ABC10"}; +function testSimpleSelectQueryWithRecordVariableV3() returns Person[] { + Teacher p1 = {firstName: "Alex", lastName: "George", age: 23, teacherId: "XYZ01"}; + Teacher p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30, teacherId: "ABC01"}; + Teacher p3 = {firstName: "John", lastName: "David", age: 33, teacherId: "ABC10"}; - TeacherQT[] teacherList = [p1, p2, p3]; + Teacher[] teacherList = [p1, p2, p3]; var outputPersonList = - from var {firstName, lastName, age, teacherId} in teacherList - select { - firstName: firstName, - lastName: lastName, - age: age - }; + from var { firstName, lastName, age, teacherId} in teacherList + select { + firstName: firstName, + lastName: lastName, + age: age + }; return outputPersonList; } -function testSimpleSelectQueryWithWhereClause() returns PersonQT[] { - PersonQT p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonQT p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonQT p3 = {firstName: "John", lastName: "David", age: 33}; +function testSimpleSelectQueryWithWhereClause() returns Person[] { + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p3 = {firstName: "John", lastName: "David", age: 33}; - PersonQT[] personList = [p1, p2, p3]; + Person[] personList = [p1, p2, p3]; var outputPersonList = from var person in personList - where person.age >= 30 - select { - firstName: person.firstName, - lastName: person.lastName, - age: person.age - }; + where person.age >= 30 + select { + firstName: person.firstName, + lastName: person.lastName, + age: person.age + }; return outputPersonList; } @@ -161,8 +160,8 @@ function testQueryExpressionForPrimitiveType() returns boolean { var outputIntList = from var value in intList - where value > 20 - select value; + where value > 20 + select value; return outputIntList == [21, 25]; } @@ -173,102 +172,102 @@ function testQueryExpressionWithSelectExpression() returns boolean { var stringOutput = from var value in intList - select value.toString(); + select value.toString(); return stringOutput == ["1", "2", "3"]; } -function testFilteringNullElements() returns PersonQT[] { +function testFilteringNullElements() returns Person[] { - PersonQT p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonQT p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonQT?[] personList = [p1, (), p2]; + Person?[] personList = [p1, (), p2]; var outputPersonList = - from var person in personList - where (person is PersonQT) - select { - firstName: person.firstName, - lastName: person.lastName, - age: person.age - }; + from var person in personList + where (person is Person) + select { + firstName: person.firstName, + lastName: person.lastName, + age: person.age + }; return outputPersonList; } function testMapWithArity() returns boolean { map m = {a: "1A", b: "2B", c: "3C", d: "4D"}; var val = map from var v in m - where v == "1A" - select ["a", v]; + where v == "1A" + select ["a", v]; return val == {a: "1A"}; } function testJSONArrayWithArity() returns boolean { json[] jdata = [{name: "bob", age: 10}, {name: "tom", age: 16}]; var val = from var v in jdata - select checkpanic v.name; + select checkpanic v.name; return val == ["bob", "tom"]; } function testArrayWithTuple() returns boolean { [int, string][] arr = [[1, "A"], [2, "B"], [3, "C"]]; var val = from var [i, v] in arr - where i == 3 - select v; + where i == 3 + select v; return val == ["C"]; } -function testQueryExpressionWithVarType() returns TeacherQT[] { +function testQueryExpressionWithVarType() returns Teacher[] { - PersonQT p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonQT p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonQT p3 = {firstName: "John", lastName: "David", age: 33}; + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p3 = {firstName: "John", lastName: "David", age: 33}; - PersonQT[] personList = [p1, p2, p3]; + Person[] personList = [p1, p2, p3]; var outputPersonList = from var person in personList - select { - firstName: person.firstName, - lastName: person.lastName, - age: person.age, - teacherId: "TER1200" - }; + select { + firstName: person.firstName, + lastName: person.lastName, + age: person.age, + teacherId: "TER1200" + }; return outputPersonList; } -function testSimpleSelectQueryWithSpreadOperator() returns PersonQT[] { - PersonQT p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonQT p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonQT p3 = {firstName: "John", lastName: "David", age: 33}; +function testSimpleSelectQueryWithSpreadOperator() returns Person[] { + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p3 = {firstName: "John", lastName: "David", age: 33}; - PersonQT[] personList = [p1, p2, p3]; + Person[] personList = [p1, p2, p3]; - PersonQT[] outputPersonList = + Person[] outputPersonList = from var person in personList - select { - ...person - }; + select { + ...person + }; return outputPersonList; } -function testQueryExpressionWithSpreadOperatorV2() returns TeacherQT[] { +function testQueryExpressionWithSpreadOperatorV2() returns Teacher[] { - PersonQT p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonQT p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonQT p3 = {firstName: "John", lastName: "David", age: 33}; + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p3 = {firstName: "John", lastName: "David", age: 33}; - PersonQT[] personList = [p1, p2, p3]; + Person[] personList = [p1, p2, p3]; var outputPersonList = from var person in personList - select { - ...person, - teacherId: "TER1200" - }; + select { + ...person, + teacherId: "TER1200" + }; return outputPersonList; } @@ -278,11 +277,11 @@ public function testQueryWithStream() returns boolean { var numberStream = new stream(numGen); var oddNumberList = stream from var num in numberStream - where (num % 2 == 1) - select num; + where (num % 2 == 1) + select num; int[] result = []; - record {|int value;|}|error? v = oddNumberList.next(); - while (v is record {|int value;|}) { + record {| int value; |}|error? v = oddNumberList.next(); + while (v is record {| int value; |}) { result.push(v.value); v = oddNumberList.next(); } @@ -291,26 +290,26 @@ public function testQueryWithStream() returns boolean { function testSimpleSelectQueryReturnStream() returns boolean { boolean testPassed = true; - PersonQT p1 = {firstName: "Alex", lastName: "George", age: 23}; - PersonQT p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; - PersonQT p3 = {firstName: "John", lastName: "David", age: 33}; + Person p1 = {firstName: "Alex", lastName: "George", age: 23}; + Person p2 = {firstName: "Ranjan", lastName: "Fonseka", age: 30}; + Person p3 = {firstName: "John", lastName: "David", age: 33}; - PersonQT[] personList = [p1, p2, p3]; + Person[] personList = [p1, p2, p3]; var outputPersonStream = stream from var person in personList - select { - firstName: person.firstName, - lastName: person.lastName, - age: person.age - }; - PersonQT? returnedVal = getRecordValue(outputPersonStream.next()); - testPassed = testPassed && (returnedVal is PersonQT) && (returnedVal == p1); + select { + firstName: person.firstName, + lastName: person.lastName, + age: person.age + }; + Person? returnedVal = getRecordValue(outputPersonStream.next()); + testPassed = testPassed && (returnedVal is Person) && (returnedVal == p1); returnedVal = getRecordValue(outputPersonStream.next()); - testPassed = testPassed && (returnedVal is PersonQT) && (returnedVal == p2); + testPassed = testPassed && (returnedVal is Person) && (returnedVal == p2); returnedVal = getRecordValue(outputPersonStream.next()); - testPassed = testPassed && (returnedVal is PersonQT) && (returnedVal == p3); + testPassed = testPassed && (returnedVal is Person) && (returnedVal == p3); return testPassed; } @@ -319,15 +318,14 @@ string fname = ""; function testVariableShadowingWithQueryExpressions1() returns boolean { EmployeeEntity[] entities = [ - {id: 1232, fname: "Sameera", lname: "Jayasoma", age: 30}, - {id: 1232, fname: "Asanthi", lname: "Kulasinghe", age: 30}, - {id: 1232, fname: "Khiana", lname: "Jayasoma", age: 2} - ]; + {id: 1232, fname: "Sameera", lname: "Jayasoma", age: 30}, + {id: 1232, fname: "Asanthi", lname: "Kulasinghe", age: 30}, + {id: 1232, fname: "Khiana", lname: "Jayasoma", age: 2} + ]; - EmployeeQT[] records = from var {fname, lname, age} in entities - select {fname, lname, age}; + Employee[] records = from var {fname, lname, age} in entities select {fname, lname, age}; boolean testPassed = true; - EmployeeQT e = records[0]; + Employee e = records[0]; testPassed = testPassed && e.fname == "Sameera" && e.lname == "Jayasoma" && e.age == 30; e = records[1]; testPassed = testPassed && e.fname == "Asanthi" && e.lname == "Kulasinghe" && e.age == 30; @@ -339,16 +337,15 @@ function testVariableShadowingWithQueryExpressions1() returns boolean { function testVariableShadowingWithQueryExpressions2() returns boolean { EmployeeEntity[] entities = [ - {id: 1232, fname: "Sameera", lname: "Jayasoma", age: 30}, - {id: 1232, fname: "Asanthi", lname: "Kulasinghe", age: 30}, - {id: 1232, fname: "Khiana", lname: "Jayasoma", age: 2} - ]; + {id: 1232, fname: "Sameera", lname: "Jayasoma", age: 30}, + {id: 1232, fname: "Asanthi", lname: "Kulasinghe", age: 30}, + {id: 1232, fname: "Khiana", lname: "Jayasoma", age: 2} + ]; - EmployeeQT[] records = from var {fname, lname, age} in entities - select {fname, lname, age}; + Employee[] records = from var {fname, lname, age} in entities select {fname, lname, age}; var lname = 5; boolean testPassed = true; - EmployeeQT e = records[0]; + Employee e = records[0]; testPassed = testPassed && e.fname == "Sameera" && e.lname == "Jayasoma" && e.age == 30; e = records[1]; testPassed = testPassed && e.fname == "Asanthi" && e.lname == "Kulasinghe" && e.age == 30; @@ -374,7 +371,7 @@ function testSimpleSelectQueryWithTable() { assertEquality((table [{"id":1234},{"id":4567}]).toString(), t2.toString()); } -type UserQuery record { +type User record { readonly int id; string firstName; string lastName; @@ -382,10 +379,10 @@ type UserQuery record { }; function testQueryConstructingTableWithVar() returns error? { - UserQuery u1 = {id: 1, firstName: "John", lastName: "Doe", age: 25}; - UserQuery u2 = {id: 2, firstName: "Anne", lastName: "Frank", age: 30}; + User u1 = {id: 1, firstName: "John", lastName: "Doe", age: 25}; + User u2 = {id: 2, firstName: "Anne", lastName: "Frank", age: 30}; - table key(id) users = table []; + table key(id) users = table []; users.add(u1); users.add(u2); @@ -393,16 +390,16 @@ function testQueryConstructingTableWithVar() returns error? { where user.age > 21 && user.age < 60 select {user}; - assertEquality(true, result1 is table key(user)); + assertEquality(true, result1 is table key(user)); assertEquality({"user": u1}, result1.get(u1)); - UserQuery[] userList = [u1, u2]; + User[] userList = [u1, u2]; var result2 = check table key(user) from var user in userList where user.age > 21 && user.age < 60 select {user}; - assertEquality(true, result2 is table key(user)); + assertEquality(true, result2 is table key(user)); assertEquality({"user": u1}, result2.get(u1)); } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/reachability-analysis/unreachability_test.bal b/tests/jballerina-unit-test/src/test/resources/test-src/reachability-analysis/unreachability_test.bal index 7dd15e0b444d..2cc46d143d5b 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/reachability-analysis/unreachability_test.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/reachability-analysis/unreachability_test.bal @@ -836,7 +836,7 @@ function testUnreachabilityWithIfElseStmts6() { int _ = 10; } else if e == 20 { int _ = 20; - } else { + } else if e == 10 { never _ = e; // unreachable code } } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/reachability-analysis/unreachability_test2.bal b/tests/jballerina-unit-test/src/test/resources/test-src/reachability-analysis/unreachability_test2.bal index 1861beac7c92..a5e704049377 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/reachability-analysis/unreachability_test2.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/reachability-analysis/unreachability_test2.bal @@ -422,12 +422,12 @@ function testUnreachabilityWithIfStmtWithEqualityExpr14() { function testUnreachabilityWithIfStmtWithEqualityExpr15() { True t = true; - True f = true; + False f = false; if f == t { - return; + return; // unreachable code } else if t == t { - string _ = "Ballerina"; // unreachable code + string _ = "Ballerina"; } else { string _ = "Ballerina"; // unreachable code } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/record/readonly_record_fields.bal b/tests/jballerina-unit-test/src/test/resources/test-src/record/readonly_record_fields.bal index 2d97b86a3e54..2912906e6806 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/record/readonly_record_fields.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/record/readonly_record_fields.bal @@ -232,40 +232,40 @@ function testReadOnlyFieldWithDefaultValue() { assertEquality("cannot update 'readonly' field 'id' in record of type 'Identifier'", err.detail()["message"]); } -type FooH record {| +type Foo record {| string name; int id; float...; |}; -type BarH record {| +type Bar record {| readonly string name; readonly int id; |}; -type EmptyClosedRecordH record {| +type EmptyClosedRecord record {| |}; function testTypeReadOnlyFlagForAllReadOnlyFields() { - BarH st = { + Bar st = { name: "Maryam", id: 1234 }; - FooH & readonly pr = st; - assertTrue(pr is BarH); - assertTrue(pr is BarH & readonly); + Foo & readonly pr = st; + assertTrue(pr is Bar); + assertTrue(pr is Bar & readonly); assertEquality("Maryam", pr.name); assertEquality(1234, pr.id); readonly rd = st; - assertTrue(rd is BarH); - assertTrue(rd is BarH & readonly); + assertTrue(rd is Bar); + assertTrue(rd is Bar & readonly); - EmptyClosedRecordH ecr = {}; + EmptyClosedRecord ecr = {}; readonly rd2 = ecr; - assertTrue(rd2 is EmptyClosedRecordH); - assertTrue(rd2 is EmptyClosedRecordH & readonly); + assertTrue(rd2 is EmptyClosedRecord); + assertTrue(rd2 is EmptyClosedRecord & readonly); assertTrue(rd2 is record {} & readonly); } @@ -275,19 +275,19 @@ record {| function testTypeReadOnlyFlagForAllReadOnlyFieldsInAnonymousRecord() { readonly rd = modAnonRecord; - assertTrue(rd is record {int x;}); - assertTrue(rd is record {int x;} & readonly); - record {int x;} rec = checkpanic rd; + assertTrue( rd is record { int x; }); + assertTrue(rd is record { int x; } & readonly); + record { int x; } rec = checkpanic rd; assertEquality(2, rec.x); record {| readonly int x = 1; - readonly BarH y; + readonly Bar y; |} localAnonRecord = {y: {name: "Amy", id: 1001}}; readonly rd2 = localAnonRecord; - assertTrue(rd2 is record {|int x; BarH y;|}); - assertTrue(rd2 is record {int x; BarH y;} & readonly); - var rec2 = checkpanic rd2; + assertTrue( rd2 is record {| int x; Bar y; |}); + assertTrue(rd2 is record { int x; Bar y; } & readonly); + var rec2 = checkpanic rd2; assertEquality(1, rec2.x); assertEquality("Amy", rec2.y.name); assertEquality(1001, rec2.y.id); diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/record/record_project_closed_rec_equiv/Ballerina.toml b/tests/jballerina-unit-test/src/test/resources/test-src/record/record_project_closed_rec_equiv/Ballerina.toml index bbccc659c584..b7ec0186ad78 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/record/record_project_closed_rec_equiv/Ballerina.toml +++ b/tests/jballerina-unit-test/src/test/resources/test-src/record/record_project_closed_rec_equiv/Ballerina.toml @@ -1,4 +1,4 @@ [package] org = "testorg" -name = "closedrecordproject" +name = "recordproject" version = "1.0.0" diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/record/record_project_closed_rec_equiv/closed_record_equivalency.bal b/tests/jballerina-unit-test/src/test/resources/test-src/record/record_project_closed_rec_equiv/closed_record_equivalency.bal index 2619d1a62c10..6cb5e6e63325 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/record/record_project_closed_rec_equiv/closed_record_equivalency.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/record/record_project_closed_rec_equiv/closed_record_equivalency.bal @@ -14,10 +14,10 @@ // specific language governing permissions and limitations // under the License. -import closedrecordproject.eq; -import closedrecordproject.eq2; -import closedrecordproject.req; -import closedrecordproject.req2; +import recordproject.eq; +import recordproject.eq2; +import recordproject.req; +import recordproject.req2; public type person1 record {| int age = 0; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/statements/ifelse/test_type_guard_type_narrow_3.bal b/tests/jballerina-unit-test/src/test/resources/test-src/statements/ifelse/test_type_guard_type_narrow_3.bal index 6ed8c273e634..74bff266e75a 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/statements/ifelse/test_type_guard_type_narrow_3.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/statements/ifelse/test_type_guard_type_narrow_3.bal @@ -260,7 +260,7 @@ function test20(int|string x) { } if x is int && !(x !is int) { - int _ = x; // OK + int _ = x; // Type not narrowed. issue #34965 } else { string _ = x; // Type not narrowed. issue #34965 } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/statements/ifelse/test_type_guard_type_narrow_4.bal b/tests/jballerina-unit-test/src/test/resources/test-src/statements/ifelse/test_type_guard_type_narrow_4.bal index a6c5ec78e343..3e95ff0b3554 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/statements/ifelse/test_type_guard_type_narrow_4.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/statements/ifelse/test_type_guard_type_narrow_4.bal @@ -18,18 +18,18 @@ function test1(2|"foo" x) { if x is int && x == 2 { 2 _ = x; // OK } else { - "foo" _ = x; // OK + "foo" _ = x; // Type not narrowed. issue #34965 } if x is 2 && x == 2 { 2 _ = x; // OK } else { - "foo" _ = x; // OK + "foo" _ = x; // Type not narrowed. issue #34965 } if x == 2 && x == 2 { 2 _ = x; // OK } else { - "foo" _ = x; // OK + "foo" _ = x; // Type not narrowed. issue #34965 } } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/statements/matchstmt/list-match-pattern-with-rest-match-pattern.bal b/tests/jballerina-unit-test/src/test/resources/test-src/statements/matchstmt/list-match-pattern-with-rest-match-pattern.bal index 55982e369681..50ee838ae2d9 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/statements/matchstmt/list-match-pattern-with-rest-match-pattern.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/statements/matchstmt/list-match-pattern-with-rest-match-pattern.bal @@ -221,11 +221,10 @@ function testListMatchPatternWithRestPattern12() { assertEquals(false, a5[2]); } -class FooObjLMP { +class FooObj { public string s; public float f; public byte b; - function init(string s, float f, byte b) { self.s = s; self.f = f; @@ -233,10 +232,9 @@ class FooObjLMP { } } -class BarObjLMP { +class BarObj { public boolean b; public int i; - function init(boolean b, int i) { self.b = b; self.i = i; @@ -244,51 +242,36 @@ class BarObjLMP { } function testListMatchPatternWithRestPattern13() { - FooObjLMP fooObj1 = new ("Fooo", 3.7, 23); - BarObjLMP barObj1 = new (true, 56); - FooObjLMP fooObj2 = new ("Foo2", 10.2, 30); - BarObjLMP barObj2 = new (false, 56); - BarObjLMP barObj3 = new (true, 58); + FooObj fooObj1 = new ("Fooo", 3.7, 23); + BarObj barObj1 = new (true, 56); + FooObj fooObj2 = new ("Foo2", 10.2, 30); + BarObj barObj2 = new (false, 56); + BarObj barObj3 = new (true, 58); string matched = "Not Matched"; - [[string, [error, map, int, (FooObjLMP|BarObjLMP)...], Bar, (byte|float)...], string, boolean...] t2 = - [ - [ - "Ballerina", - [ - error("Error", detail1 = 12, detail2 = true), - {firstName: "John", lastName: "Damon"}, - 12, - fooObj1, - barObj1 - ], - {id: 34, flag: true}, - 10.5, - 20 - ], - "A", - true, - false - ]; + [[string, [error, map, int, (FooObj|BarObj)...], Bar, (byte|float)...], string, boolean...] t2 = + [["Ballerina", [error("Error", detail1= 12, detail2= true), + {firstName: "John", lastName: "Damon"}, 12, fooObj1, barObj1], {id: 34, flag: true}, 10.5, 20], + "A", true, false]; string a1; error a2; - [map, int, (FooObjLMP|BarObjLMP)...] a3; + [map, int, (FooObj|BarObj)...] a3; [Bar, (byte|float)...] a4; [string, boolean...] a5; map a6; - [int, (FooObjLMP|BarObjLMP)...] a7; + [int, (FooObj|BarObj)...] a7; string b1; error b2; - [map, int, (FooObjLMP|BarObjLMP)...] b3; + [map, int, (FooObj|BarObj)...] b3; [Bar, (byte|float)...] b4; [string, boolean...] b5; map b6; - [int, (FooObjLMP|BarObjLMP)...] b7; + [int, (FooObj|BarObj)...] b7; match t2 { - [[var g1, [var g2, ...var g3], ...var g4], ...var g5] => { + [[var g1, [var g2, ... var g3], ...var g4], ...var g5] => { matched = "Matched1"; a1 = g1; a2 = g2; @@ -303,24 +286,9 @@ function testListMatchPatternWithRestPattern13() { } } - [[g1, g2, ...g3], [...g5], ...g4] = [ - [ - "Hello", - error("Transaction Error"), - [ - { - primary: "Blue", - secondary: "Green" - }, - 1000, - barObj2, - fooObj2, - barObj3 - ] - ], - [["World", true, false, true, false]], - [{id: 40, flag: true}, 0x5, 0x7, 20.25, 0x8] - ]; + [[g1, g2, ...g3], [...g5], ...g4] = [["Hello", error("Transaction Error"), [{primary: "Blue", + secondary: "Green"}, 1000, barObj2, fooObj2, barObj3]], [["World", true, false, true, false]], + [{id: 40, flag: true}, 0x5, 0x7, 20.25, 0x8]]; b1 = g1; b2 = g2; b3 = g3; @@ -355,16 +323,16 @@ function testListMatchPatternWithRestPattern13() { assertEquals("Blue", b3[0]["primary"]); assertEquals("Green", b3[0]["secondary"]); assertEquals(1000, b3[1]); - assertEquals(true, b3[2] is BarObjLMP); - assertEquals(false, (b3[2]).b); - assertEquals(56, (b3[2]).i); - assertEquals(true, b3[3] is FooObjLMP); - assertEquals("Foo2", (b3[3]).s); - assertEquals(10.2, (b3[3]).f); - assertEquals(30, (b3[3]).b); - assertEquals(true, b3[4] is BarObjLMP); - assertEquals(true, (b3[4]).b); - assertEquals(58, (b3[4]).i); + assertEquals(true, b3[2] is BarObj); + assertEquals(false, (b3[2]).b); + assertEquals(56, (b3[2]).i); + assertEquals(true, b3[3] is FooObj); + assertEquals("Foo2", (b3[3]).s); + assertEquals(10.2, (b3[3]).f); + assertEquals(30, (b3[3]).b); + assertEquals(true, b3[4] is BarObj); + assertEquals(true, (b3[4]).b); + assertEquals(58, (b3[4]).i); assertEquals(5, b5.length()); assertEquals("World", b5[0]); assertEquals(true, b5[1]); diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/statements/matchstmt/list-match-pattern.bal b/tests/jballerina-unit-test/src/test/resources/test-src/statements/matchstmt/list-match-pattern.bal index 32bb925e047d..0395cd3756c2 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/statements/matchstmt/list-match-pattern.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/statements/matchstmt/list-match-pattern.bal @@ -504,35 +504,35 @@ function testListMatchPattern18() { assertEquals("Default" ,listMatchPattern18(a5)); } -type FooRecLMP record { +type FooRec record { string s; int i; float f; }; -type BarRecLMP record { +type BarRec record { byte b; - FooRecLMP f; + FooRec f; }; function listMatchPattern19(any a) returns string { match a { - [var i, var s] if i is FooRecLMP && s is BarRecLMP => { + [var i, var s] if i is FooRec && s is BarRec => { return "Matched with FooRec and BarRec : " + i.toString() + " , " + s.toString(); } - [var i, var s] if i is FooRecLMP && s is float => { + [var i, var s] if i is FooRec && s is float => { return "Matched with FooRec and float : " + i.toString() + " , " + s.toString(); } - [var i, var s] if i is BarRecLMP && s is FooRecLMP => { + [var i, var s] if i is BarRec && s is FooRec => { return "Matched with BarRec and FooRec : " + i.toString() + " , " + s.toString(); } - [var i, var s] if i is BarRecLMP && s is int => { + [var i, var s] if i is BarRec && s is int => { return "Matched with BarRec and int : " + i.toString() + " , " + s.toString(); } - [var i, var s] if i is float && s is FooRecLMP => { + [var i, var s] if i is float && s is FooRec => { return "Matched with float and FooRec : " + i.toString() + " , " + s.toString(); } - [var i, var s] if i is int && s is BarRecLMP => { + [var i, var s] if i is int && s is BarRec => { return "Matched with int and BarRec : " + i.toString() + " , " + s.toString(); } } @@ -541,34 +541,34 @@ function listMatchPattern19(any a) returns string { } function testListMatchPattern19() { - FooRecLMP fooRec1 = {s: "S", i: 23, f: 5.6}; - BarRecLMP barRec1 = {b: 12, f: fooRec1}; - - [int|FooRecLMP, float|BarRecLMP]|[float|BarRecLMP, int|FooRecLMP] a1 = [fooRec1, barRec1]; - [int|FooRecLMP, float|BarRecLMP]|[float|BarRecLMP, int|FooRecLMP] a2 = [fooRec1, 4.5]; - [int|FooRecLMP, float|BarRecLMP]|[float|BarRecLMP, int|FooRecLMP] a3 = [barRec1, fooRec1]; - [int|FooRecLMP, float|BarRecLMP]|[float|BarRecLMP, int|FooRecLMP] a4 = [barRec1, 543]; - [int|FooRecLMP, float|BarRecLMP]|[float|BarRecLMP, int|FooRecLMP] a5 = [5.2, fooRec1]; - [int|FooRecLMP, float|BarRecLMP]|[float|BarRecLMP, int|FooRecLMP] a6 = [15, barRec1]; - [int|FooRecLMP, float|BarRecLMP]|[float|BarRecLMP, int|FooRecLMP] a7 = [65, 7.4]; - [int|FooRecLMP, float|BarRecLMP]|[float|BarRecLMP, int|FooRecLMP] a8 = [3.6, 42]; + FooRec fooRec1 = {s: "S", i: 23, f: 5.6}; + BarRec barRec1 = {b: 12, f: fooRec1}; + + [int|FooRec, float|BarRec] | [float|BarRec, int|FooRec] a1 = [fooRec1, barRec1]; + [int|FooRec, float|BarRec] | [float|BarRec, int|FooRec] a2 = [fooRec1, 4.5]; + [int|FooRec, float|BarRec] | [float|BarRec, int|FooRec] a3 = [barRec1, fooRec1]; + [int|FooRec, float|BarRec] | [float|BarRec, int|FooRec] a4 = [barRec1, 543]; + [int|FooRec, float|BarRec] | [float|BarRec, int|FooRec] a5 = [5.2, fooRec1]; + [int|FooRec, float|BarRec] | [float|BarRec, int|FooRec] a6 = [15, barRec1]; + [int|FooRec, float|BarRec] | [float|BarRec, int|FooRec] a7 = [65, 7.4]; + [int|FooRec, float|BarRec] | [float|BarRec, int|FooRec] a8 = [3.6, 42]; assertEquals("Matched with FooRec and BarRec : {\"s\":\"S\",\"i\":23,\"f\":5.6} , " + "{\"b\":12,\"f\":{\"s\":\"S\",\"i\":23,\"f\":5.6}}", listMatchPattern19(a1)); - assertEquals("Matched with FooRec and float : {\"s\":\"S\",\"i\":23,\"f\":5.6} , 4.5", listMatchPattern19(a2)); + assertEquals("Matched with FooRec and float : {\"s\":\"S\",\"i\":23,\"f\":5.6} , 4.5" ,listMatchPattern19(a2)); assertEquals("Matched with BarRec and FooRec : {\"b\":12,\"f\":{\"s\":\"S\",\"i\":23,\"f\":5.6}} , " + - "{\"s\":\"S\",\"i\":23,\"f\":5.6}", listMatchPattern19(a3)); - assertEquals("Matched with BarRec and int : {\"b\":12,\"f\":{\"s\":\"S\",\"i\":23,\"f\":5.6}} , 543", - listMatchPattern19(a4)); - assertEquals("Matched with float and FooRec : 5.2 , {\"s\":\"S\",\"i\":23,\"f\":5.6}", listMatchPattern19(a5)); - assertEquals("Matched with int and BarRec : 15 , {\"b\":12,\"f\":{\"s\":\"S\",\"i\":23,\"f\":5.6}}", - listMatchPattern19(a6)); - assertEquals("Default", listMatchPattern19(a7)); - assertEquals("Default", listMatchPattern19(a8)); + "{\"s\":\"S\",\"i\":23,\"f\":5.6}" ,listMatchPattern19(a3)); + assertEquals("Matched with BarRec and int : {\"b\":12,\"f\":{\"s\":\"S\",\"i\":23,\"f\":5.6}} , 543" , + listMatchPattern19(a4)); + assertEquals("Matched with float and FooRec : 5.2 , {\"s\":\"S\",\"i\":23,\"f\":5.6}" ,listMatchPattern19(a5)); + assertEquals("Matched with int and BarRec : 15 , {\"b\":12,\"f\":{\"s\":\"S\",\"i\":23,\"f\":5.6}}" , + listMatchPattern19(a6)); + assertEquals("Default" ,listMatchPattern19(a7)); + assertEquals("Default" ,listMatchPattern19(a8)); } function listMatchPattern20() returns string { - [boolean, string]|[int, string, decimal] v = [1, "A", 1.1d]; + [boolean, string] | [int, string, decimal] v = [1, "A", 1.1d]; match v { [var i, ...var s] => { return "i: " + i.toString() + " s: " + s.toString(); @@ -699,7 +699,7 @@ function testListMatchPatternWithWildCard() { result = "Matched"; } _ => { - result = "Default"; + result = "Default"; } } assertEquals("Default", result); @@ -711,7 +711,7 @@ function testListMatchPatternWithWildCard() { result = "Matched"; } _ => { - result = "Default"; + result = "Default"; } } assertEquals("Not Matched", result); @@ -719,10 +719,10 @@ function testListMatchPatternWithWildCard() { function testListMatchPatternWithArrayAndAnydataIntersection() { int[] x = [1, 2, 3]; - assertEquals(x, listMatchPattern28([x])); + assertEquals(x, listMatchPattern28( [x])); anydata[] y = [["hello", "world"]]; assertEquals(["hello", "world"], listMatchPattern28(y)); - assertEquals("other", listMatchPattern28([["hello", "world"], 1, 2])); + assertEquals("other", listMatchPattern28( [["hello", "world"], 1, 2])); assertEquals("other", listMatchPattern28("hello")); } @@ -745,12 +745,12 @@ function testListMatchPattern29() { assertEquals((), listMatchPattern29(1)); } -type RecLMP record {| +type Rec record {| int|float a; |}; function testListMatchPattern30() { - [int, RecLMP|string] a1 = [12, {a: 1}]; + [int, Rec|string] a1 = [12, {a: 1}]; string result = ""; match a1 { @@ -781,7 +781,7 @@ function testListMatchPattern30() { } assertEquals("Pattern3", result); - [int, RecLMP|string...] a2 = [12, {a: 1}]; + [int, Rec|string...] a2 = [12, {a: 1}]; result = ""; match a2 { @@ -797,7 +797,7 @@ function testListMatchPattern30() { } assertEquals("Pattern3", result); - [int, string, RecLMP|string...] a3 = [12, "C", {a: 1.5}]; + [int, string, Rec|string...] a3 = [12, "C", {a: 1.5}]; result = ""; match a3 { @@ -813,7 +813,7 @@ function testListMatchPattern30() { } assertEquals("Pattern2", result); - [RecLMP|string...] a4 = [{a: 1}, {a: 2}, {a: 3}]; + [Rec|string...] a4 = [{a: 1}, {a: 2}, {a: 3}]; result = ""; match a4 { @@ -838,8 +838,8 @@ function testListMatchPattern30() { } assertEquals("Pattern2", result); - error err1 = error("Error One", data = [{b: 5}, 12]); - [error, RecLMP|string...] a5 = [err1, {a: 2}, {a: 3}]; + error err1 = error("Error One", data= [{b: 5}, 12]); + [error, Rec|string...] a5 = [err1, {a: 2}, {a: 3}]; result = ""; match a5 { @@ -853,22 +853,21 @@ function testListMatchPattern30() { assertEquals("Pattern2", result); } -type TLMP readonly & SLMP; - -type SLMP [INT, int]|[STRING, string]; +type T readonly & S; +type S [INT, int]|[STRING, string]; const INT = 1; const STRING = 2; function testListMatchPattern31() { - TLMP t1 = [STRING, "hello"]; - TLMP t2 = [INT, 1234]; + T t1 = [STRING, "hello"]; + T t2 = [INT, 1234]; assertEquals(["hello", ()], listMatchPattern31(t1)); assertEquals([(), 1234], listMatchPattern31(t2)); } -function listMatchPattern31(TLMP t) returns [string?, int?] { +function listMatchPattern31(T t) returns [string?, int?] { string? s = (); int? i = (); @@ -885,14 +884,14 @@ function listMatchPattern31(TLMP t) returns [string?, int?] { } function testListMatchPattern32() { - TLMP t1 = [STRING, "hello"]; - TLMP t2 = [INT, 1234]; + T t1 = [STRING, "hello"]; + T t2 = [INT, 1234]; assertEquals("hello", listMatchPattern32(t1)); assertEquals(1234, listMatchPattern32(t2)); } -function listMatchPattern32(TLMP t) returns string|int { +function listMatchPattern32(T t) returns string|int { string|int s; match t { @@ -904,19 +903,19 @@ function listMatchPattern32(TLMP t) returns string|int { return s; } -type T2LMP readonly & ([1, string]|[2, string]|[3, string]); +type T2 readonly & ([1, string]|[2, string]|[3, string]); function testListMatchPattern33() { - T2LMP t1 = [1, "hello"]; - T2LMP t2 = [2, "1234"]; - T2LMP t3 = [3, "abcd"]; + T2 t1 = [1, "hello"]; + T2 t2 = [2, "1234"]; + T2 t3 = [3, "abcd"]; assertEquals("hello", listMatchPattern33(t1)); assertEquals("1234", listMatchPattern33(t2)); assertEquals("abcd", listMatchPattern33(t3)); } -function listMatchPattern33(T2LMP t) returns string { +function listMatchPattern33(T2 t) returns string { string s; match t { @@ -928,19 +927,18 @@ function listMatchPattern33(T2LMP t) returns string { return s; } -type T3LMP readonly & S3LMP; - -type S3LMP string[2]|int[2]; +type T3 readonly & S3; +type S3 string[2]|int[2]; function testListMatchPattern34() { - T3LMP t1 = ["1", "hello"]; - T3LMP t2 = [2, 1234]; + T3 t1 = ["1", "hello"]; + T3 t2 = [2, 1234]; assertEquals("hello", listMatchPattern34(t1)); assertEquals(1234, listMatchPattern34(t2)); } -function listMatchPattern34(T3LMP t) returns string|int { +function listMatchPattern34(T3 t) returns string|int { string|int s = 10; match t { @@ -952,22 +950,22 @@ function listMatchPattern34(T3LMP t) returns string|int { return s; } -public type T4LMP ["list", T4LMP[]]|"int"; +public type T4 ["list", T4[]]|"int"; function testListMatchPattern35() { - T4LMP[] t1 = ["int"]; - T4LMP[] t2 = ["int", "int", "int"]; + T4[] t1 = ["int"]; + T4[] t2 = ["int", "int", "int"]; - T4LMP x1 = ["list", t1]; - T4LMP x2 = ["list", ["int", "int"]]; - T4LMP x3 = ["list", t2]; + T4 x1 = ["list", t1]; + T4 x2 = ["list", ["int", "int"]]; + T4 x3 = ["list", t2]; assertEquals(listMatchPattern35(x1, t1), "match 4"); assertEquals(listMatchPattern35("int", ()), "match 1"); assertEquals(listMatchPattern35(x2, ()), "match 2"); assertEquals(listMatchPattern35(x3, t2), "match 4"); } -function listMatchPattern35(T4LMP x, T4LMP[]? t) returns string? { +function listMatchPattern35(T4 x, T4[]? t) returns string? { match x { "int" => { return "match 1"; @@ -989,19 +987,19 @@ function listMatchPattern35(T4LMP x, T4LMP[]? t) returns string? { } function testListMatchPattern36() { - T4LMP[] t1 = ["int"]; - T4LMP[] t2 = ["int", "int", "int"]; + T4[] t1 = ["int"]; + T4[] t2 = ["int", "int", "int"]; - T4LMP x1 = ["list", t1]; - T4LMP x2 = ["list", ["int", "int"]]; - T4LMP x3 = ["list", t2]; + T4 x1 = ["list", t1]; + T4 x2 = ["list", ["int", "int"]]; + T4 x3 = ["list", t2]; assertEquals(listMatchPattern36(x1, t1), "match 4"); assertEquals(listMatchPattern36("int", ()), "match 1"); assertEquals(listMatchPattern36(x2, ()), "match 2"); assertEquals(listMatchPattern36(x3, t2), "match 4"); } -function listMatchPattern36((T4LMP|anydata)? x, T4LMP[]? t) returns string? { +function listMatchPattern36((T4|anydata)? x, T4[]? t) returns string? { string? a = (); match x { "int" => { @@ -1020,17 +1018,16 @@ function listMatchPattern36((T4LMP|anydata)? x, T4LMP[]? t) returns string? { } } -public type T5LMP ["array", T6LMP]|["cell", T6LMP, string]; - -public type T6LMP ["|", T6LMP]|"int"; +public type T5 ["array", T6]|["cell", T6, string]; +public type T6 ["|", T6]|"int"; function testListMatchPattern37() { - T6LMP t1 = ["|", ["|", "int"]]; - T6LMP t2 = "int"; - T5LMP x1 = ["cell", t1, "inf"]; - T5LMP x2 = ["array", t1]; - T5LMP x3 = ["cell", t2, "inf1"]; - T5LMP x4 = ["array", t2]; + T6 t1 = ["|", ["|", "int"]]; + T6 t2 = "int"; + T5 x1 = ["cell", t1, "inf"]; + T5 x2 = ["array", t1]; + T5 x3 = ["cell", t2, "inf1"]; + T5 x4 = ["array", t2]; assertEquals(listMatchPattern37(x1, t1, "inf"), "match 2"); assertEquals(listMatchPattern37(x2, t1, ()), "match 4"); @@ -1038,7 +1035,7 @@ function testListMatchPattern37() { assertEquals(listMatchPattern37(x4, t2, ()), "match 4"); } -function listMatchPattern37(T5LMP x, T6LMP? t, string? s) returns string { +function listMatchPattern37(T5 x, T6? t, string? s) returns string { match x { ["cell", "int", "inf1"] => { return "match 1"; @@ -1062,12 +1059,12 @@ function listMatchPattern37(T5LMP x, T6LMP? t, string? s) returns string { } function testListMatchPattern38() { - T6LMP t1 = ["|", ["|", "int"]]; - T6LMP t2 = "int"; - T5LMP x1 = ["cell", t1, "inf"]; - T5LMP x2 = ["array", t1]; - T5LMP x3 = ["cell", t2, "inf1"]; - T5LMP x4 = ["array", t2]; + T6 t1 = ["|", ["|", "int"]]; + T6 t2 = "int"; + T5 x1 = ["cell", t1, "inf"]; + T5 x2 = ["array", t1]; + T5 x3 = ["cell", t2, "inf1"]; + T5 x4 = ["array", t2]; assertEquals(listMatchPattern38(x1, t1, "inf"), "match 2"); assertEquals(listMatchPattern38(x2, t1, ()), "match 4"); @@ -1075,7 +1072,7 @@ function testListMatchPattern38() { assertEquals(listMatchPattern38(x4, t2, ()), "match 4"); } -function listMatchPattern38((anydata|T5LMP)? x, T6LMP? t, string? s) returns string? { +function listMatchPattern38((anydata|T5)? x, T6? t, string? s) returns string? { match x { ["cell", "int", "inf1"] => { return "match 1"; @@ -1095,40 +1092,40 @@ function listMatchPattern38((anydata|T5LMP)? x, T6LMP? t, string? s) returns str } } -public type T7LMP ["array", T6LMP]|["cell", T6LMP]; +public type T7 ["array", T6]|["cell", T6]; function testListMatchPattern39() { - T6LMP y1 = "int"; - T6LMP y2 = ["|", "int"]; + T6 y1 = "int"; + T6 y2 = ["|", "int"]; - T7LMP x1 = ["cell", y1]; - T7LMP x2 = ["array", y1]; - T7LMP x3 = ["cell", y2]; + T7 x1 = ["cell", y1]; + T7 x2 = ["array", y1]; + T7 x3 = ["cell", y2]; assertEquals(listMatchPattern39(x1, y1), "match 3"); assertEquals(listMatchPattern39(x2, y1), "match 2"); assertEquals(listMatchPattern39(x3, y2), "match 3"); } -function listMatchPattern39(T7LMP x, T6LMP y) returns string { +function listMatchPattern39(T7 x, T6 y) returns string { match x { ["list", var _] => { - T6LMP _ = x[1]; - T6LMP a = x[1]; + T6 _ = x[1]; + T6 a = x[1]; assertEquals(a, y); assertEquals(x[0], "list"); return "match 1"; } ["array", var _] => { - T6LMP _ = x[1]; - T6LMP a = x[1]; + T6 _ = x[1]; + T6 a = x[1]; assertEquals(a, y); assertEquals(x[0], "array"); return "match 2"; } ["cell", var _] => { - T6LMP _ = x[1]; - T6LMP a = x[1]; + T6 _ = x[1]; + T6 a = x[1]; assertEquals(a, y); assertEquals(x[0], "cell"); return "match 3"; @@ -1139,19 +1136,19 @@ function listMatchPattern39(T7LMP x, T6LMP y) returns string { } } -public type T8LMP ["list", T8LMP, T8LMP[]]|["list", T8LMP[]]|"int"; +public type T8 ["list", T8, T8[]]|["list", T8[]]|"int"; function testListMatchPattern40() { - T8LMP t1 = "int"; - T8LMP[] t2 = ["int", "int", "int"]; - T8LMP[] t3 = [t1]; - T8LMP t4 = ["list", ["int", "int", "int"]]; + T8 t1 = "int"; + T8[] t2 = ["int", "int", "int"]; + T8[] t3 = [t1]; + T8 t4 = ["list", ["int", "int", "int"]]; - T8LMP x1 = ["list", t3]; - T8LMP x2 = ["list", ["int", "int"]]; - T8LMP x3 = ["list", t2]; - T8LMP x4 = ["list", "int", t2]; - T8LMP x5 = ["list", t4, t3]; + T8 x1 = ["list", t3]; + T8 x2 = ["list", ["int", "int"]]; + T8 x3 = ["list", t2]; + T8 x4 = ["list", "int", t2]; + T8 x5 = ["list", t4, t3]; assertEquals(listMatchPattern40(x1, (), t3, ()), "match 4"); assertEquals(listMatchPattern40("int", (), (), ()), "match 1"); @@ -1161,7 +1158,7 @@ function testListMatchPattern40() { assertEquals(listMatchPattern40(x5, t4, t3, ()), "match 6"); } -function listMatchPattern40(T8LMP x, T8LMP? t1, T8LMP[]? t2, T8LMP? t3) returns string? { +function listMatchPattern40(T8 x, T8? t1, T8[]? t2, T8? t3) returns string? { match x { "int" => { return "match 1"; @@ -1180,7 +1177,7 @@ function listMatchPattern40(T8LMP x, T8LMP? t1, T8LMP[]? t2, T8LMP? t3) returns return "match 5"; } ["list", var y, var z] => { - T8LMP _ = z[0]; + T8 _ = z[0]; assertEquals(y, t1); assertEquals(z, t2); return "match 6"; @@ -1191,15 +1188,15 @@ function listMatchPattern40(T8LMP x, T8LMP? t1, T8LMP[]? t2, T8LMP? t3) returns } } -public type T9LMP ["array", T9LMP]|["cell", T6LMP]|["array", T6LMP]|[string, int]; +public type T9 ["array", T9]|["cell", T6]|["array", T6]|[string, int]; function testListMatchPattern41() { - T9LMP x1 = ["cell", "int"]; - T9LMP x2 = ["array", ["|", "int"]]; - T9LMP x3 = ["cell", ["|", "int"]]; - T9LMP x4 = ["string 1", 1]; - T9LMP x5 = ["array", x4]; - T9LMP x6 = ["string 2", 1]; + T9 x1 = ["cell", "int"]; + T9 x2 = ["array", ["|", "int"]]; + T9 x3 = ["cell", ["|", "int"]]; + T9 x4 = ["string 1", 1]; + T9 x5 = ["array", x4]; + T9 x6 = ["string 2", 1]; assertEquals(listMatchPattern41(x1), "match 1"); assertEquals(listMatchPattern41(x2), "match 4"); @@ -1209,7 +1206,7 @@ function testListMatchPattern41() { assertEquals(listMatchPattern41(x6), "match 6"); } -function listMatchPattern41(T9LMP x) returns string { +function listMatchPattern41(T9 x) returns string { match x { ["cell", "int"] => { return "match 1"; @@ -1232,14 +1229,14 @@ function listMatchPattern41(T9LMP x) returns string { } } -public type T10LMP [string, decimal, string]|[string, boolean...]|[int...]|[boolean]; +public type T10 [string, decimal, string]|[string, boolean...]|[int...]|[boolean]; function testListMatchPattern42() { - T10LMP x1 = ["string", 1d, "string"]; - T10LMP x2 = ["string", true, true, true, true, true, true]; - T10LMP x3 = [1, 1, 1, 1]; - T10LMP x4 = [true]; - T10LMP x5 = ["string", true]; + T10 x1 = ["string", 1d, "string"]; + T10 x2 = ["string", true, true, true, true, true, true]; + T10 x3 = [1, 1, 1, 1]; + T10 x4 = [true]; + T10 x5 = ["string", true]; assertEquals(listMatchPattern42(x1, ["string", 1d, "string"]), "match 1"); assertEquals(listMatchPattern42(x2, ["string", true, true, true, true, [true, true]]), "match 3"); @@ -1248,7 +1245,7 @@ function testListMatchPattern42() { assertEquals(listMatchPattern42(x5, ["string", true]), "match 5"); } -function listMatchPattern42(T10LMP t, anydata a) returns string { +function listMatchPattern42(T10 t, anydata a) returns string { match t { [var x, var y, var z] => { assertEquals([x, y, z], a); @@ -1273,25 +1270,25 @@ function listMatchPattern42(T10LMP t, anydata a) returns string { } } -public type T11LMP [int, T11LMP, T11LMP...]|[T11LMP...]|["int"]; +public type T11 [int, T11, T11...]|[T11...]|["int"]; public function testListMatchPattern43() { - T11LMP[] t1 = [["int"], ["int"], ["int"]]; - T11LMP x1 = [1, ["int"], ["int"]]; - T11LMP x2 = [1, ["int"], ["int"], ["int"], ["int"], ["int"], ["int"], ["int"]]; - T11LMP x3 = [["int"], ["int"], ["int"], ["int"]]; - T11LMP x4 = [["int"]]; - T11LMP x5 = [t1, ["int"]]; + T11[] t1 = [["int"], ["int"], ["int"]]; + T11 x1 = [1, ["int"], ["int"]]; + T11 x2 = [1, ["int"], ["int"], ["int"], ["int"], ["int"], ["int"], ["int"]]; + T11 x3 = [["int"], ["int"], ["int"], ["int"]]; + T11 x4 = [["int"]]; + T11 x5 = [t1, ["int"]]; assertEquals(listMatchPattern43(x1, [1, ["int"], ["int"]]), "match 1"); assertEquals(listMatchPattern43(x2, - [1, ["int"], ["int"], ["int"], ["int"], [["int"], ["int"], ["int"]]]), "match 3"); + [1, ["int"], ["int"], ["int"], ["int"], [["int"], ["int"], ["int"]]]), "match 3"); assertEquals(listMatchPattern43(x3, [["int"], ["int"], ["int"], [["int"]]]), "match 4"); assertEquals(listMatchPattern43(x4, [["int"]]), "match 2"); assertEquals(listMatchPattern43(x5, [t1, ["int"]]), "match 5"); } -function listMatchPattern43(T11LMP t, anydata a) returns string { +function listMatchPattern43(T11 t, anydata a) returns string { match t { [var x, var y, var z] => { assertEquals([x, y, z], a); @@ -1316,24 +1313,23 @@ function listMatchPattern43(T11LMP t, anydata a) returns string { } } -public type T12LMP [int, T12LMP[], T12LMP...]|[T12LMP[]...]|"int"; - -public type T13LMP [int, T13LMP, T13LMP, T13LMP[]...]|[T13LMP...]|"int"; +public type T12 [int, T12[], T12...]|[T12[]...]|"int"; +public type T13 [int, T13, T13, T13[]...]|[T13...]|"int"; public function testListMatchPattern44() { - T12LMP[] t1 = ["int", "int", "int"]; - T12LMP x1 = [1, t1, "int", "int"]; - T12LMP x2 = [1, t1, "int", "int", "int", "int", "int", "int", "int"]; - T12LMP x3 = [t1, t1, t1, t1, t1]; - T12LMP x4 = [t1]; - T12LMP x5 = [t1, t1]; - - T13LMP[] t2 = ["int", "int", "int"]; - T13LMP y1 = [1, "int", "int", t2, t2]; - T13LMP y2 = [1, "int", "int", t2, t2, t2, t2, t2, t2, t2]; - T13LMP y3 = [t2, t2, t2, t2, t2, t2]; - T13LMP y4 = [t2]; - T13LMP y5 = [t2, t2]; + T12[] t1 = ["int", "int", "int"]; + T12 x1 = [1, t1, "int", "int"]; + T12 x2 = [1, t1, "int", "int", "int", "int", "int", "int", "int"]; + T12 x3 = [t1, t1, t1, t1, t1]; + T12 x4 = [t1]; + T12 x5 = [t1, t1]; + + T13[] t2 = ["int", "int", "int"]; + T13 y1 = [1, "int", "int", t2, t2]; + T13 y2 = [1, "int", "int", t2, t2, t2, t2, t2, t2, t2]; + T13 y3 = [t2, t2, t2, t2, t2, t2]; + T13 y4 = [t2]; + T13 y5 = [t2, t2]; assertEquals(listMatchPattern44(x1, [1, t1, "int", "int"]), "match 1"); assertEquals(listMatchPattern44(x2, [1, t1, "int", "int", "int", "int", ["int", "int", "int"]]), "match 3"); @@ -1348,8 +1344,8 @@ public function testListMatchPattern44() { assertEquals(listMatchPattern44(y5, [t2, t2]), "match 5"); } -function listMatchPattern44(T12LMP|T13LMP t, anydata a) returns string? { - if t is T12LMP { +function listMatchPattern44(T12|T13 t, anydata a) returns string? { + if t is T12 { match t { [var p, var x, var y, var z] => { assertEquals([p, x, y, z], a); @@ -1398,19 +1394,18 @@ function listMatchPattern44(T12LMP|T13LMP t, anydata a) returns string? { } } -public type T14LMP [string]|[int, string]|[int, int, string]; - -public type T15LMP [int]|[T15LMP, T15LMP]|[T15LMP[], T15LMP[], T15LMP[]]; +public type T14 [string]|[int, string]|[int, int, string]; +public type T15 [int]|[T15, T15]|[T15[], T15[], T15[]]; public function testListMatchPattern45() { - T14LMP x1 = ["string"]; - T14LMP x2 = [1, "string"]; - T14LMP x3 = [1, 1, "string"]; + T14 x1 = ["string"]; + T14 x2 = [1, "string"]; + T14 x3 = [1, 1, "string"]; - T15LMP y1 = [1]; - T15LMP[] t2 = [y1, y1]; - T15LMP y2 = [y1, y1]; - T15LMP y3 = [t2, t2, t2]; + T15 y1 = [1]; + T15[] t2 = [y1, y1]; + T15 y2 = [y1, y1]; + T15 y3 = [t2, t2, t2]; assertEquals(listMatchPattern45(x1, x1), "match 3"); assertEquals(listMatchPattern45(x2, x2), "match 2"); @@ -1421,7 +1416,7 @@ public function testListMatchPattern45() { assertEquals(listMatchPattern45(y3, y3), "match 1"); } -function listMatchPattern45(T14LMP|T15LMP t, anydata a) returns string? { +function listMatchPattern45(T14|T15 t, anydata a) returns string? { match t { [var p, var x, var y, ...var z] => { assertEquals([p, x, y], a); @@ -1441,14 +1436,14 @@ function listMatchPattern45(T14LMP|T15LMP t, anydata a) returns string? { } } -public type T16LMP [string, int]; +public type T16 [string, int]; public function testListMatchPattern46() { assertEquals(listMatchPattern46(), "string"); } public function listMatchPattern46() returns string { - T16LMP a = ["string", 1]; + T16 a = ["string", 1]; string b; match a { [_, var x] => { @@ -1458,20 +1453,17 @@ public function listMatchPattern46() returns string { return b; } -type DataLMP string|DataLMP[]; - -type Data2LMP ["call", string, DataLMP...]; - -type Data3LMP ["branch", string]; - -type Data4LMP Data2LMP|Data3LMP; +type Data string|Data[]; +type Data2 ["call", string, Data...]; +type Data3 ["branch", string]; +type Data4 Data2|Data3; public function testListMatchPattern47() { assertEquals(listMatchPattern47(["branch", "b.target"]), "match 2"); assertEquals(listMatchPattern47(["call", "add", "1", "2"]), "match 1"); } -function listMatchPattern47(Data4LMP d) returns string { +function listMatchPattern47(Data4 d) returns string { match d { ["call", "add", ...var operands] => { return "match 1"; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/statements/matchstmt/match-stmt-type-narrow.bal b/tests/jballerina-unit-test/src/test/resources/test-src/statements/matchstmt/match-stmt-type-narrow.bal index 2c57d02fd94a..fb4d64647048 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/statements/matchstmt/match-stmt-type-narrow.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/statements/matchstmt/match-stmt-type-narrow.bal @@ -226,19 +226,19 @@ function testMatchClauseWithTypeGuard6() { assertEquals("Int or String", matched); } -type PersonMtStmt record {| +type Person record {| string name; int age; - AddressMtStmt address; + Address address; |}; -type AddressMtStmt record { +type Address record { string street; int houseNo; string city; }; -type AddressWithProvinceMtStmt record { +type AddressWithProvince record { string street; int houseNo; string city; @@ -248,20 +248,20 @@ type AddressWithProvinceMtStmt record { type E 100|200; function testMatchClauseWithTypeGuard7() { - PersonMtStmt person = {name: "John", age: 12, address: {street: "Main Street", houseNo:10, city: "Colombo", + Person person = {name: "John", age: 12, address: {street: "Main Street", houseNo:10, city: "Colombo", "country": "Sri Lanka"}}; string matched = "Not Matched"; int age = 0; string street = ""; - PersonMtStmt newPerson = person; + Person newPerson = person; match person { - {name: var a, ...var b} if a is string && b is record {|int age; AddressWithProvinceMtStmt address;|} => { + {name: var a, ...var b} if a is string && b is record {|int age; AddressWithProvince address;|} => { matched = "Pattern1"; age = b.age; street = b.address.street; } - {name: var a, ...var b} if a is string && b is record {|int age; AddressMtStmt address;|} => { + {name: var a, ...var b} if a is string && b is record {|int age; Address address;|} => { matched = "Pattern2"; age = b.age; street = b.address.street; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/statements/matchstmt/structured_record_match_patterns.bal b/tests/jballerina-unit-test/src/test/resources/test-src/statements/matchstmt/structured_record_match_patterns.bal index b37e6d5fabab..dcdad44551b9 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/statements/matchstmt/structured_record_match_patterns.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/statements/matchstmt/structured_record_match_patterns.bal @@ -14,14 +14,14 @@ // specific language governing permissions and limitations // under the License. -type FooSRMP record { +type Foo record { string s; int i; float f; }; function testStructuredMatchPatternsBasic1() returns string { - FooSRMP foo = {s: "S", i: 23, f: 5.6}; + Foo foo = {s: "S", i: 23, f: 5.6}; match foo { var {s, i: integer, f} => { @@ -32,14 +32,14 @@ function testStructuredMatchPatternsBasic1() returns string { return "Default"; } -type BarSRMP record { +type Bar record { byte b; - FooSRMP f; + Foo f; }; function testStructuredMatchPatternsBasic2() returns string { - FooSRMP foo = {s: "S", i: 23, f: 5.6}; - BarSRMP bar = {b: 12, f: foo}; + Foo foo = {s: "S", i: 23, f: 5.6}; + Bar bar = {b: 12, f: foo}; match bar { var {b: byteValue, f: {s, i, f}} => { @@ -52,8 +52,8 @@ function testStructuredMatchPatternsBasic2() returns string { } function testStructuredMatchPatternsBasic3() returns string { - FooSRMP foo = {s: "S", i: 23, f: 5.6}; - BarSRMP bar = {b: 12, f: foo}; + Foo foo = {s: "S", i: 23, f: 5.6}; + Bar bar = {b: 12, f: foo}; match bar { var {b, f} => { @@ -65,8 +65,8 @@ function testStructuredMatchPatternsBasic3() returns string { } function testStructuredMatchPatternsBasic4() returns string { - FooSRMP foo = {s: "S", i: 23, f: 5.6}; - BarSRMP bar = {b: 12, f: foo}; + Foo foo = {s: "S", i: 23, f: 5.6}; + Bar bar = {b: 12, f: foo}; match bar { var {a} => { @@ -105,17 +105,17 @@ function testStructuredMatchPatternsBasics5() returns string[] { ClosedFoo3 foo3 = {var1: "Hello", var2: 150, var3: true}; ClosedFoo4 foo4 = {var1: "Hello"}; - ClosedFoo1|ClosedFoo2|ClosedFoo3|ClosedFoo4 a1 = foo1; - ClosedFoo1|ClosedFoo2|ClosedFoo3|ClosedFoo4 a2 = foo2; - ClosedFoo1|ClosedFoo2|ClosedFoo3|ClosedFoo4 a3 = foo3; - ClosedFoo1|ClosedFoo2|ClosedFoo3|ClosedFoo4 a4 = foo4; + ClosedFoo1 | ClosedFoo2 | ClosedFoo3 | ClosedFoo4 a1 = foo1; + ClosedFoo1 | ClosedFoo2 | ClosedFoo3 | ClosedFoo4 a2 = foo2; + ClosedFoo1 | ClosedFoo2 | ClosedFoo3 | ClosedFoo4 a3 = foo3; + ClosedFoo1 | ClosedFoo2 | ClosedFoo3 | ClosedFoo4 a4 = foo4; string[] result = [basicMatch(a1), basicMatch(a2), basicMatch(a3), basicMatch(a4)]; return result; } -function basicMatch(ClosedFoo1|ClosedFoo2|ClosedFoo3|ClosedFoo4 a) returns string { +function basicMatch(ClosedFoo1 | ClosedFoo2 | ClosedFoo3 | ClosedFoo4 a) returns string { match a { var {var1, var2, var3} => { return "Matched with three vars : " + var1.toString() + ", " + @@ -146,16 +146,16 @@ function testStructuredMatchPatternComplex1() returns string[] { ClosedBar1 bar1 = {var1: "Ballerina", var2: 500}; ClosedBar2 bar2 = {var1: "Language", var2: bar1}; - ClosedBar1|ClosedBar2|string a1 = bar1; - ClosedBar1|ClosedBar2|string a2 = bar2; - ClosedBar1|ClosedBar2|string a3 = "bar2"; + ClosedBar1 | ClosedBar2 | string a1 = bar1; + ClosedBar1 | ClosedBar2 | string a2 = bar2; + ClosedBar1 | ClosedBar2 | string a3 = "bar2"; string[] result = [complexMatch(a1), complexMatch(a2), complexMatch(a3)]; return result; } -function complexMatch(ClosedBar1|ClosedBar2|string a) returns string { +function complexMatch(ClosedBar1 | ClosedBar2 | string a) returns string { match a { var {var1, var2: {var1: v1, var2}} => { return "Matched with three vars : " + var1.toString() + ", " + v1.toString() + @@ -172,22 +172,16 @@ function complexMatch(ClosedBar1|ClosedBar2|string a) returns string { function testRuntimeCheck() returns string[] { [int, boolean] tuple = [50, true]; - FooSRMP foo1 = {s: "S", i: 23, f: 5.6, "t": tuple}; - FooSRMP foo2 = {s: "S", i: 23, f: 5.6}; - FooSRMP foo3 = {s: "S", i: 23, f: 5.6, "t": 12}; - - string[] values = [ - matchRuntimeCheck(foo1), - matchRuntimeCheck(foo2), - matchRuntimeCheck(foo3), - matchRuntimeCheckWithAny(foo1), - matchRuntimeCheckWithAny(foo2), - matchRuntimeCheckWithAny(foo3) - ]; + Foo foo1 = {s: "S", i: 23, f: 5.6, "t": tuple}; + Foo foo2 = {s: "S", i: 23, f: 5.6}; + Foo foo3 = {s: "S", i: 23, f: 5.6, "t": 12}; + + string[] values = [matchRuntimeCheck(foo1), matchRuntimeCheck(foo2), matchRuntimeCheck(foo3), + matchRuntimeCheckWithAny(foo1), matchRuntimeCheckWithAny(foo2), matchRuntimeCheckWithAny(foo3)]; return values; } -function matchRuntimeCheck(FooSRMP foo) returns string { +function matchRuntimeCheck(Foo foo) returns string { match foo { var {s, i, f, t: [i2, b]} => { return "Matched with five vars : " + s.toString() + ", " + i.toString() + diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/types/anydata/anydata_test.bal b/tests/jballerina-unit-test/src/test/resources/test-src/types/anydata/anydata_test.bal index 085c964a8034..c135cd5ec49d 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/types/anydata/anydata_test.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/types/anydata/anydata_test.bal @@ -14,8 +14,6 @@ // specific language governing permissions and limitations // under the License. -import ballerina/lang.regexp; - type Foo record { int a = 0; }; @@ -274,7 +272,7 @@ function testAnydataArray() returns anydata[] { } type ValueType int|float|string|boolean|byte|decimal; -type DataType ValueType|table>|json|xml|regexp:RegExp|ClosedFoo|Foo|map|anydata[]|(); +type DataType ValueType|table>|json|xml|ClosedFoo|Foo|map|anydata[]|(); function testUnionAssignment() returns anydata[] { anydata[] rets = []; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/types/never/never_type_is_expr_negative.bal b/tests/jballerina-unit-test/src/test/resources/test-src/types/never/never_type_is_expr_negative.bal deleted file mode 100644 index ecb769e0f29d..000000000000 --- a/tests/jballerina-unit-test/src/test/resources/test-src/types/never/never_type_is_expr_negative.bal +++ /dev/null @@ -1,47 +0,0 @@ - // Copyright (c) 2024 WSO2 LLC. (http://www.wso2.com). - // - // WSO2 LLC. licenses this file to you under the Apache License, - // Version 2.0 (the "License"); you may not use this file except - // in compliance with the License. - // You may obtain a copy of the License at - // - // http://www.apache.org/licenses/LICENSE-2.0 - // - // Unless required by applicable law or agreed to in writing, - // software distributed under the License is distributed on an - // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - // KIND, either express or implied. See the License for the - // specific language governing permissions and limitations - // under the License. - -function testNeverRuntime10() { - int x = 100; - boolean _ = x is never; -} - -type Record record {| - int i; - never[] j; -|}; - -function testNeverRuntime11() { - Record x = {i: 1, j: []}; - boolean _ = x is never; -} - -function testNeverFieldTypeCheck() { - record {int x;} r2 = {x: 2, "color": "blue"}; - boolean _ = r2 is record {never x?;}; - - record {never? x;} r3 = {x: (), "color": "blue"}; - boolean _ = r3 is record {never x?;}; - - record {int? x;} r4 = {x: 2, "color": "blue"}; - boolean _ = r4 is record {never x?;}; - - record {int x;} & readonly v3 = {x: 2, "color": "blue"}; - boolean _ = v3 is record {never x?;}; - - record {never? x;} & readonly v4 = {x: (), "color": "blue"}; - boolean _ = v4 is record {never x?;}; -} diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/types/never/never_type_runtime.bal b/tests/jballerina-unit-test/src/test/resources/test-src/types/never/never_type_runtime.bal index 2d6620d7f835..645ac4b21f79 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/types/never/never_type_runtime.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/types/never/never_type_runtime.bal @@ -72,6 +72,12 @@ function testNeverRuntime9() { assertEquality(true, b); } +function testNeverRuntime10() { + int x = 100; + boolean b = x is never; + assertEquality(false, b); +} + type Record record {| int i; never[] j; @@ -82,6 +88,12 @@ type Record2 record {| never[] j = []; |}; +function testNeverRuntime11() { + Record x = { i: 1, j: [] }; + boolean b = x is never; + assertEquality(false, b); +} + function testNeverRuntime12() { Record x = {i: 1, j: []}; boolean b = x is Record2; @@ -129,6 +141,15 @@ function testNeverFieldTypeCheck() { record {} r1 = {"x": 2, "color": "blue"}; assertEquality(false, r1 is record {never x?;}); + record {int x;} r2 = {x: 2, "color": "blue"}; + assertEquality(false, r2 is record {never x?;}); + + record {never? x;} r3 = {x: (), "color": "blue"}; + assertEquality(false, r3 is record {never x?;}); + + record {int? x;} r4 = {x: 2, "color": "blue"}; + assertEquality(false, r4 is record {never x?;}); + record {} r5 = {}; assertEquality(false, r5 is record {never x?;}); @@ -186,6 +207,12 @@ function testNeverFieldTypeCheck() { record {} & readonly v2 = {"x": 2}; assertEquality(false, v2 is record {never x?;}); + record {int x;} & readonly v3 = {x: 2, "color": "blue"}; + assertEquality(false, v3 is record {never x?;}); + + record {never? x;} & readonly v4 = {x: (), "color": "blue"}; + assertEquality(false, v4 is record {never x?;}); + record {never? x;} & readonly v5 = {x: (), "color": "blue"}; assertEquality(true, v5 is record {never? x;}); diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_inherently_immutable_type_negative.bal b/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_inherently_immutable_type_negative.bal index de9645cfba02..9603606618b0 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_inherently_immutable_type_negative.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_inherently_immutable_type_negative.bal @@ -19,6 +19,11 @@ any x = y; } + function cannotDeepEqualReadonly() returns boolean { + readonly arr = [1, 2 , 3]; + return arr == [1, 2 , 3]; + } + function testReadOnlyAssignabilityToUnions() { readonly readonlyVal = 1; error? errOrNil = readonlyVal; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_selectively_immutable_type.bal b/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_selectively_immutable_type.bal index 459d0ee84059..89489482b63d 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_selectively_immutable_type.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_selectively_immutable_type.bal @@ -64,12 +64,12 @@ function testSimpleInitializationForSelectivelyImmutableXmlTypes() { assertEquality(c, r4); } -type EmployeeFoo record {| - DetailsBar details; +type Employee record {| + Details details; string department; |}; -type DetailsBar record {| +type Details record {| string name; int id; |}; @@ -78,9 +78,9 @@ function testSimpleInitializationForSelectivelyImmutableListTypes() { int[] & readonly a = [1, 2]; readonly r1 = a; assertTrue(r1 is int[] & readonly); - assertEquality([1, 2], r1); + assertEquality( [1, 2], r1); - EmployeeFoo & readonly emp = { + Employee & readonly emp = { details: { name: "Emma", id: 1234 @@ -88,60 +88,60 @@ function testSimpleInitializationForSelectivelyImmutableListTypes() { department: "finance" }; - [EmployeeFoo, EmployeeFoo] & readonly b = [emp, {details: {name: "Jo", id: 5678}, department: "IT"}]; + [Employee, Employee] & readonly b = [emp, {details: {name: "Jo", id: 5678}, department: "IT"}]; readonly r2 = b; - assertTrue(r2 is [EmployeeFoo, EmployeeFoo] & readonly); - assertTrue(r2 is EmployeeFoo[2] & readonly); + assertTrue(r2 is [Employee, Employee] & readonly); + assertTrue(r2 is Employee[2] & readonly); - [EmployeeFoo, EmployeeFoo] & readonly empTup = <[EmployeeFoo, EmployeeFoo] & readonly>checkpanic r2; + [Employee, Employee] & readonly empTup = <[Employee, Employee] & readonly> checkpanic r2; assertEquality(emp, empTup[0]); record {} rec = empTup[0]; - assertTrue(rec is EmployeeFoo & readonly); + assertTrue(rec is Employee & readonly); assertTrue(rec.isReadOnly()); rec = empTup[1]; - assertTrue(rec is EmployeeFoo & readonly); + assertTrue(rec is Employee & readonly); assertTrue(rec.isReadOnly()); assertEquality("IT", rec["department"]); - assertTrue(rec["details"] is DetailsBar & readonly); + assertTrue(rec["details"] is Details & readonly); assertTrue(rec["details"].isReadOnly()); - DetailsBar & readonly details = { + Details & readonly details = { name: "Jo", id: 9876 }; - [DetailsBar[], EmployeeFoo...] & readonly detEmpTup = [ - [{name: "May", id: 1234}, details], - {details, department: "finance"} - ]; + [Details[], Employee...] & readonly detEmpTup = [ + [{name: "May", id: 1234}, details], + {details, department: "finance"} + ]; readonly r3 = detEmpTup; - assertTrue(r3 is [DetailsBar[], EmployeeFoo...] & readonly); - assertTrue(r3 is [[DetailsBar, DetailsBar], EmployeeFoo] & readonly); + assertTrue(r3 is [Details[], Employee...] & readonly); + assertTrue(r3 is [[Details, Details], Employee] & readonly); - [[DetailsBar, DetailsBar], EmployeeFoo] & readonly vals = <[[DetailsBar, DetailsBar], EmployeeFoo] & readonly>checkpanic r3; + [[Details, Details], Employee] & readonly vals = <[[Details, Details], Employee] & readonly> checkpanic r3; assertTrue(vals[0].isReadOnly()); - DetailsBar d1 = vals[0][0]; - assertEquality({name: "May", id: 1234}, d1); + Details d1 = vals[0][0]; + assertEquality(
{name: "May", id: 1234}, d1); assertTrue(d1.isReadOnly()); - DetailsBar d2 = vals[0][1]; + Details d2 = vals[0][1]; assertEquality(details, d2); assertTrue(d2.isReadOnly()); - EmployeeFoo e = vals[1]; - assertEquality({details, department: "finance"}, e); + Employee e = vals[1]; + assertEquality( {details, department: "finance"}, e); assertTrue(e.isReadOnly()); assertTrue(e.details.isReadOnly()); (int[] & readonly)|string[] arr = [1, 2]; - assertEquality([1, 2], arr); + assertEquality( [1, 2], arr); assertTrue(arr is int[] & readonly); assertTrue(arr.isReadOnly()); arr = ["hello"]; - assertEquality(["hello"], arr); + assertEquality( ["hello"], arr); assertTrue(arr is string[]); assertFalse(arr is string[] & readonly); assertFalse(arr.isReadOnly()); @@ -157,9 +157,9 @@ function testSimpleInitializationForSelectivelyImmutableMappingTypes() { }; readonly r1 = a; assertTrue(r1 is map & readonly); - assertEquality(>{a: true, bool: false, c: false}, r1); + assertEquality(> {a: true, bool: false, c: false}, r1); - EmployeeFoo & readonly emp = { + Employee & readonly emp = { details: { name: "Emma", id: 1234 @@ -168,20 +168,20 @@ function testSimpleInitializationForSelectivelyImmutableMappingTypes() { }; readonly r2 = emp; - assertTrue(r2 is EmployeeFoo & readonly); + assertTrue(r2 is Employee & readonly); assertEquality(emp, r2); any|error val = r2; assertFalse(val is error); - EmployeeFoo rec = checkpanic val; - assertTrue(rec is EmployeeFoo & readonly); + Employee rec = checkpanic val; + assertTrue(rec is Employee & readonly); assertTrue(rec.isReadOnly()); - DetailsBar det = rec.details; - assertTrue(det is DetailsBar & readonly); + Details det = rec.details; + assertTrue(det is Details & readonly); assertTrue(det.isReadOnly()); - StudentFoo & readonly st = { + Student & readonly st = { details: { name: "Jo", id: 4567 @@ -190,25 +190,25 @@ function testSimpleInitializationForSelectivelyImmutableMappingTypes() { "science": ["P", 65] }; readonly r3 = st; - assertTrue(r3 is StudentFoo & readonly); + assertTrue(r3 is Student & readonly); val = r3; assertFalse(val is error); - StudentFoo stVal = checkpanic val; + Student stVal = checkpanic val; assertTrue(stVal.isReadOnly()); assertTrue(stVal.details.isReadOnly()); - assertEquality({name: "Jo", id: 4567}, stVal.details); + assertEquality(
{name: "Jo", id: 4567}, stVal.details); - assertTrue(stVal["math"] is [RESULTFoo, int] & readonly); + assertTrue(stVal["math"] is [RESULT, int] & readonly); assertTrue(stVal["math"].isReadOnly()); - assertEquality(<[RESULTFoo, int]>["P", 75], stVal["math"]); + assertEquality(<[RESULT, int]> ["P", 75], stVal["math"]); - assertTrue(stVal["science"] is [RESULTFoo, int] & readonly); + assertTrue(stVal["science"] is [RESULT, int] & readonly); assertTrue(stVal["science"].isReadOnly()); - assertEquality(<[RESULTFoo, int]>["P", 65], stVal["science"]); + assertEquality(<[RESULT, int]> ["P", 65], stVal["science"]); } -type IdentifierFoo record {| +type Identifier record {| readonly string name; int id; |}; @@ -222,41 +222,41 @@ function testSimpleInitializationForSelectivelyImmutableTableTypes() { readonly r1 = a; assertTrue(r1 is table> & readonly); - table> tbString = >>checkpanic r1; + table> tbString = >> checkpanic r1; assertEquality(2, tbString.length()); map[] mapArr = tbString.toArray(); - assertTrue(mapArr[0] is map & readonly); - assertEquality(>{x: "x", y: "y"}, mapArr[0]); - assertTrue(mapArr[1] is map & readonly); - assertEquality(>{z: "z"}, mapArr[1]); + assertTrue( mapArr[0] is map & readonly); + assertEquality(> {x: "x", y: "y"}, mapArr[0]); + assertTrue( mapArr[1] is map & readonly); + assertEquality(> {z: "z"}, mapArr[1]); - table key(name) & readonly b = table [ + table key(name) & readonly b = table [ {name: "Jo", id: 4567}, {name: "Emma", id: 1234}, {name: "Amy", id: 678} ]; readonly r2 = b; - assertTrue(r2 is table key(name) & readonly); - assertTrue(r2 is table & readonly); + assertTrue(r2 is table key(name) & readonly); + assertTrue(r2 is table & readonly); - table tbDetails = >checkpanic r2; + table tbDetails = > checkpanic r2; assertEquality(3, tbDetails.length()); - IdentifierFoo[] detailsArr = tbDetails.toArray(); - assertTrue(detailsArr[0] is IdentifierFoo & readonly); - assertEquality({name: "Jo", id: 4567}, detailsArr[0]); - assertTrue(detailsArr[1] is IdentifierFoo & readonly); - assertEquality({name: "Emma", id: 1234}, detailsArr[1]); - assertTrue(detailsArr[2] is IdentifierFoo & readonly); - assertEquality({name: "Amy", id: 678}, detailsArr[2]); + Identifier[] detailsArr = tbDetails.toArray(); + assertTrue(detailsArr[0] is Identifier & readonly); + assertEquality( {name: "Jo", id: 4567}, detailsArr[0]); + assertTrue(detailsArr[1] is Identifier & readonly); + assertEquality( {name: "Emma", id: 1234}, detailsArr[1]); + assertTrue(detailsArr[2] is Identifier & readonly); + assertEquality( {name: "Amy", id: 678}, detailsArr[2]); } -type RESULTFoo "P"|"F"; +type RESULT "P"|"F"; -type StudentFoo record {| - DetailsBar details; - [RESULTFoo, int]...; +type Student record {| + Details details; + [RESULT, int]...; |}; type recursiveTuple [int, string|xml, recursiveTuple...]; @@ -296,7 +296,7 @@ function testRuntimeIsTypeForSelectivelyImmutableBasicTypes() { assertFalse(k is readonly); assertTrue(l is readonly); - EmployeeFoo m = { + Employee m = { details: { name: "Maryam", id: 9876 @@ -317,7 +317,7 @@ function testRuntimeIsTypeNegativeForSelectivelyImmutableTypes() { assertFalse(an1 is readonly); assertFalse(a1.isReadOnly()); - EmployeeFoo emp = { + Employee emp = { details: { name: "Emma", id: 1234 @@ -325,54 +325,54 @@ function testRuntimeIsTypeNegativeForSelectivelyImmutableTypes() { department: "finance" }; - [EmployeeFoo, EmployeeFoo] b = [emp, {details: {name: "Jo", id: 5678}, department: "IT"}]; + [Employee, Employee] b = [emp, {details: {name: "Jo", id: 5678}, department: "IT"}]; anydata a2 = b; any an2 = b; - assertFalse(an2 is [EmployeeFoo, EmployeeFoo] & readonly); + assertFalse(an2 is [Employee, Employee] & readonly); assertFalse(an2 is readonly); assertFalse(a2.isReadOnly()); - [EmployeeFoo, EmployeeFoo] empTup = <[EmployeeFoo, EmployeeFoo]>a2; + [Employee, Employee] empTup = <[Employee, Employee]> a2; assertEquality(emp, empTup[0]); record {} rec = empTup[0]; - assertTrue(rec is EmployeeFoo); - assertFalse(rec is EmployeeFoo & readonly); + assertTrue(rec is Employee); + assertFalse(rec is Employee & readonly); assertFalse(rec.isReadOnly()); rec = empTup[1]; - assertTrue(rec is EmployeeFoo); - assertFalse(rec is EmployeeFoo & readonly); + assertTrue(rec is Employee); + assertFalse(rec is Employee & readonly); assertFalse(rec.isReadOnly()); - assertTrue(rec["details"] is DetailsBar); - assertFalse(rec["details"] is DetailsBar & readonly); + assertTrue(rec["details"] is Details); + assertFalse(rec["details"] is Details & readonly); assertFalse(rec["details"].isReadOnly()); - DetailsBar & readonly details = { + Details & readonly details = { name: "Jo", id: 9876 }; - [DetailsBar[], EmployeeFoo...] detEmpTup = [ - [{name: "May", id: 1234}, details], - {details, department: "finance"} - ]; + [Details[], Employee...] detEmpTup = [ + [{name: "May", id: 1234}, details], + {details, department: "finance"} + ]; anydata a3 = detEmpTup; - assertTrue(a3 is [DetailsBar[], EmployeeFoo...]); - assertFalse(a3 is [DetailsBar[], EmployeeFoo...] & readonly); - assertFalse(a3 is [[DetailsBar, DetailsBar], EmployeeFoo] & readonly); + assertTrue(a3 is [Details[], Employee...]); + assertFalse(a3 is [Details[], Employee...] & readonly); + assertFalse(a3 is [[Details, Details], Employee] & readonly); - [DetailsBar[], EmployeeFoo...] vals = <[DetailsBar[], EmployeeFoo...]>a3; + [Details[], Employee...] vals = <[Details[], Employee...]> a3; assertFalse(vals[0].isReadOnly()); - DetailsBar d1 = vals[0][0]; + Details d1 = vals[0][0]; assertFalse(d1.isReadOnly()); - DetailsBar d2 = vals[0][1]; + Details d2 = vals[0][1]; assertEquality(details, d2); assertTrue(d2.isReadOnly()); - EmployeeFoo e = vals[1]; - assertEquality({details, department: "finance"}, e); + Employee e = vals[1]; + assertEquality( {details, department: "finance"}, e); assertFalse(e.isReadOnly()); assertTrue(e.details.isReadOnly()); @@ -396,8 +396,8 @@ function testRuntimeIsTypeNegativeForSelectivelyImmutableTypes() { assertFalse(an5 is readonly); assertFalse(a5.isReadOnly()); - json[] jsonVal = an5; - map a8 = >jsonVal[1]; + json[] jsonVal = an5; + map a8 = > jsonVal[1]; any an8 = a8; assertFalse(a8 is map & readonly); assertFalse(an8 is readonly); @@ -421,15 +421,15 @@ function testRuntimeIsTypeNegativeForSelectivelyImmutableTypes() { assertFalse(an7 is readonly); assertFalse(a7.isReadOnly()); - table key(name) j = table [ + table key(name) j = table [ {name: "Jo", id: 4567}, {name: "Emma", id: 1234}, {name: "Amy", id: 678} ]; anydata a9 = j; any an9 = j; - assertTrue(an9 is table); - assertFalse(an9 is table & readonly); + assertTrue(an9 is table); + assertFalse(an9 is table & readonly); assertFalse(an9 is readonly); assertFalse(a9.isReadOnly());