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 c78ac64ba9f..66db3defb7e 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 b1f99ba5be3..bb94ce32723 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 b67c53ca99d..721f608cead 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 012c71251b1..915982d7fbd 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 30b85196537..3b976d1cdbe 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 7ee98c5619f..430f1887a71 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 e573b947a51..af5f0e0befc 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 43de9aa5285..90b9aebe75b 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 b3de43ef5ab..00000000000 --- 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 c0e489e70da..00000000000 --- 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 0228add708c..bb36d33e9ff 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 24ae08d8a24..69ee93d97d2 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 448280c9b28..f1de266db50 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 af36ee6e0e2..a9174207279 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 a9a2b824786..3570f64fc8d 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 31953297e27..7ebbcf9ed51 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 fb125050393..d944872d9a9 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 17b996c4de8..c3de3615a74 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