Skip to content

Commit

Permalink
Rewrite isLaxType() check using semtypes
Browse files Browse the repository at this point in the history
  • Loading branch information
lochana-chathura committed Oct 1, 2024
1 parent 30bf60d commit 91ce09e
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import io.ballerina.types.Context;
import io.ballerina.types.Core;
import io.ballerina.types.Env;
import io.ballerina.types.MappingAtomicType;
import io.ballerina.types.PredefinedType;
import io.ballerina.types.SemType;
import io.ballerina.types.SemTypes;
Expand Down Expand Up @@ -324,41 +325,41 @@ public boolean isLaxFieldAccessAllowed(BType type) {
return false;
}

type = Types.getImpliedType(type);
Set<BType> visited = new HashSet<>();
return isLaxType(type, visited) == 1 || isAssignable(type, symTable.xmlType);
return SemTypeHelper.isSubtype(semTypeCtx, type, PredefinedType.XML) || isLaxType(type);
}

// TODO : clean
public int isLaxType(BType type, Set<BType> visited) {
type = getImpliedType(type);
if (!visited.add(type)) {
return -1;
private boolean isLaxType(BType type) {
SemType t = SemTypeHelper.semType(type);
return isLaxType(t);
}

/**
* Checks if the type is a lax type.
* <p>
* Rules:
* <ul>
* <li>json and readonly-json are lax</li>
* <li>map&lt;T&gt; is lax if T is lax</li>
* <li>U = T1|T2...|Tn is lax, if Ti is lax for all i.</li>
* </ul>
*
* @param t type to be checked
* @return true if t is lax
*/
private boolean isLaxType(SemType t) {
SemType json = Core.createJson(semTypeCtx);
if (SemTypes.isSubtype(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;

Optional<List<MappingAtomicType>> optMatList = Core.mappingAtomicTypesInUnion(semTypeCtx, t);
if (optMatList.isEmpty()) {
return false;
}
return 0;

List<MappingAtomicType> matList = optMatList.get();
return matList.stream().allMatch(mat -> mat.names().length == 0 && isLaxType(Core.cellInnerVal(mat.rest())));
}

public boolean isSameType(BType source, BType target) {
Expand Down
49 changes: 49 additions & 0 deletions semtypes/src/main/java/io/ballerina/types/Core.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
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;
Expand Down Expand Up @@ -770,4 +771,52 @@ public static SemType createBasicSemType(BasicTypeCode typeCode, SubtypeData sub
BasicSubtype.from(typeCode, (ProperSubtypeData) subtypeData));
}
}

// ------------------------- Newly Introduced APIs (Does not exist in nBallerina) --------------------------------

// Consider map<T1>|map<T2>|...|map<Tn>. This API will return all MappingAtomicTypes in the union.
public static Optional<List<MappingAtomicType>> mappingAtomicTypesInUnion(Context cx, SemType t) {
ArrayList<MappingAtomicType> 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<MappingAtomicType> 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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ static BddNode create(Atom atom, Bdd left, Bdd middle, Bdd right) {
}

private static boolean isSimpleNode(Bdd left, Bdd middle, Bdd right) {
return left instanceof AllOrNothingSubtype leftNode && leftNode.isAllSubtype() &&
middle instanceof AllOrNothingSubtype middleNode && middleNode.isNothingSubtype() &&
right instanceof AllOrNothingSubtype rightNode && rightNode.isNothingSubtype();
return left instanceof BddAllOrNothing leftNode && leftNode.isAll() &&
middle instanceof BddAllOrNothing middleNode && middleNode.isNothing() &&
right instanceof BddAllOrNothing rightNode && rightNode.isNothing();
}

Atom atom();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@
* @param right path that include this node's atom negatively
* @since 2201.10.0
*/
record BddNodeImpl(Atom atom, Bdd left, Bdd middle, Bdd right) implements BddNode {
public record BddNodeImpl(Atom atom, Bdd left, Bdd middle, Bdd right) implements BddNode {

}

0 comments on commit 91ce09e

Please sign in to comment.