From 868a85394aa739021af5c91faa0d84f5b0e4fe9d Mon Sep 17 00:00:00 2001 From: Heshan Padmasiri Date: Tue, 13 Aug 2024 15:12:04 +0530 Subject: [PATCH] Refactor isSameType --- .../runtime/api/types/semtype/Builder.java | 7 +- .../runtime/internal/TypeChecker.java | 67 +++++++++++++------ 2 files changed, 51 insertions(+), 23 deletions(-) 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 index b84450d9a9bf..4926635d2d07 100644 --- 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 @@ -113,7 +113,8 @@ public final class Builder { 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()); @@ -417,6 +418,10 @@ public static SemType xmlTextType() { return XML_TEXT.get(); } + public static SemType xmlNeverType() { + return XML_NEVER.get(); + } + public static SemType xmlPIType() { return XML_PI.get(); } 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 63ab96294d8b..766c65fadd99 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 @@ -25,6 +25,7 @@ import io.ballerina.runtime.api.types.FunctionType; import io.ballerina.runtime.api.types.MethodType; import io.ballerina.runtime.api.types.ParameterizedType; +import io.ballerina.runtime.api.types.ReadonlyType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.XmlNodeType; import io.ballerina.runtime.api.types.semtype.Builder; @@ -122,6 +123,8 @@ public class TypeChecker { private static final ThreadLocal threadContext = ThreadLocal.withInitial(() -> Context.from(Env.getInstance())); private static final SemType SIMPLE_BASIC_TYPE = createSimpleBasicType(); + private static final SemType NUMERIC_TYPE = createNumericType(); + private static final SemType INHERENTLY_IMMUTABLE_TYPE = createInherentlyImmutableType(); private static final byte MAX_TYPECAST_ERROR_COUNT = 20; public static Object checkCast(Object sourceVal, Type targetType) { @@ -344,33 +347,34 @@ private static SemType appendNumericConversionTypes(SemType semType) { * @return true if the two types are same; false otherwise */ public static boolean isSameType(Type sourceType, Type targetType) { - // FIXME: - return sourceType == targetType || sourceType.equals(targetType); + return Core.isSameType(context(), sourceType, targetType); } public static Type getType(Object value) { if (value == null) { return TYPE_NULL; } else if (value instanceof Number number) { - if (value instanceof Double) { - return BFloatType.singletonType(number.doubleValue()); - } - long numberValue = - number instanceof Byte byteValue ? Byte.toUnsignedLong(byteValue) : number.longValue(); - if (value instanceof Long) { - return BIntegerType.singletonType(numberValue); - } else if (value instanceof Integer || value instanceof Byte) { - return BByteType.singletonType(numberValue); - } + return getNumberType(number); } else if (value instanceof Boolean booleanValue) { return BBooleanType.singletonType(booleanValue); - } else if (value instanceof BObject) { - return ((BObject) value).getOriginalType(); + } else if (value instanceof BObject bObject) { + return bObject.getOriginalType(); } - return ((BValue) value).getType(); } + private static Type getNumberType(Number number) { + if (number instanceof Double) { + return BFloatType.singletonType(number.doubleValue()); + } + long numberValue = + number instanceof Byte byteValue ? Byte.toUnsignedLong(byteValue) : number.longValue(); + if (number instanceof Integer || number instanceof Byte) { + return BByteType.singletonType(numberValue); + } + return BIntegerType.singletonType(numberValue); + } + /** * Deep value equality check for anydata. * @@ -549,10 +553,10 @@ public static TypedescValue getTypedesc(Object value) { */ public static Object getAnnotValue(TypedescValue typedescValue, BString annotTag) { Type describingType = typedescValue.getDescribingType(); - if (!(describingType instanceof BAnnotatableType)) { + if (!(describingType instanceof BAnnotatableType annotatableType)) { return null; } - return ((BAnnotatableType) describingType).getAnnotation(annotTag); + return annotatableType.getAnnotation(annotTag); } /** @@ -583,10 +587,13 @@ public static boolean checkDecimalEqual(DecimalValue lhsValue, DecimalValue rhsV lhsValue.decimalValue().compareTo(rhsValue.decimalValue()) == 0; } + private static SemType createNumericType() { + return Stream.of(Builder.intType(), Builder.floatType(), Builder.decimalType()) + .reduce(Builder.neverType(), Core::union); + } + public static boolean isNumericType(Type type) { - // FIXME: - type = getImpliedType(type); - return type.getTag() < TypeTags.STRING_TAG || TypeTags.isIntegerTypeTag(type.getTag()); + return Core.isSubType(context(), type, NUMERIC_TYPE); } static boolean isByteLiteral(long longValue) { @@ -629,8 +636,23 @@ private static SemType widenedType(Context cx, Object value) { } } - // FIXME: + private static SemType createInherentlyImmutableType() { + return Stream.of(createSimpleBasicType(), Builder.stringType(), Builder.errorType(), Builder.functionType(), + Builder.typeDescType(), Builder.handleType(), Builder.xmlTextType(), Builder.xmlNeverType(), + Builder.regexType()) + .reduce(Builder.neverType(), Core::union); + } + public static boolean isInherentlyImmutableType(Type sourceType) { + // boolean expected = isInherentlyImmutableOld(sourceType); + // readonly part is there to match to old API + return + Core.isSubType(context(), sourceType, INHERENTLY_IMMUTABLE_TYPE) || sourceType instanceof ReadonlyType; + // assert expected == actual; +// return actual; + } + + private static boolean isInherentlyImmutableOld(Type sourceType) { sourceType = getImpliedType(sourceType); if (belongToSingleBasicTypeOrString(sourceType)) { return true; @@ -648,7 +670,7 @@ public static boolean isInherentlyImmutableType(Type sourceType) { case TypeTags.TYPEDESC_TAG: case TypeTags.FUNCTION_POINTER_TAG: case TypeTags.HANDLE_TAG: - case TypeTags.REG_EXP_TYPE_TAG: + case TypeTags.REG_EXP_TYPE_TAG: return true; case TypeTags.XML_TAG: return ((BXmlType) sourceType).constraint.getTag() == TypeTags.NEVER_TAG; @@ -673,6 +695,7 @@ public static boolean isSelectivelyImmutableType(Type type, Set unresolved case TypeTags.XML_COMMENT_TAG: case TypeTags.XML_ELEMENT_TAG: case TypeTags.XML_PI_TAG: + case TypeTags.READONLY_TAG: return true; case TypeTags.ARRAY_TAG: Type elementType = ((BArrayType) type).getElementType();