Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Port nBallerina readonly and error types #42663

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 19 additions & 8 deletions semtypes/src/main/java/io/ballerina/types/Error.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,16 @@

import io.ballerina.types.subtypedata.AllOrNothingSubtype;
import io.ballerina.types.subtypedata.BddNode;
import io.ballerina.types.typeops.BddCommonOps;

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.createRecAtom;
import static io.ballerina.types.typeops.BddCommonOps.bddAtom;
import static io.ballerina.types.typeops.BddCommonOps.bddIntersect;

/**
* Contain functions found in error.bal file.
Expand All @@ -28,22 +37,24 @@
*/
public class Error {
public static SemType errorDetail(SemType detail) {
SubtypeData sd = Core.subtypeData(detail, BasicTypeCode.BT_MAPPING); // TODO: type should be MAPPING_RO
SubtypeData sd = bddIntersect((Bdd) subtypeData(detail, BasicTypeCode.BT_MAPPING), BDD_SUBTYPE_RO);
if (sd instanceof AllOrNothingSubtype allOrNothingSubtype) {
if (allOrNothingSubtype.isAllSubtype()) {
return PredefinedType.ERROR;
return ERROR;
} else {
// XXX This should be reported as an error
return PredefinedType.NEVER;
return NEVER;
}
} else {
return PredefinedType.basicSubtype(BasicTypeCode.BT_ERROR, (ProperSubtypeData) sd);
}
if (sd == BDD_SUBTYPE_RO) {
return ERROR;
}
return basicSubtype(BT_ERROR, (ProperSubtypeData) sd);
}

// distinctId must be >= 0
public SemType errorDistinct(int distinctId) {
BddNode bdd = BddCommonOps.bddAtom(RecAtom.createRecAtom(-distinctId - 1));
return PredefinedType.basicSubtype(BasicTypeCode.BT_ERROR, bdd);
BddNode bdd = bddAtom(createRecAtom(-distinctId - 1));
lochana-chathura marked this conversation as resolved.
Show resolved Hide resolved
return basicSubtype(BT_ERROR, bdd);
}
}
35 changes: 24 additions & 11 deletions semtypes/src/main/java/io/ballerina/types/PredefinedType.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import static io.ballerina.types.BasicTypeCode.BT_LIST;
import static io.ballerina.types.BasicTypeCode.BT_MAPPING;
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.intersect;
import static io.ballerina.types.Core.union;
Expand All @@ -41,6 +43,7 @@
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.
Expand Down Expand Up @@ -148,7 +151,7 @@ BT_CELL, bddAtom(ATOM_CELL_INNER_MAPPING)

public static final int BDD_REC_ATOM_READONLY = 0;
// represents both readonly & map<readonly> and readonly & readonly[]
private static final BddNode BDD_SUBTYPE_RO = bddAtom(RecAtom.createRecAtom(BDD_REC_ATOM_READONLY));
public static final BddNode BDD_SUBTYPE_RO = bddAtom(RecAtom.createRecAtom(BDD_REC_ATOM_READONLY));
// represents (map<any|error>)[]
public static final ComplexSemType MAPPING_RO = basicSubtype(BT_MAPPING, BDD_SUBTYPE_RO);

Expand All @@ -167,10 +170,11 @@ BT_CELL, bddAtom(ATOM_CELL_INNER_MAPPING_RO)
// represents readonly & (map<readonly>)[]
static final BddNode LIST_SUBTYPE_MAPPING_RO = bddAtom(ATOM_LIST_MAPPING_RO);

public static final SemType VAL_READONLY = createComplexSemType(IMPLEMENTED_INHERENTLY_IMMUTABLE,
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_MAPPING_RO)
BasicSubtype.from(BT_TABLE, LIST_SUBTYPE_MAPPING_RO),
BasicSubtype.from(BT_XML, XML_SUBTYPE_RO)
);
public static final SemType IMPLEMENTED_VAL_READONLY = createComplexSemType(IMPLEMENTED_INHERENTLY_IMMUTABLE,
BasicSubtype.from(BT_LIST, BDD_SUBTYPE_RO)
Expand Down Expand Up @@ -244,27 +248,36 @@ static String toString(BasicTypeBitSet ut) {
if ((ut.bitset & ERROR.bitset) != 0) {
sb.add("error");
}
if ((ut.bitset & LIST.bitset) != 0) {
sb.add("list");
}
if ((ut.bitset & FUNCTION.bitset) != 0) {
sb.add("function");
}
if ((ut.bitset & TYPEDESC.bitset) != 0) {
sb.add("typedesc");
}
if ((ut.bitset & HANDLE.bitset) != 0) {
sb.add("handle");
}
if ((ut.bitset & BasicTypeCode.VT_INHERENTLY_IMMUTABLE) != 0) { // TODO: fix when porting readonly
sb.add("readonly");
if ((ut.bitset & FUNCTION.bitset) != 0) {
sb.add("function");
}
lochana-chathura marked this conversation as resolved.
Show resolved Hide resolved
if ((ut.bitset & FUTURE.bitset) != 0) {
sb.add("future");
}
if ((ut.bitset & STREAM.bitset) != 0) {
sb.add("stream");
}
if ((ut.bitset & LIST.bitset) != 0) {
sb.add("list");
}
if ((ut.bitset & MAPPING.bitset) != 0) {
sb.add("map");
}
if ((ut.bitset & TABLE.bitset) != 0) {
sb.add("table");
}
if ((ut.bitset & XML.bitset) != 0) {
sb.add("xml");
}
if ((ut.bitset & OBJECT.bitset) != 0) {
sb.add("object");
}
if ((ut.bitset & CELL.bitset) != 0) {
sb.add("cell");
}
Expand Down
33 changes: 31 additions & 2 deletions semtypes/src/main/java/io/ballerina/types/typeops/ErrorOps.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,48 @@
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<any|error>` rather than `readonly & map<readonly>`.
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) {
// TODO: implement bddPosMaybeEmpty
throw new UnsupportedOperationException("Unimplemented");
return errorSubtypeIsEmpty(cx, t);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -273,9 +273,9 @@ public void stringTest() {
Assert.assertEquals(result.get(1).value, "d");
}

@Test(enabled = false)
public void roTest() {
SemType t1 = PredefinedType.basicType(BasicTypeCode.BT_LIST); // TODO: type should be LIST_RO
@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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
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;
Expand Down Expand Up @@ -165,6 +166,8 @@ public SemType resolveTypeDesc(Context cx, Map<String, BLangNode> mod, BLangType
return resolveTypeDesc(cx, mod, defn, depth, (BLangFunctionTypeNode) td);
case TABLE_TYPE:
return resolveTypeDesc(cx, mod, depth, (BLangTableTypeNode) td);
case ERROR_TYPE:
return resolveTypeDesc(cx, mod, defn, depth, (BLangErrorType) td);
default:
throw new UnsupportedOperationException("type not implemented: " + td.getKind());
}
Expand Down Expand Up @@ -503,4 +506,14 @@ private SemType resolveTypeDesc(Context cx, Map<String, BLangNode> mod, int dept
SemType memberType = resolveTypeDesc(cx, mod, (BLangTypeDefinition) td.constraint.defn, depth, td.constraint);
return SemTypes.tableContaining(cx.env, memberType);
}

private SemType resolveTypeDesc(Context cx, Map<String, BLangNode> mod, BLangTypeDefinition defn, int depth,
BLangErrorType td) {
if (td.detailType == null) {
return PredefinedType.ERROR;
}

SemType detail = resolveTypeDesc(cx, mod, defn, depth, td.detailType);
return SemTypes.errorDetail(detail);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,24 +80,10 @@ public Object[] dataDirFileNameProvider() {

public final HashSet<String> dataDirSkipList() {
HashSet<String> hashSet = new HashSet<>();
// error type not supported yet
hashSet.add("basic.bal");
hashSet.add("error1.bal");
hashSet.add("error2.bal");

// readonly type not supported yet
hashSet.add("fixed-length-array.bal");
hashSet.add("fixed-length-array-tuple.bal");

// causes a stack overflow with mappingSubtypeIsEmpty
// https://github.com/ballerina-platform/ballerina-lang/issues/42662
hashSet.add("error1.bal");
hashSet.add("hard.bal");
// func type not supported yet
hashSet.add("function.bal"); // due to https://github.com/ballerina-platform/ballerina-lang/issues/35204
hashSet.add("never.bal");

// readonly type not supported yet
hashSet.add("readonly1.bal");
hashSet.add("readonly2.bal");
return hashSet;
}

Expand Down Expand Up @@ -175,18 +161,8 @@ public final HashSet<String> typeRelDirSkipList() {
hashSet.add("proj9-t.bal");
hashSet.add("proj10-t.bal");

// readonly type not supported yet
hashSet.add("fixed-length-array-t.bal");
hashSet.add("fixed-length-array-tuple-t.bal");

hashSet.add("xml-complex-ro-tv.bal");
hashSet.add("xml-readonly-tv.bal");
// Not a type test. This is an error test
hashSet.add("xml-te.bal");

// table type not supported yet
hashSet.add("anydata-tv.bal");
hashSet.add("table-t.bal");
hashSet.add("table2-t.bal");
return hashSet;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
// ROInt5<:IntArray
// ROInt5<:ROIntArray
// ROIntArray<:IntArray
// EmptyIntArray<:ROIntArray

type IntArray int[];

Expand All @@ -65,7 +66,6 @@ type Array5OfInt5 int[5][5];

type INT int;


type Array5OfIntArray int[5][];

type ROIntArray readonly & IntArray;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

type IntArray int[];
type Int5 int[5];
type ISTArray (1|2|3)[];

public const int MAX_VALUE = 9223372036854775807;

public const int MAX_VALUE_M_1 = MAX_VALUE - 1;

// -@type LargeArray < IntArray
type LargeArray int[MAX_VALUE];

// @type LargeArray2 < IntArray
// -@type LargeArray <> LargeArray2
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created #42684

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);

Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,9 @@ type ROIntArray readonly & IntArray;
// @type ROInt5 < ROIntArray
type ROInt5 readonly & int[5];

// ! not supported in JBallerina
// -@type ArrayExcept5 <> Int5;
// -@type ArrayExcept5 < IntArray;
//type ArrayExcept5 IntArray & !Int5;
type ArrayExcept5 IntArray & !Int5;

const FIVE = 5;

Expand Down Expand Up @@ -67,18 +66,3 @@ type Array7OfArray2OfInt5 Array2OfInt5[7];

// @type Array7x2x5 = Array7OfArray2OfInt5
type Array7x2x5 int[7][2][5];

//public const int MAX_VALUE = 9223372036854775807;
//public const int MAX_VALUE_M_1 = 9223372036854775806;
public const int MAX_VALUE = 2147483637;
public const int MAX_VALUE_M_1 = 2147483636;

// @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;
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type ReadOnlyFlat T|E|P|C;
// -@type C < NonEmptyRoSingletons
type NonEmptyRoSingletons ReadOnlyFlat & !N;

// @type NonEmptyRoSingletons < UX
// -@type NonEmptyRoSingletons < UX
type UX XE|XP|XC|T;

// -@type XNonEmptyRoSingletons = RX
Expand Down