From 021b4e03b6b4992d344b301532f74868ca5e1ec8 Mon Sep 17 00:00:00 2001 From: Gergo Torok Date: Wed, 20 Sep 2023 14:30:08 +0200 Subject: [PATCH] Reworking binary equality After specification change the equality expressions are no longer connected to the ".equals()" method. From now on the separation of reference and value equality is based on the expressions it compares. Change-Id: I2ef36659a960a8063707ef168b0745baaa7e7827 Signed-off-by: Gergo Torok --- ets2panda/checker/ets/arithmetic.cpp | 107 ++-- ets2panda/checker/ets/helpers.cpp | 2 +- .../checker/types/ets/etsFunctionType.cpp | 10 + ets2panda/checker/types/ets/etsFunctionType.h | 1 + ets2panda/compiler/core/ETSGen.cpp | 64 +- ets2panda/compiler/core/ETSGen.h | 35 +- .../ets/dynamic-equality-error-expected.txt | 2 +- ...eferenceEqualityNotCastable_n-expected.txt | 2 +- ...ferenceEqualityNotReference_n-expected.txt | 548 ------------------ .../ets/referenceEqualityNotReference_n.ets | 20 - ets2panda/test/runtime/ets/array-object.ets | 4 +- ets2panda/test/runtime/ets/dollar_dollar.ets | 2 +- ets2panda/test/runtime/ets/notNull.ets | 2 +- .../ets/optional-chaining-lazy-evaluation.ets | 3 +- .../test/runtime/ets/referenceEquality.ets | 28 + .../test/runtime/ets/string-assignment.ets | 2 +- ets2panda/test/runtime/ets/string-builder.ets | 10 +- ets2panda/test/runtime/ets/top_level_02.ets | 6 +- 18 files changed, 137 insertions(+), 711 deletions(-) delete mode 100644 ets2panda/test/compiler/ets/referenceEqualityNotReference_n-expected.txt delete mode 100644 ets2panda/test/compiler/ets/referenceEqualityNotReference_n.ets diff --git a/ets2panda/checker/ets/arithmetic.cpp b/ets2panda/checker/ets/arithmetic.cpp index c78ac64ba9..66db3defb7 100644 --- a/ets2panda/checker/ets/arithmetic.cpp +++ b/ets2panda/checker/ets/arithmetic.cpp @@ -273,38 +273,58 @@ checker::Type *ETSChecker::CheckBinaryOperatorLogical(ir::Expression *left, ir:: UNREACHABLE(); } -std::tuple ETSChecker::CheckBinaryOperatorStrictEqual(ir::Expression *left, lexer::SourcePosition pos, - checker::Type *const left_type, - checker::Type *const right_type) +std::tuple ETSChecker::CheckBinaryOperatorEqual( + ir::Expression *left, ir::Expression *right, lexer::TokenType operation_type, lexer::SourcePosition pos, + checker::Type *const left_type, checker::Type *const right_type, Type *unboxed_l, Type *unboxed_r) { checker::Type *ts_type {}; - if (!(left_type->HasTypeFlag(checker::TypeFlag::ETS_ARRAY_OR_OBJECT)) || - !(right_type->HasTypeFlag(checker::TypeFlag::ETS_ARRAY_OR_OBJECT))) { - ThrowTypeError("Both operands have to be reference types", pos); + checker::Type *op_type {}; + ts_type = GlobalETSBooleanType(); + + if ((left->IsNullLiteral() || right->IsNullLiteral()) && + (left->IsUndefinedLiteral() || right->IsUndefinedLiteral())) { + ts_type = CreateETSBooleanType(operation_type == lexer::TokenType::PUNCTUATOR_EQUAL || + operation_type == lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL); + + return {ts_type, GlobalETSUndefinedType()}; } - Relation()->SetNode(left); - if (!Relation()->IsCastableTo(left_type, right_type) && !Relation()->IsCastableTo(right_type, left_type)) { - ThrowTypeError("The operands of strict equality are not compatible with each other", pos); + if (IsReferenceType(left_type) && IsReferenceType(right_type)) { + // Reference Equality + + Relation()->SetNode(left); + if (!right->IsNullLiteral() && !left->IsNullLiteral() && !right->IsUndefinedLiteral() && + !left->IsUndefinedLiteral() && !Relation()->IsCastableTo(left_type, right_type) && + !Relation()->IsCastableTo(right_type, left_type)) { + if (unboxed_l == nullptr || unboxed_r == nullptr) { + ThrowTypeError("The operands of reference equality are not compatible with each other", pos); + } + + } else { + if (left_type->IsETSDynamicType() || right_type->IsETSDynamicType()) { + return CheckBinaryOperatorEqualDynamic(left, right, pos); + } + + return {ts_type, GlobalETSObjectType()}; + } } - ts_type = GlobalETSBooleanType(); - if (right_type->IsETSDynamicType() && left_type->IsETSDynamicType()) { - return {ts_type, GlobalBuiltinJSValueType()}; + + // Value Equality + auto positive_equal = operation_type == lexer::TokenType::PUNCTUATOR_EQUAL || + operation_type == lexer::TokenType::PUNCTUATOR_STRICT_EQUAL; + + if (left->IsNullLiteral() || right->IsNullLiteral() || left->IsUndefinedLiteral() || right->IsUndefinedLiteral()) { + op_type = left->IsNullLiteral() || left->IsUndefinedLiteral() ? right_type : left_type; + ts_type = CreateETSBooleanType(!positive_equal); + + return {ts_type, op_type}; } - return {ts_type, GlobalETSObjectType()}; -} -std::tuple ETSChecker::CheckBinaryOperatorEqual( - ir::Expression *left, ir::Expression *right, lexer::TokenType operation_type, lexer::SourcePosition pos, - checker::Type *const left_type, checker::Type *const right_type, Type *unboxed_l, Type *unboxed_r) -{ - checker::Type *ts_type {}; if (left_type->IsETSEnumType() && right_type->IsETSEnumType()) { if (!left_type->AsETSEnumType()->IsSameEnumType(right_type->AsETSEnumType())) { ThrowTypeError("Bad operand type, the types of the operands must be the same enum type.", pos); } - ts_type = GlobalETSBooleanType(); return {ts_type, left_type}; } @@ -313,35 +333,38 @@ std::tuple ETSChecker::CheckBinaryOperatorEqual( ThrowTypeError("Bad operand type, the types of the operands must be the same enum type.", pos); } - ts_type = GlobalETSBooleanType(); return {ts_type, left_type}; } - if (left_type->IsETSDynamicType() || right_type->IsETSDynamicType()) { - return CheckBinaryOperatorEqualDynamic(left, right, pos); - } + if (unboxed_l != nullptr && unboxed_r != nullptr) { + if (unboxed_l->HasTypeFlag(checker::TypeFlag::ETS_BOOLEAN) && + unboxed_r->HasTypeFlag(checker::TypeFlag::ETS_BOOLEAN)) { + if (unboxed_l->HasTypeFlag(checker::TypeFlag::CONSTANT) && + unboxed_r->HasTypeFlag(checker::TypeFlag::CONSTANT)) { + const bool res = unboxed_l->AsETSBooleanType()->GetValue() == unboxed_r->AsETSBooleanType()->GetValue(); - if (IsReferenceType(left_type) && IsReferenceType(right_type)) { - ts_type = GlobalETSBooleanType(); - auto *op_type = GlobalETSObjectType(); - return {ts_type, op_type}; - } + ts_type = CreateETSBooleanType(positive_equal ? res : !res); + return {ts_type, op_type}; + } + op_type = GlobalETSBooleanType(); - if (unboxed_l != nullptr && unboxed_l->HasTypeFlag(checker::TypeFlag::ETS_BOOLEAN) && unboxed_r != nullptr && - unboxed_r->HasTypeFlag(checker::TypeFlag::ETS_BOOLEAN)) { - if (unboxed_l->HasTypeFlag(checker::TypeFlag::CONSTANT) && - unboxed_r->HasTypeFlag(checker::TypeFlag::CONSTANT)) { - bool res = unboxed_l->AsETSBooleanType()->GetValue() == unboxed_r->AsETSBooleanType()->GetValue(); + } else if (unboxed_l->HasTypeFlag(checker::TypeFlag::CHAR) && unboxed_r->HasTypeFlag(checker::TypeFlag::CHAR)) { + if (unboxed_l->HasTypeFlag(checker::TypeFlag::CONSTANT) && + unboxed_r->HasTypeFlag(checker::TypeFlag::CONSTANT)) { + const bool res = unboxed_l->AsCharType()->GetValue() == unboxed_r->AsCharType()->GetValue(); - ts_type = CreateETSBooleanType(operation_type == lexer::TokenType::PUNCTUATOR_EQUAL ? res : !res); - return {ts_type, ts_type}; + ts_type = CreateETSBooleanType(positive_equal ? res : !res); + return {ts_type, op_type}; + } + op_type = GlobalCharType(); } - FlagExpressionWithUnboxing(left_type, unboxed_l, left); - FlagExpressionWithUnboxing(right_type, unboxed_r, right); + if (op_type != nullptr) { + FlagExpressionWithUnboxing(left_type, unboxed_l, left); + FlagExpressionWithUnboxing(right_type, unboxed_r, right); - ts_type = GlobalETSBooleanType(); - return {ts_type, ts_type}; + return {ts_type, op_type}; + } } return {nullptr, nullptr}; } @@ -524,9 +547,7 @@ std::tuple ETSChecker::CheckBinaryOperator(ir::Expression *left, break; } case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL: - case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: { - return CheckBinaryOperatorStrictEqual(left, pos, left_type, right_type); - } + case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: case lexer::TokenType::PUNCTUATOR_EQUAL: case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: { std::tuple res = diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index b1f99ba5be..bb94ce3272 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -1341,7 +1341,7 @@ bool ETSChecker::IsTypeBuiltinType(Type *type) bool ETSChecker::IsReferenceType(const Type *type) { return type->HasTypeFlag(checker::TypeFlag::ETS_ARRAY_OR_OBJECT) || type->IsETSNullLike() || - type->IsETSStringType(); + type->IsETSFunctionType(); } const ir::AstNode *ETSChecker::FindJumpTarget(ir::AstNodeType node_type, const ir::AstNode *node, diff --git a/ets2panda/checker/types/ets/etsFunctionType.cpp b/ets2panda/checker/types/ets/etsFunctionType.cpp index b67c53ca99..721f608cea 100644 --- a/ets2panda/checker/types/ets/etsFunctionType.cpp +++ b/ets2panda/checker/types/ets/etsFunctionType.cpp @@ -51,6 +51,16 @@ void ETSFunctionType::Identical(TypeRelation *relation, Type *other) call_signatures_[0]->Identical(relation, other->AsETSFunctionType()->CallSignatures()[0]); } +void ETSFunctionType::Cast(TypeRelation *const relation, Type *target) +{ + if (!target->IsETSFunctionType()) { + relation->Result(false); + } + + Identical(relation, target); + // TODO(TorokG): Implement casting for function types as specification expects +} + bool ETSFunctionType::AssignmentSource(TypeRelation *relation, Type *target) { if (target->IsETSDynamicType()) { diff --git a/ets2panda/checker/types/ets/etsFunctionType.h b/ets2panda/checker/types/ets/etsFunctionType.h index 012c71251b..915982d7fb 100644 --- a/ets2panda/checker/types/ets/etsFunctionType.h +++ b/ets2panda/checker/types/ets/etsFunctionType.h @@ -114,6 +114,7 @@ public: Signature *FirstAbstractSignature(); void ToString(std::stringstream &ss) const override; void Identical(TypeRelation *relation, Type *other) override; + void Cast(TypeRelation *relation, Type *target) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; bool AssignmentSource(TypeRelation *relation, Type *target) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *global_types) override; diff --git a/ets2panda/compiler/core/ETSGen.cpp b/ets2panda/compiler/core/ETSGen.cpp index 30b8519653..3b976d1cdb 100644 --- a/ets2panda/compiler/core/ETSGen.cpp +++ b/ets2panda/compiler/core/ETSGen.cpp @@ -1814,12 +1814,12 @@ void ETSGen::Binary(const ir::AstNode *node, lexer::TokenType op, VReg lhs) } case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL: { Label *if_false = AllocLabel(); - BinaryStrictEquality(node, lhs, if_false); + BinaryEquality(node, lhs, if_false); break; } case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: { Label *if_false = AllocLabel(); - BinaryStrictEquality(node, lhs, if_false); + BinaryEquality(node, lhs, if_false); break; } case lexer::TokenType::PUNCTUATOR_LESS_THAN: { @@ -1921,11 +1921,11 @@ void ETSGen::Condition(const ir::AstNode *node, lexer::TokenType op, VReg lhs, L { switch (op) { case lexer::TokenType::PUNCTUATOR_EQUAL: { - BinaryEqualityCondition(node, lhs, if_false); + BinaryEqualityCondition(node, lhs, if_false); break; } case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: { - BinaryEqualityCondition(node, lhs, if_false); + BinaryEqualityCondition(node, lhs, if_false); break; } case lexer::TokenType::PUNCTUATOR_LESS_THAN: { @@ -2062,62 +2062,6 @@ void ETSGen::EmitNullishException(const ir::AstNode *node) SetAccumulatorType(nullptr); } -void ETSGen::BinaryEqualityRefDynamic(const ir::AstNode *node, bool test_equal, VReg lhs, VReg rhs, Label *if_false) -{ - // NOTE: vpukhov. implement - LoadAccumulator(node, lhs); - if (test_equal) { - Ra().Emit(node, rhs, if_false); - } else { - Ra().Emit(node, rhs, if_false); - } -} - -void ETSGen::BinaryEqualityRef(const ir::AstNode *node, bool test_equal, VReg lhs, VReg rhs, Label *if_false) -{ - Label *if_true = AllocLabel(); - if (GetVRegType(lhs)->IsETSDynamicType() || GetVRegType(rhs)->IsETSDynamicType()) { - BinaryEqualityRefDynamic(node, test_equal, lhs, rhs, if_false); - return; - } - - if (GetVRegType(lhs)->IsETSNullLike() || GetVRegType(rhs)->IsETSNullLike()) { - LoadAccumulator(node, GetVRegType(lhs)->IsETSNullLike() ? rhs : lhs); - test_equal ? BranchIfNotNullish(node, if_false) : BranchIfNullish(node, if_false); - } else { - Label *if_lhs_nullish = AllocLabel(); - - auto const rhs_nullish_type = GetVRegType(rhs); - - LoadAccumulator(node, lhs); - BranchIfNullish(node, if_lhs_nullish); - ConvertToNonNullish(node); - StoreAccumulator(node, lhs); - - LoadAccumulator(node, rhs); - BranchIfNullish(node, test_equal ? if_false : if_true); - ConvertToNonNullish(node); - StoreAccumulator(node, rhs); - - LoadAccumulator(node, lhs); - if (GetVRegType(lhs)->IsETSStringType()) { - CallThisStatic1(node, lhs, Signatures::BUILTIN_STRING_EQUALS, rhs); - } else { - CallThisVirtual1(node, lhs, Signatures::BUILTIN_OBJECT_EQUALS, rhs); - } - test_equal ? BranchIfFalse(node, if_false) : BranchIfTrue(node, if_false); - JumpTo(node, if_true); - - SetLabel(node, if_lhs_nullish); - LoadAccumulator(node, rhs); - SetAccumulatorType(rhs_nullish_type); - test_equal ? BranchIfNotNullish(node, if_false) : BranchIfNullish(node, if_false); - // fallthrough - } - SetLabel(node, if_true); - SetAccumulatorType(nullptr); -} - void ETSGen::CompileStatements(const ArenaVector &statements) { for (const auto *stmt : statements) { diff --git a/ets2panda/compiler/core/ETSGen.h b/ets2panda/compiler/core/ETSGen.h index 7ee98c5619..430f1887a7 100644 --- a/ets2panda/compiler/core/ETSGen.h +++ b/ets2panda/compiler/core/ETSGen.h @@ -706,9 +706,6 @@ private: } } - void BinaryEqualityRef(const ir::AstNode *node, bool test_equal, VReg lhs, VReg rhs, Label *if_false); - void BinaryEqualityRefDynamic(const ir::AstNode *node, bool test_equal, VReg lhs, VReg rhs, Label *if_false); - template void BinaryNumberComparison(const ir::AstNode *node, VReg lhs, Label *if_false) { @@ -727,25 +724,30 @@ private: template void BinaryEquality(const ir::AstNode *node, VReg lhs, Label *if_false) { - BinaryEqualityCondition(node, lhs, if_false); + BinaryEqualityCondition(node, lhs, if_false); + ToBinaryResult(node, if_false); SetAccumulatorType(Checker()->GlobalETSBooleanType()); } - template + template void BinaryEqualityCondition(const ir::AstNode *node, VReg lhs, Label *if_false) { auto type_kind = checker::ETSChecker::TypeKind(target_type_); switch (type_kind) { - case checker::TypeFlag::ETS_OBJECT: case checker::TypeFlag::ETS_DYNAMIC_TYPE: { - RegScope rs(this); - VReg arg0 = AllocReg(); - StoreAccumulator(node, arg0); - BinaryEqualityRef(node, !std::is_same_v, lhs, arg0, if_false); + if (!std::is_same_v) { + Ra().Emit(node, lhs, if_false); + } else { + Ra().Emit(node, lhs, if_false); + } return; } + case checker::TypeFlag::ETS_OBJECT: { + Ra().Emit(node, lhs, if_false); + break; + } case checker::TypeFlag::DOUBLE: { BinaryFloatingPointComparison(node, lhs, if_false); break; @@ -776,19 +778,6 @@ private: SetAccumulatorType(Checker()->GlobalETSBooleanType()); } - template - void BinaryStrictEquality(const ir::AstNode *node, VReg lhs, Label *if_false) - { - if (GetAccumulatorType()->IsETSDynamicType() || GetVRegType(lhs)->IsETSDynamicType()) { - BinaryDynamicStrictEquality(node, lhs, if_false); - } else { - Ra().Emit(node, lhs, if_false); - } - - ToBinaryResult(node, if_false); - SetAccumulatorType(Checker()->GlobalETSBooleanType()); - } - template void BinaryRelation(const ir::AstNode *node, VReg lhs, Label *if_false) { diff --git a/ets2panda/test/compiler/ets/dynamic-equality-error-expected.txt b/ets2panda/test/compiler/ets/dynamic-equality-error-expected.txt index e573b947a5..af5f0e0bef 100644 --- a/ets2panda/test/compiler/ets/dynamic-equality-error-expected.txt +++ b/ets2panda/test/compiler/ets/dynamic-equality-error-expected.txt @@ -1 +1 @@ -TypeError: The operands of strict equality are not compatible with each other [dynamic-equality-error.ets:29:9] +TypeError: The operands of reference equality are not compatible with each other [dynamic-equality-error.ets:29:9] diff --git a/ets2panda/test/compiler/ets/referenceEqualityNotCastable_n-expected.txt b/ets2panda/test/compiler/ets/referenceEqualityNotCastable_n-expected.txt index 43de9aa528..90b9aebe75 100644 --- a/ets2panda/test/compiler/ets/referenceEqualityNotCastable_n-expected.txt +++ b/ets2panda/test/compiler/ets/referenceEqualityNotCastable_n-expected.txt @@ -929,4 +929,4 @@ } } } -TypeError: The operands of strict equality are not compatible with each other [referenceEqualityNotCastable_n.ets:22:11] +TypeError: The operands of reference equality are not compatible with each other [referenceEqualityNotCastable_n.ets:22:11] diff --git a/ets2panda/test/compiler/ets/referenceEqualityNotReference_n-expected.txt b/ets2panda/test/compiler/ets/referenceEqualityNotReference_n-expected.txt deleted file mode 100644 index b3de43ef5a..0000000000 --- a/ets2panda/test/compiler/ets/referenceEqualityNotReference_n-expected.txt +++ /dev/null @@ -1,548 +0,0 @@ -{ - "type": "Program", - "statements": [ - { - "type": "ClassDeclaration", - "definition": { - "id": { - "type": "Identifier", - "name": "ETSGLOBAL", - "decorators": [], - "loc": { - "start": { - "line": 1, - "column": 1 - }, - "end": { - "line": 1, - "column": 1 - } - } - }, - "superClass": null, - "implements": [], - "body": [ - { - "type": "MethodDefinition", - "key": { - "type": "Identifier", - "name": "_$init$_", - "decorators": [], - "loc": { - "start": { - "line": 1, - "column": 1 - }, - "end": { - "line": 1, - "column": 1 - } - } - }, - "kind": "method", - "accessibility": "public", - "static": true, - "optional": false, - "computed": false, - "value": { - "type": "FunctionExpression", - "function": { - "type": "ScriptFunction", - "id": { - "type": "Identifier", - "name": "_$init$_", - "decorators": [], - "loc": { - "start": { - "line": 1, - "column": 1 - }, - "end": { - "line": 1, - "column": 1 - } - } - }, - "generator": false, - "async": false, - "expression": false, - "params": [], - "body": { - "type": "BlockStatement", - "statements": [], - "loc": { - "start": { - "line": 1, - "column": 1 - }, - "end": { - "line": 1, - "column": 1 - } - } - }, - "loc": { - "start": { - "line": 1, - "column": 1 - }, - "end": { - "line": 1, - "column": 1 - } - } - }, - "loc": { - "start": { - "line": 1, - "column": 1 - }, - "end": { - "line": 1, - "column": 1 - } - } - }, - "overloads": [], - "decorators": [], - "loc": { - "start": { - "line": 1, - "column": 1 - }, - "end": { - "line": 1, - "column": 1 - } - } - }, - { - "type": "MethodDefinition", - "key": { - "type": "Identifier", - "name": "main", - "decorators": [], - "loc": { - "start": { - "line": 16, - "column": 10 - }, - "end": { - "line": 16, - "column": 14 - } - } - }, - "kind": "method", - "accessibility": "public", - "static": true, - "optional": false, - "computed": false, - "value": { - "type": "FunctionExpression", - "function": { - "type": "ScriptFunction", - "id": { - "type": "Identifier", - "name": "main", - "decorators": [], - "loc": { - "start": { - "line": 16, - "column": 10 - }, - "end": { - "line": 16, - "column": 14 - } - } - }, - "generator": false, - "async": false, - "expression": false, - "params": [], - "returnType": { - "type": "ETSTypeReference", - "part": { - "type": "ETSTypeReferencePart", - "name": { - "type": "Identifier", - "name": "void", - "decorators": [], - "loc": { - "start": { - "line": 16, - "column": 18 - }, - "end": { - "line": 16, - "column": 22 - } - } - }, - "loc": { - "start": { - "line": 16, - "column": 18 - }, - "end": { - "line": 16, - "column": 24 - } - } - }, - "loc": { - "start": { - "line": 16, - "column": 18 - }, - "end": { - "line": 16, - "column": 24 - } - } - }, - "body": { - "type": "BlockStatement", - "statements": [ - { - "type": "VariableDeclaration", - "declarations": [ - { - "type": "VariableDeclarator", - "id": { - "type": "Identifier", - "name": "a", - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 17, - "column": 11 - }, - "end": { - "line": 17, - "column": 14 - } - } - }, - "decorators": [], - "loc": { - "start": { - "line": 17, - "column": 7 - }, - "end": { - "line": 17, - "column": 8 - } - } - }, - "init": { - "type": "NumberLiteral", - "value": 1, - "loc": { - "start": { - "line": 17, - "column": 17 - }, - "end": { - "line": 17, - "column": 18 - } - } - }, - "loc": { - "start": { - "line": 17, - "column": 7 - }, - "end": { - "line": 17, - "column": 18 - } - } - } - ], - "kind": "let", - "loc": { - "start": { - "line": 17, - "column": 3 - }, - "end": { - "line": 17, - "column": 19 - } - } - }, - { - "type": "VariableDeclaration", - "declarations": [ - { - "type": "VariableDeclarator", - "id": { - "type": "Identifier", - "name": "b", - "typeAnnotation": { - "type": "ETSTypeReference", - "part": { - "type": "ETSTypeReferencePart", - "name": { - "type": "Identifier", - "name": "Int", - "decorators": [], - "loc": { - "start": { - "line": 18, - "column": 11 - }, - "end": { - "line": 18, - "column": 14 - } - } - }, - "loc": { - "start": { - "line": 18, - "column": 11 - }, - "end": { - "line": 18, - "column": 16 - } - } - }, - "loc": { - "start": { - "line": 18, - "column": 11 - }, - "end": { - "line": 18, - "column": 16 - } - } - }, - "decorators": [], - "loc": { - "start": { - "line": 18, - "column": 7 - }, - "end": { - "line": 18, - "column": 8 - } - } - }, - "init": { - "type": "NumberLiteral", - "value": 1, - "loc": { - "start": { - "line": 18, - "column": 17 - }, - "end": { - "line": 18, - "column": 18 - } - } - }, - "loc": { - "start": { - "line": 18, - "column": 7 - }, - "end": { - "line": 18, - "column": 18 - } - } - } - ], - "kind": "let", - "loc": { - "start": { - "line": 18, - "column": 3 - }, - "end": { - "line": 18, - "column": 19 - } - } - }, - { - "type": "VariableDeclaration", - "declarations": [ - { - "type": "VariableDeclarator", - "id": { - "type": "Identifier", - "name": "c", - "decorators": [], - "loc": { - "start": { - "line": 19, - "column": 7 - }, - "end": { - "line": 19, - "column": 8 - } - } - }, - "init": { - "type": "BinaryExpression", - "operator": "===", - "left": { - "type": "Identifier", - "name": "a", - "decorators": [], - "loc": { - "start": { - "line": 19, - "column": 11 - }, - "end": { - "line": 19, - "column": 12 - } - } - }, - "right": { - "type": "Identifier", - "name": "b", - "decorators": [], - "loc": { - "start": { - "line": 19, - "column": 17 - }, - "end": { - "line": 19, - "column": 18 - } - } - }, - "loc": { - "start": { - "line": 19, - "column": 11 - }, - "end": { - "line": 19, - "column": 18 - } - } - }, - "loc": { - "start": { - "line": 19, - "column": 7 - }, - "end": { - "line": 19, - "column": 18 - } - } - } - ], - "kind": "let", - "loc": { - "start": { - "line": 19, - "column": 3 - }, - "end": { - "line": 19, - "column": 19 - } - } - } - ], - "loc": { - "start": { - "line": 16, - "column": 23 - }, - "end": { - "line": 20, - "column": 2 - } - } - }, - "loc": { - "start": { - "line": 16, - "column": 14 - }, - "end": { - "line": 20, - "column": 2 - } - } - }, - "loc": { - "start": { - "line": 16, - "column": 14 - }, - "end": { - "line": 20, - "column": 2 - } - } - }, - "overloads": [], - "decorators": [], - "loc": { - "start": { - "line": 16, - "column": 1 - }, - "end": { - "line": 20, - "column": 2 - } - } - } - ], - "loc": { - "start": { - "line": 1, - "column": 1 - }, - "end": { - "line": 1, - "column": 1 - } - } - }, - "loc": { - "start": { - "line": 1, - "column": 1 - }, - "end": { - "line": 1, - "column": 1 - } - } - } - ], - "loc": { - "start": { - "line": 1, - "column": 1 - }, - "end": { - "line": 21, - "column": 1 - } - } -} -TypeError: Both operands have to be reference types [referenceEqualityNotReference_n.ets:19:11] diff --git a/ets2panda/test/compiler/ets/referenceEqualityNotReference_n.ets b/ets2panda/test/compiler/ets/referenceEqualityNotReference_n.ets deleted file mode 100644 index c0e489e70d..0000000000 --- a/ets2panda/test/compiler/ets/referenceEqualityNotReference_n.ets +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2021-2023 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. - */ - -function main(): void { - let a : int = 1; - let b : Int = 1; - let c = a === b; -} diff --git a/ets2panda/test/runtime/ets/array-object.ets b/ets2panda/test/runtime/ets/array-object.ets index 0228add708..bb36d33e9f 100644 --- a/ets2panda/test/runtime/ets/array-object.ets +++ b/ets2panda/test/runtime/ets/array-object.ets @@ -36,7 +36,9 @@ function main(): void { assert(arr1 == arr1); assert(arr1 == object_array); assert(arr1 == object); - assert(arr1 != arr2); + +// TypeError: The operands of reference equality are not compatible with each other +// assert(arr1 != arr2); assert(object.equals(arr1 as Object) == true); // Cannot cast type 'int[]' to 'Object[]' diff --git a/ets2panda/test/runtime/ets/dollar_dollar.ets b/ets2panda/test/runtime/ets/dollar_dollar.ets index 24ae08d8a2..69ee93d97d 100644 --- a/ets2panda/test/runtime/ets/dollar_dollar.ets +++ b/ets2panda/test/runtime/ets/dollar_dollar.ets @@ -18,6 +18,6 @@ function main() { let a = "aaaddd" let b = $$a } catch (e) { - assert(e.toString() == "$$ operator can only be used with ARKUI plugin") + assert(e.toString().equals("$$ operator can only be used with ARKUI plugin")) } } diff --git a/ets2panda/test/runtime/ets/notNull.ets b/ets2panda/test/runtime/ets/notNull.ets index 448280c9b2..f1de266db5 100644 --- a/ets2panda/test/runtime/ets/notNull.ets +++ b/ets2panda/test/runtime/ets/notNull.ets @@ -51,7 +51,7 @@ function testLocalArray() : void { arr![2][1] = 42; - assert arr[2][1].toString() == "42" : "arr[2][1].toString() must be '42'"; + assert arr[2][1].toString().equals("42") : "arr[2][1].toString() must be '42'"; } function bar(arg : Int | null) : Int { diff --git a/ets2panda/test/runtime/ets/optional-chaining-lazy-evaluation.ets b/ets2panda/test/runtime/ets/optional-chaining-lazy-evaluation.ets index af36ee6e0e..a917420727 100644 --- a/ets2panda/test/runtime/ets/optional-chaining-lazy-evaluation.ets +++ b/ets2panda/test/runtime/ets/optional-chaining-lazy-evaluation.ets @@ -24,7 +24,6 @@ function main(): void { let obj: Int[] = [11, 21, 31]; number = obj?.[x++]; - let a : Int = 11; - assert(number == a); + assert(number == obj?.[0]); assert(x == 1); // 1 as x was incremented } diff --git a/ets2panda/test/runtime/ets/referenceEquality.ets b/ets2panda/test/runtime/ets/referenceEquality.ets index a9a2b82478..3570f64fc8 100644 --- a/ets2panda/test/runtime/ets/referenceEquality.ets +++ b/ets2panda/test/runtime/ets/referenceEquality.ets @@ -27,6 +27,13 @@ function ClassEquality(): void { assert (a === b); let c : A = new A(); assert (a !== c); + + assert(new A() != new A()) + let x1 = new A() + let x2 = x1 + assert(x1 == x2) + + assert(5 == new Int(5)) } @@ -37,6 +44,22 @@ function NullEquality(): void { let c : A | null = null; assert (c === null); assert (null === null); + + assert(5 != null) + assert("a string" != null) + assert(5.0 != null) + + let x: A | null = null + assert(x == null) + + assert(null != new Int(5)) + assert(new Double(5) != null) + + let i: Int|null = null + assert(i == null) + + let f: Int|null = 1 + assert(f != null) } @@ -46,6 +69,11 @@ function ArrayEquality(): void { assert (a === b); let c : int[] = [1, 2, 3]; assert (a !== c); + + assert([1, 2, 3] != [1, 2, 3]) + let y1 : Object[] = [] + let y2 = y1 + assert(y1 == y2) } function NumericEquality(): void { diff --git a/ets2panda/test/runtime/ets/string-assignment.ets b/ets2panda/test/runtime/ets/string-assignment.ets index 31953297e2..7ebbcf9ed5 100644 --- a/ets2panda/test/runtime/ets/string-assignment.ets +++ b/ets2panda/test/runtime/ets/string-assignment.ets @@ -16,5 +16,5 @@ function main(): void { let str = "constant string literal"; // init with a const string literal without "String" annotation -> str shouldn't be const str = "new string value"; - assert (str + "123" == "new string value123") + assert ((str + "123").equals("new string value123")) } diff --git a/ets2panda/test/runtime/ets/string-builder.ets b/ets2panda/test/runtime/ets/string-builder.ets index fb12505039..d944872d9a 100644 --- a/ets2panda/test/runtime/ets/string-builder.ets +++ b/ets2panda/test/runtime/ets/string-builder.ets @@ -27,10 +27,10 @@ function concatenate_float(prefix: String, number: float, suffix: String) : Stri function concatenate_compile_time() : void { let x: String = 5 + "10"; - assert x == "510"; + assert x.equals("510"); let y = 5 + "10"; - assert y == "510"; + assert y.equals("510"); } function main(): void { @@ -38,13 +38,13 @@ function main(): void { let a: String = "abc"; a += foo(123); - assert a == "abcd"; + assert a.equals("abcd"); assert count == 1; let const_str: String = 'str' + c'a'; - assert const_str == "stra"; + assert const_str.equals("stra"); - assert concatenate_float('x', 1.0 as float, "y") == "x1y"; + assert concatenate_float('x', 1.0 as float, "y").equals("x1y"); concatenate_compile_time(); } diff --git a/ets2panda/test/runtime/ets/top_level_02.ets b/ets2panda/test/runtime/ets/top_level_02.ets index 17b996c4de..c3de3615a7 100644 --- a/ets2panda/test/runtime/ets/top_level_02.ets +++ b/ets2panda/test/runtime/ets/top_level_02.ets @@ -45,7 +45,7 @@ catch (e) { } assert(q == 8) -assert(s == "abccba") +assert(s.equals("abccba")) function main(): void { ETSGLOBAL.q = 1; @@ -54,13 +54,13 @@ function main(): void { assert(q == 30) assert(ETSGLOBAL.q == 1) - assert(s == "abccba") + assert(s.equals("abccba")) s = "def"; assert(s == "def") _$init$_(); - assert(s == "abccba") + assert(s.equals("abccba")) assert(q == 30) assert(ETSGLOBAL.q == 8) } -- Gitee