From 11ee4cd7aa259f27ef6be886d2750c83aca92d64 Mon Sep 17 00:00:00 2001 From: Istvan Romai Date: Mon, 18 Aug 2025 13:05:48 +0200 Subject: [PATCH] Double type enum Implemented double type enum properly Added new tests Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICTJ49 Internal issue: #27357 Change-Id: I8d6282b3919ac3b24c1112d3f0978bdaf6f72691 Signed-off-by: Istvan Romai --- ets2panda/checker/ets/typeCheckingHelpers.cpp | 5 ++ ets2panda/checker/ets/typeCreation.cpp | 6 +- ets2panda/checker/types/ets/etsEnumType.cpp | 57 +++++++++++++++++++ ets2panda/checker/types/ets/etsEnumType.h | 21 +++++++ .../types/ets/etsObjectTypeConstants.h | 3 +- ets2panda/checker/types/type.h | 1 + .../compiler/lowering/ets/enumLowering.cpp | 13 ++++- ets2panda/ir/base/classDefinition.h | 8 ++- .../ast/compiler/ets/enum-double-to-int.ets | 28 +++++++++ .../runtime/ets/enum-double-operations.ets | 26 +++++++++ .../util/diagnostic/arktsconfig_error.yaml | 2 +- ets2panda/util/diagnostic/syntax.yaml | 32 +++++------ 12 files changed, 178 insertions(+), 24 deletions(-) create mode 100644 ets2panda/test/ast/compiler/ets/enum-double-to-int.ets create mode 100644 ets2panda/test/runtime/ets/enum-double-operations.ets diff --git a/ets2panda/checker/ets/typeCheckingHelpers.cpp b/ets2panda/checker/ets/typeCheckingHelpers.cpp index e1b046b4d2..0e023e34e6 100644 --- a/ets2panda/checker/ets/typeCheckingHelpers.cpp +++ b/ets2panda/checker/ets/typeCheckingHelpers.cpp @@ -412,6 +412,11 @@ bool Type::IsETSPrimitiveOrEnumType() const return IsETSPrimitiveType() || IsETSEnumType(); } +bool Type::IsETSDoubleEnumType() const +{ + return IsETSObjectType() && AsETSObjectType()->HasObjectFlag(ETSObjectFlags::DOUBLE_ENUM_OBJECT); +} + bool Type::IsETSReferenceType() const { // Do not modify diff --git a/ets2panda/checker/ets/typeCreation.cpp b/ets2panda/checker/ets/typeCreation.cpp index c6396ad643..74210412c8 100644 --- a/ets2panda/checker/ets/typeCreation.cpp +++ b/ets2panda/checker/ets/typeCreation.cpp @@ -375,10 +375,12 @@ ETSObjectType *ETSChecker::CreateETSObjectType(ir::AstNode *declNode, ETSObjectF if (declNode->AsClassDefinition()->IsIntEnumTransformed()) { objectType = ProgramAllocator()->New(ProgramAllocator(), name, internalName, declNode, Relation()); - } else { - ES2PANDA_ASSERT(declNode->AsClassDefinition()->IsStringEnumTransformed()); + } else if (declNode->AsClassDefinition()->IsStringEnumTransformed()) { objectType = ProgramAllocator()->New(ProgramAllocator(), name, internalName, declNode, Relation()); + } else if (declNode->AsClassDefinition()->IsDoubleEnumTransformed()) { + objectType = ProgramAllocator()->New(ProgramAllocator(), name, internalName, declNode, + Relation()); } } else if (internalName == compiler::Signatures::BUILTIN_ARRAY) { objectType = ProgramAllocator()->New(ProgramAllocator(), name, diff --git a/ets2panda/checker/types/ets/etsEnumType.cpp b/ets2panda/checker/types/ets/etsEnumType.cpp index 233a403e05..368e6f735c 100644 --- a/ets2panda/checker/types/ets/etsEnumType.cpp +++ b/ets2panda/checker/types/ets/etsEnumType.cpp @@ -134,4 +134,61 @@ void ETSIntEnumType::CastTarget(TypeRelation *relation, Type *source) conversion::Forbidden(relation); } +bool ETSDoubleEnumType::AssignmentSource(TypeRelation *relation, Type *target) +{ + bool result = false; + if (target->IsETSObjectType()) { + if (target->AsETSObjectType()->IsGlobalETSObjectType() || + target->AsETSObjectType()->Name() == compiler::Signatures::BUILTIN_DOUBLE_CLASS) { + result = true; + relation->GetNode()->AddAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF); + } else if (target->IsDoubleType()) { + result = true; + relation->GetNode()->AddAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF); + } + } else if (target->HasTypeFlag(TypeFlag::DOUBLE)) { + result = true; + relation->GetNode()->AddAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF); + } else if (target->IsETSUnionType()) { + auto &unionConstituentTypes = target->AsETSUnionType()->ConstituentTypes(); + for (auto *constituentType : unionConstituentTypes) { + if (relation->IsIdenticalTo(this, constituentType)) { + result = true; + break; + } + } + } + relation->Result(result); + return relation->IsTrue(); +} + +void ETSDoubleEnumType::AssignmentTarget(TypeRelation *relation, Type *source) +{ + relation->IsIdenticalTo(this, source) ? relation->Result(true) : relation->Result(false); +} + +void ETSDoubleEnumType::Cast(TypeRelation *const relation, Type *const target) +{ + if (relation->IsIdenticalTo(this, target)) { + relation->Result(true); + return; + } + if (target->HasTypeFlag(TypeFlag::ETS_NUMERIC) || target->IsBuiltinNumeric()) { + relation->RaiseError(diagnostic::ENUM_DEPRECATED_CAST, {this, target}, relation->GetNode()->Start()); + relation->Result(true); + return; + } + conversion::Forbidden(relation); +} + +void ETSDoubleEnumType::CastTarget(TypeRelation *relation, Type *source) +{ + if (source->IsFloatType() || source->IsBuiltinNumeric()) { + relation->RaiseError(diagnostic::ENUM_DEPRECATED_CAST, {source, this}, relation->GetNode()->Start()); + relation->Result(true); + return; + } + conversion::Forbidden(relation); +} + } // namespace ark::es2panda::checker diff --git a/ets2panda/checker/types/ets/etsEnumType.h b/ets2panda/checker/types/ets/etsEnumType.h index 3005b78053..d09b0274dd 100644 --- a/ets2panda/checker/types/ets/etsEnumType.h +++ b/ets2panda/checker/types/ets/etsEnumType.h @@ -162,6 +162,27 @@ public: void CastTarget(TypeRelation *relation, Type *source) override; }; +class ETSDoubleEnumType : public ETSEnumType { +public: + explicit ETSDoubleEnumType(ThreadSafeArenaAllocator *allocator, util::StringView name, + util::StringView internalName, ir::AstNode *declNode, TypeRelation *relation) + : ETSEnumType(allocator, name, internalName, declNode, relation, ETSObjectFlags::DOUBLE_ENUM_OBJECT) + { + AddTypeFlag(checker::TypeFlag::ETS_ENUM); // TypeFlag enum is full, cannot add new ETS_DOUBLE_ENUM typeflag + } + + NO_COPY_SEMANTIC(ETSDoubleEnumType); + NO_MOVE_SEMANTIC(ETSDoubleEnumType); + + ETSDoubleEnumType() = delete; + ~ETSDoubleEnumType() override = default; + + bool AssignmentSource(TypeRelation *relation, Type *target) override; + void AssignmentTarget(TypeRelation *relation, Type *source) override; + void Cast(TypeRelation *relation, Type *target) override; + void CastTarget(TypeRelation *relation, Type *source) override; +}; + } // namespace ark::es2panda::checker #endif diff --git a/ets2panda/checker/types/ets/etsObjectTypeConstants.h b/ets2panda/checker/types/ets/etsObjectTypeConstants.h index b3a4e93f35..c627166245 100644 --- a/ets2panda/checker/types/ets/etsObjectTypeConstants.h +++ b/ets2panda/checker/types/ets/etsObjectTypeConstants.h @@ -62,8 +62,9 @@ enum class ETSObjectFlags : std::uint64_t { EXTENSION_FUNCTION = 1ULL << 36U, FUNCTIONAL_REFERENCE = 1ULL << 37U, LAZY_IMPORT_OBJECT = 1ULL << 38U, + DOUBLE_ENUM_OBJECT = 1ULL << 39U, - ENUM_OBJECT = INT_ENUM_OBJECT | STRING_ENUM_OBJECT, + ENUM_OBJECT = INT_ENUM_OBJECT | STRING_ENUM_OBJECT | DOUBLE_ENUM_OBJECT, BUILTIN_FLOATING_POINT = BUILTIN_DOUBLE | BUILTIN_FLOAT, BUILTIN_INTEGRAL = BUILTIN_BYTE | BUILTIN_SHORT | BUILTIN_INT | BUILTIN_LONG, diff --git a/ets2panda/checker/types/type.h b/ets2panda/checker/types/type.h index b0565a97d7..b038f7e91d 100644 --- a/ets2panda/checker/types/type.h +++ b/ets2panda/checker/types/type.h @@ -112,6 +112,7 @@ public: bool IsETSAsyncFuncReturnType() const; bool IsETSUnboxableObject() const; bool IsETSPrimitiveOrEnumType() const; + bool IsETSDoubleEnumType() const; bool PossiblyETSNull() const; bool PossiblyETSUndefined() const; diff --git a/ets2panda/compiler/lowering/ets/enumLowering.cpp b/ets2panda/compiler/lowering/ets/enumLowering.cpp index a36144f45d..976ae61be6 100644 --- a/ets2panda/compiler/lowering/ets/enumLowering.cpp +++ b/ets2panda/compiler/lowering/ets/enumLowering.cpp @@ -292,9 +292,16 @@ ir::ClassDeclaration *EnumLoweringPhase::CreateClass(ir::TSEnumDeclaration *cons { auto *ident = Allocator()->New(enumDecl->Key()->Name(), Allocator()); ident->SetRange(enumDecl->Key()->Range()); - auto enumFlag = enumType == EnumType::INT || enumType == EnumType::LONG - ? ir::ClassDefinitionModifiers::INT_ENUM_TRANSFORMED - : ir::ClassDefinitionModifiers::STRING_ENUM_TRANSFORMED; + + ir::ClassDefinitionModifiers enumFlag = ir::ClassDefinitionModifiers::NONE; + if (enumType == EnumType::INT || enumType == EnumType::LONG) { + enumFlag = ir::ClassDefinitionModifiers::INT_ENUM_TRANSFORMED; + } else if (enumType == EnumType::DOUBLE) { + enumFlag = ir::ClassDefinitionModifiers::DOUBLE_ENUM_TRANSFORMED; + } else if (enumType == EnumType::STRING) { + enumFlag = ir::ClassDefinitionModifiers::STRING_ENUM_TRANSFORMED; + } + auto baseClassDefinitionFlag = ir::ClassDefinitionModifiers::CLASS_DECL | enumFlag; auto typeParamsVector = ArenaVector(Allocator()->Adapter()); diff --git a/ets2panda/ir/base/classDefinition.h b/ets2panda/ir/base/classDefinition.h index 881734d32e..4425052ca7 100644 --- a/ets2panda/ir/base/classDefinition.h +++ b/ets2panda/ir/base/classDefinition.h @@ -60,6 +60,7 @@ enum class ClassDefinitionModifiers : uint32_t { FUNCTIONAL_REFERENCE = 1U << 17U, LAZY_IMPORT_OBJECT_CLASS = 1U << 18U, INIT_IN_CCTOR = 1U << 19U, + DOUBLE_ENUM_TRANSFORMED = 1U << 20U, DECLARATION_ID_REQUIRED = DECLARATION | ID_REQUIRED, ETS_MODULE = NAMESPACE_TRANSFORMED | GLOBAL }; @@ -256,6 +257,11 @@ public: return (Modifiers() & ClassDefinitionModifiers::INT_ENUM_TRANSFORMED) != 0; } + [[nodiscard]] bool IsDoubleEnumTransformed() const noexcept + { + return (Modifiers() & ClassDefinitionModifiers::DOUBLE_ENUM_TRANSFORMED) != 0; + } + [[nodiscard]] bool IsStringEnumTransformed() const noexcept { return (Modifiers() & ClassDefinitionModifiers::STRING_ENUM_TRANSFORMED) != 0; @@ -263,7 +269,7 @@ public: [[nodiscard]] bool IsEnumTransformed() const noexcept { - return IsIntEnumTransformed() || IsStringEnumTransformed(); + return IsIntEnumTransformed() || IsStringEnumTransformed() || IsDoubleEnumTransformed(); } [[nodiscard]] bool IsNamespaceTransformed() const noexcept diff --git a/ets2panda/test/ast/compiler/ets/enum-double-to-int.ets b/ets2panda/test/ast/compiler/ets/enum-double-to-int.ets new file mode 100644 index 0000000000..98e3d23733 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/enum-double-to-int.ets @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed 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. + */ + +enum Color: double { + Red = 1.1, + Green = 2.2, + Blue = 3.3 +} + +function main(): void { + let c1: int = /* @@ label1 */Color.Blue; + let c2: int = /* @@ label2 */Color.Red + Color.Green; +} + +/* @@@ label1 Error TypeError: Type 'Color' cannot be assigned to type 'Int' */ +/* @@@ label2 Error TypeError: Type 'Double' cannot be assigned to type 'Int' */ \ No newline at end of file diff --git a/ets2panda/test/runtime/ets/enum-double-operations.ets b/ets2panda/test/runtime/ets/enum-double-operations.ets new file mode 100644 index 0000000000..a63d1acf70 --- /dev/null +++ b/ets2panda/test/runtime/ets/enum-double-operations.ets @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed 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. + */ + +enum Color: double { + Red = 1.1, + Green = 2.2, + Blue = 3.3 +} + +let c1: double = Color.Red + Color.Green; +let c2: double = Color.Blue; + +arktest.assertDoubleEQ(c1, 3.3, 0.0000001); +arktest.assertDoubleEQ(c2, 3.3, 0.0000001); \ No newline at end of file diff --git a/ets2panda/util/diagnostic/arktsconfig_error.yaml b/ets2panda/util/diagnostic/arktsconfig_error.yaml index 21d311b7b1..2ce9b5aa9c 100644 --- a/ets2panda/util/diagnostic/arktsconfig_error.yaml +++ b/ets2panda/util/diagnostic/arktsconfig_error.yaml @@ -67,7 +67,7 @@ arkts_config_error: - name: NOT_A_DIR id: 19 - message: '{} is not a directory' + message: '{} is not a directory' - name: NOT_ROOT_DIR id: 15 diff --git a/ets2panda/util/diagnostic/syntax.yaml b/ets2panda/util/diagnostic/syntax.yaml index 6ce29340a6..a04f4edd24 100644 --- a/ets2panda/util/diagnostic/syntax.yaml +++ b/ets2panda/util/diagnostic/syntax.yaml @@ -235,8 +235,8 @@ syntax: - name: ERROR_ARKTS_NO_FOR_IN_LOOP id: 6987 - message: "'for ... in' loop is not supported, please use regular 'for' or 'for ... of ...' loop to iterate through arrays\ - \ and iterable objects." + message: "'for ... in' loop is not supported, please use regular 'for' or 'for ... of ...' loop to iterate through arrays + and iterable objects." - name: ERROR_ARKTS_NO_IMPORT_ASSERTIONS id: 313 @@ -253,8 +253,8 @@ syntax: - name: ERROR_ARKTS_NO_IS_OPERATOR id: 169587 - message: "'is' operator is not supported. Use 'instanceof' instead to check whether a variable is instance of a given type\ - \ and use 'as' operator to cast to the appropriate type!" + message: "'is' operator is not supported. Use 'instanceof' instead to check whether a variable is instance of a given type + and use 'as' operator to cast to the appropriate type!" - name: ERROR_ARKTS_NO_OBJ_LITERAL_TO_DECL_TYPE id: 177354 @@ -274,8 +274,8 @@ syntax: - name: ERROR_ARKTS_NO_SIDE_EFFECT_IMPORT id: 73297 - message: "Importing for side-effect only is prohibited! Please provide objects to be imported explicitly or use * to import\ - \ all objects declared in the module!" + message: "Importing for side-effect only is prohibited! Please provide objects to be imported explicitly or use * to import + all objects declared in the module!" - name: ERROR_ARKTS_NO_UMD id: 114179 @@ -485,8 +485,8 @@ syntax: - name: IMPORT_TOP_LEVEL id: 226 - message: "Import declarations can only be used on the top level and before any other declaration, top level statement or\ - \ directive." + message: "Import declarations can only be used on the top level and before any other declaration, top level statement or + directive." - name: IMPROPER_NESTING_CLASS id: 233 @@ -522,8 +522,8 @@ syntax: - name: INIT_MODULE_DECLARATION_POSITION id: 322 - message: "initModule() must only be called immediately after the import statement, and before any other declarations or\ - \ statements." + message: "initModule() must only be called immediately after the import statement, and before any other declarations or + statements." - name: INSERT_NODE_ABSENT id: 10 @@ -607,8 +607,8 @@ syntax: - name: INVALID_DECORATOR_CONSTRUCTOR id: 201 - message: "The modifier for a constructor should be limited to access modifiers (private, internal, protected, public), and\ - \ 'native' modifiers." + message: "The modifier for a constructor should be limited to access modifiers (private, internal, protected, public), and + 'native' modifiers." - name: INVALID_DESTRUCTURING_TARGET id: 49 @@ -776,8 +776,8 @@ syntax: - name: LITERAL_VALUE_IDENT id: 315 - message: "Number, string or computed value property name '{}' is not allowed, use classes to access data by property names\ - \ that are identifiers" + message: "Number, string or computed value property name '{}' is not allowed, use classes to access data by property names + that are identifiers" - name: LOCAL_CLASS_ACCESS_MOD id: 30 @@ -1262,8 +1262,8 @@ syntax: - name: UNSUPPORTED_ENUM_TYPE id: 327 - message: "Unsupported enum type annotation. Supported enum types are: int, long or double. String is allowed for literal\ - \ types, not annotations." + message: "Unsupported enum type annotation. Supported enum types are: int, long or double. String is allowed for literal + types, not annotations." - name: UNTERMINATED_MULTI_LINE_COMMENT id: 245 -- Gitee