Skip to content

Commit

Permalink
Merge pull request #26173 from suleka96/similarities_array_and_tuple
Browse files Browse the repository at this point in the history
Add missing similarity criteria between array and tuple types
  • Loading branch information
MaryamZi authored Oct 20, 2020
2 parents ada2b9b + 3d8c0e9 commit 25d759e
Show file tree
Hide file tree
Showing 28 changed files with 323 additions and 143 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public class BArrayType extends BType implements BIndexedType {
private BType elementType;
private int dimensions = 1;
private int size = -1;
private BArrayState state = BArrayState.UNSEALED;
private BArrayState state = BArrayState.OPEN;

public BArrayType(BType elementType) {
super(null, null, BNewArray.class);
Expand All @@ -53,7 +53,7 @@ public BArrayType(BType elemType, int size) {
dimensions = ((BArrayType) elementType).getDimensions() + 1;
}
if (size != -1) {
state = BArrayState.CLOSED_SEALED;
state = BArrayState.CLOSED;
this.size = size;
}
}
Expand Down Expand Up @@ -113,7 +113,7 @@ public int hashCode() {
public boolean equals(Object obj) {
if (obj instanceof BArrayType) {
BArrayType other = (BArrayType) obj;
if (other.state == BArrayState.CLOSED_SEALED && this.size != other.size) {
if (other.state == BArrayState.CLOSED && this.size != other.size) {
return false;
}
return this.elementType.equals(other.elementType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ protected void rangeCheckForGet(long index, int size) {

protected void ensureCapacity(int requestedCapacity, int currentArraySize) {
if ((requestedCapacity - currentArraySize) >= 0 && this.arrayType.getTag() == TypeTags.ARRAY_TAG &&
((BArrayType) this.arrayType).getState() == BArrayState.UNSEALED) {
((BArrayType) this.arrayType).getState() == BArrayState.OPEN) {
// Here the growth rate is 1.5. This value has been used by many other languages
int newArraySize = currentArraySize + (currentArraySize >> 1);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public BValueArray(BType type) {
if (type.getTag() == TypeTags.ARRAY_TAG) {
BArrayType arrayType = (BArrayType) type;
this.elementType = arrayType.getElementType();
if (arrayType.getState() == BArrayState.CLOSED_SEALED) {
if (arrayType.getState() == BArrayState.CLOSED) {
this.size = maxArraySize = arrayType.getSize();
}
refValues = (BRefType[]) newArrayInstance(BRefType.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import io.ballerina.runtime.api.Module;
import io.ballerina.runtime.api.StringUtils;
import io.ballerina.runtime.api.TypeTags;
import io.ballerina.runtime.api.types.ArrayType;
import io.ballerina.runtime.api.types.ArrayType.ArrayState;
import io.ballerina.runtime.api.types.AttachedFunctionType;
import io.ballerina.runtime.api.types.Field;
import io.ballerina.runtime.api.types.FunctionType;
Expand Down Expand Up @@ -1246,8 +1246,59 @@ private static boolean hasIncompatibleReadOnlyFlags(Field targetField, Field sou
Flags.READONLY);
}

private static boolean checkIsArrayType(BArrayType sourceType, BArrayType targetType,
List<TypePair> 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;
}
return checkIsType(sourceType.getElementType(), targetType.getElementType(), unresolvedTypes);
}

private static boolean checkIsArrayType(BTupleType sourceType, BArrayType targetType,
List<TypePair> unresolvedTypes) {
List<Type> 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<TypePair> unresolvedTypes) {
if (sourceType.getTag() == TypeTags.UNION_TAG) {
int sourceTypeTag = sourceType.getTag();

if (sourceTypeTag == TypeTags.UNION_TAG) {
for (Type memberType : ((BUnionType) sourceType).getMemberTypes()) {
if (!checkIsArrayType(memberType, targetType, unresolvedTypes)) {
return false;
Expand All @@ -1256,83 +1307,123 @@ private static boolean checkIsArrayType(Type sourceType, BArrayType targetType,
return true;
}

if (sourceType.getTag() != TypeTags.ARRAY_TAG && sourceType.getTag() != TypeTags.TUPLE_TAG) {
if (sourceTypeTag != TypeTags.ARRAY_TAG && sourceTypeTag != TypeTags.TUPLE_TAG) {
return false;
}

BArrayType sourceArrayType;
if (sourceType.getTag() == TypeTags.ARRAY_TAG) {
sourceArrayType = (BArrayType) sourceType;
} else {
BTupleType sourceTupleType = (BTupleType) sourceType;
Set<Type> tupleTypes = new HashSet<>(sourceTupleType.getTupleTypes());
if (sourceTupleType.getRestType() != null) {
tupleTypes.add(sourceTupleType.getRestType());
}
if (tupleTypes.isEmpty()) {
return targetType.getState() == ArrayType.ArrayState.UNSEALED || targetType.getSize() == 0;
}
sourceArrayType =
new BArrayType(new BUnionType(new ArrayList<>(tupleTypes), sourceTupleType.getTypeFlags()));
if (sourceTypeTag == TypeTags.ARRAY_TAG) {
return checkIsArrayType((BArrayType) sourceType, targetType, unresolvedTypes);
}
return checkIsArrayType((BTupleType) sourceType, targetType, unresolvedTypes);
}

switch (sourceArrayType.getState()) {
case UNSEALED:
if (targetType.getState() != ArrayType.ArrayState.UNSEALED) {
private static boolean checkIsTupleType(BArrayType sourceType, BTupleType targetType,
List<TypePair> unresolvedTypes) {
Type sourceElementType = sourceType.getElementType();
List<Type> targetTypes = targetType.getTupleTypes();
Type targetRestType = targetType.getRestType();

switch (sourceType.getState()) {
case OPEN:
if (targetRestType == null) {
return false;
}
break;
case CLOSED_SEALED:
if (targetType.getState() == ArrayType.ArrayState.CLOSED_SEALED &&
sourceArrayType.getSize() != targetType.getSize()) {
if (targetTypes.isEmpty()) {
return checkIsType(sourceElementType, targetRestType, unresolvedTypes);
}
return false;
case CLOSED:
if (sourceType.getSize() < targetTypes.size()) {
return false;
}
break;
}
if (targetTypes.isEmpty()) {
if (targetRestType != null) {
return checkIsType(sourceElementType, targetRestType, unresolvedTypes);
}
return sourceType.getSize() == 0;
}

//If element type is a value type, then check same type
Type targetElementType = targetType.getElementType();
int targetElementTypeTag = targetElementType.getTag();
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;
}
}

Type sourceElementType = sourceArrayType.getElementType();
private static boolean checkIsTupleType(BTupleType sourceType, BTupleType targetType,
List<TypePair> unresolvedTypes) {
List<Type> sourceTypes = sourceType.getTupleTypes();
Type sourceRestType = sourceType.getRestType();
List<Type> targetTypes = targetType.getTupleTypes();
Type targetRestType = targetType.getRestType();

if (targetElementTypeTag <= TypeTags.BOOLEAN_TAG) {
if (targetElementTypeTag == TypeTags.INT_TAG && sourceElementType.getTag() == TypeTags.BYTE_TAG) {
return true;
}
if (sourceRestType != null && targetRestType == null) {
return false;
}
int sourceTypeSize = sourceTypes.size();
int targetTypeSize = targetTypes.size();

return sourceElementType.getTag() == targetElementTypeTag;
if (sourceRestType == null && targetRestType == null && sourceTypeSize != targetTypeSize) {
return false;
}
return checkIsType(sourceElementType, targetElementType, unresolvedTypes);
}

private static boolean checkIsTupleType(Type sourceType, BTupleType targetType, List<TypePair> unresolvedTypes) {
if (sourceType.getTag() != TypeTags.TUPLE_TAG) {
if (sourceTypeSize < targetTypeSize) {
return false;
}

List<Type> sourceTypes = new ArrayList<>(((BTupleType) sourceType).getTupleTypes());
Type sourceRestType = ((BTupleType) sourceType).getRestType();
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) {
sourceTypes.add(sourceRestType);
return checkIsType(sourceRestType, targetRestType, unresolvedTypes);
}
return true;
}

List<Type> targetTypes = new ArrayList<>(targetType.getTupleTypes());
Type targetRestType = targetType.getRestType();
if (targetRestType != null) {
targetTypes.add(targetRestType);
private static boolean checkIsTupleType(Type sourceType, BTupleType targetType, List<TypePair> unresolvedTypes) {
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 (sourceTypes.size() != targetTypes.size()) {
if (sourceTypeTag != TypeTags.ARRAY_TAG && sourceTypeTag != TypeTags.TUPLE_TAG) {
return false;
}

for (int i = 0; i < sourceTypes.size(); i++) {
if (!checkIsType(sourceTypes.get(i), targetTypes.get(i), unresolvedTypes)) {
return false;
}
if (sourceTypeTag == TypeTags.ARRAY_TAG) {
return checkIsTupleType((BArrayType) sourceType, targetType, unresolvedTypes);
}
return true;
return checkIsTupleType((BTupleType) sourceType, targetType, unresolvedTypes);
}

private static boolean checkIsAnyType(Type sourceType) {
Expand Down Expand Up @@ -2680,7 +2771,7 @@ private static boolean checkFillerValue(BRecordType type, List<Type> unAnalyzedT
}

private static boolean checkFillerValue(BArrayType type) {
return type.getState() == ArrayType.ArrayState.UNSEALED || hasFillerValue(type.getElementType());
return type.getState() == ArrayState.OPEN || hasFillerValue(type.getElementType());
}

private static boolean checkFillerValue(BObjectType type) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ public interface ArrayType extends Type {
* @since 2.0.0
*/
enum ArrayState {
CLOSED_SEALED((byte) 1),
OPEN_SEALED((byte) 2),
UNSEALED((byte) 3);
CLOSED((byte) 1),
INFERRED((byte) 2),
OPEN((byte) 3);

byte value;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public class BArrayType extends BType implements ArrayType {
private int dimensions = 1;
private int size = -1;
private boolean hasFillerValue;
private ArrayState state = ArrayState.UNSEALED;
private ArrayState state = ArrayState.OPEN;

private final boolean readonly;
private IntersectionType immutableType;
Expand All @@ -67,7 +67,7 @@ public BArrayType(Type elemType, int size, boolean readonly) {
dimensions = ((BArrayType) elementType).getDimensions() + 1;
}
if (size != -1) {
state = ArrayState.CLOSED_SEALED;
state = ArrayState.CLOSED;
this.size = size;
}
hasFillerValue = TypeChecker.hasFillerValue(this.elementType);
Expand Down Expand Up @@ -129,7 +129,7 @@ public int hashCode() {
public boolean equals(Object obj) {
if (obj instanceof BArrayType) {
BArrayType other = (BArrayType) obj;
if (other.state == ArrayState.CLOSED_SEALED && 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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import io.ballerina.runtime.api.StringUtils;
import io.ballerina.runtime.api.TypeTags;
import io.ballerina.runtime.api.types.ArrayType;
import io.ballerina.runtime.api.types.ArrayType.ArrayState;
import io.ballerina.runtime.api.types.Type;
import io.ballerina.runtime.api.values.BLink;
import io.ballerina.runtime.api.values.BString;
Expand Down Expand Up @@ -133,7 +134,7 @@ public ArrayValueImpl(ArrayType type) {
ArrayType arrayType = type;
this.elementType = arrayType.getElementType();
initArrayValues(elementType);
if (arrayType.getState() == ArrayType.ArrayState.CLOSED_SEALED) {
if (arrayType.getState() == ArrayState.CLOSED) {
this.size = maxSize = arrayType.getSize();
}
}
Expand Down Expand Up @@ -165,7 +166,7 @@ private void initArrayValues(Type elementType) {
break;
default:
this.refValues = new Object[initialArraySize];
if (arrayType.getState() == ArrayType.ArrayState.CLOSED_SEALED) {
if (arrayType.getState() == ArrayState.CLOSED) {
fillerValueCheck(initialArraySize, initialArraySize);
fillValues(initialArraySize);
}
Expand Down Expand Up @@ -1003,7 +1004,7 @@ protected void ensureCapacity(int requestedCapacity, int currentArraySize) {
return;
}

if (this.arrayType.getState() != ArrayType.ArrayState.UNSEALED) {
if (this.arrayType.getState() != ArrayState.OPEN) {
return;
}

Expand All @@ -1020,7 +1021,7 @@ protected void ensureCapacity(int requestedCapacity, int currentArraySize) {

@Override
protected void checkFixedLength(long length) {
if (this.arrayType.getState() == ArrayType.ArrayState.CLOSED_SEALED) {
if (this.arrayType.getState() == ArrayState.CLOSED) {
throw BLangExceptionHelper.getRuntimeException(
getModulePrefixedReason(ARRAY_LANG_LIB, INHERENT_TYPE_VIOLATION_ERROR_IDENTIFIER),
RuntimeErrors.ILLEGAL_ARRAY_SIZE, size, length);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2461,7 +2461,7 @@ private void generateListConstructorExpr(BLangListConstructorExpr listConstructo
long size = -1L;
List<BLangExpression> exprs = listConstructorExpr.exprs;
if (listConstructorExpr.type.tag == TypeTags.ARRAY &&
((BArrayType) listConstructorExpr.type).state != BArrayState.UNSEALED) {
((BArrayType) listConstructorExpr.type).state != BArrayState.OPEN) {
size = ((BArrayType) listConstructorExpr.type).size;
} else if (listConstructorExpr.type.tag == TypeTags.TUPLE) {
size = exprs.size();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1997,7 +1997,7 @@ private void checkArrayVarRefEquivalency(DiagnosticPos pos, BLangTupleVarRef tar
BArrayType arraySource = (BArrayType) source;

// For unsealed
if (arraySource.size < target.expressions.size() && arraySource.state != BArrayState.UNSEALED) {
if (arraySource.size < target.expressions.size() && arraySource.state != BArrayState.OPEN) {
dlog.error(rhsPos, DiagnosticCode.INCOMPATIBLE_TYPES, target.type, arraySource);
}

Expand Down
Loading

0 comments on commit 25d759e

Please sign in to comment.