From 7996dccc4b5f102f58c30d6d36a67aaea5e89fb7 Mon Sep 17 00:00:00 2001 From: hufeng Date: Sat, 25 Feb 2023 11:20:25 +0800 Subject: [PATCH] Implement logical assignment operators [ECMA-2021] Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I6GG2Z?from=project-issue Signed-off-by: hufeng Change-Id: Ib1c5c734189786eda1d450edc5161ccb75209b8e --- es2panda/compiler/core/pandagen.cpp | 5 -- .../ir/expressions/assignmentExpression.cpp | 31 ++++++++++- ...pression-with-assignment-done-expected.txt | 4 ++ ...sigment-expression-with-assignment-done.js | 13 +++++ ...ession-with-assignment-undone-expected.txt | 3 ++ ...gment-expression-with-assignment-undone.js | 10 ++++ test262/es2021_tests.txt | 54 +++++++++++++++++++ 7 files changed, 113 insertions(+), 7 deletions(-) create mode 100644 es2panda/test/compiler/js/language/expressions/assignment/test-logic-assigment-expression-with-assignment-done-expected.txt create mode 100644 es2panda/test/compiler/js/language/expressions/assignment/test-logic-assigment-expression-with-assignment-done.js create mode 100644 es2panda/test/compiler/js/language/expressions/assignment/test-logic-assigment-expression-with-assignment-undone-expected.txt create mode 100644 es2panda/test/compiler/js/language/expressions/assignment/test-logic-assigment-expression-with-assignment-undone.js diff --git a/es2panda/compiler/core/pandagen.cpp b/es2panda/compiler/core/pandagen.cpp index 125075287fb..74071c7fe60 100644 --- a/es2panda/compiler/core/pandagen.cpp +++ b/es2panda/compiler/core/pandagen.cpp @@ -988,11 +988,6 @@ void PandaGen::Binary(const ir::AstNode *node, lexer::TokenType op, VReg lhs) ra_.Emit(node, 0, lhs); break; } - case lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING: - case lexer::TokenType::PUNCTUATOR_LOGICAL_NULLISH_EQUAL: { - Unimplemented(); - break; - } default: { UNREACHABLE(); } diff --git a/es2panda/ir/expressions/assignmentExpression.cpp b/es2panda/ir/expressions/assignmentExpression.cpp index 9e89751a4ed..8b6bd222cfd 100644 --- a/es2panda/ir/expressions/assignmentExpression.cpp +++ b/es2panda/ir/expressions/assignmentExpression.cpp @@ -114,8 +114,35 @@ void AssignmentExpression::Compile(compiler::PandaGen *pg) const compiler::LReference lref = compiler::LReference::CreateLRef(pg, left_, false); if (operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_AND_EQUAL || - operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_OR_EQUAL) { - pg->Unimplemented(); + operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_OR_EQUAL || + operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_NULLISH_EQUAL) { + auto *skipRight = pg->AllocLabel(); + auto *endLabel = pg->AllocLabel(); + compiler::VReg lhsReg = pg->AllocReg(); + + lref.GetValue(); + pg->StoreAccumulator(left_, lhsReg); + if (operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_AND_EQUAL) { + pg->BranchIfFalse(left_, skipRight); + } else if (operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_OR_EQUAL) { + pg->BranchIfTrue(left_, skipRight); + } else { + ASSERT(operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_NULLISH_EQUAL); + auto *nullish = pg->AllocLabel(); + pg->BranchIfStrictNull(left_, nullish); + pg->LoadAccumulator(left_, lhsReg); + pg->BranchIfStrictNotUndefined(this, skipRight); + pg->SetLabel(left_, nullish); + } + // left = right + right_->Compile(pg); + lref.SetValue(); + pg->Branch(this, endLabel); + // skip right part + pg->SetLabel(this, skipRight); + pg->LoadAccumulator(this, lhsReg); + pg->SetLabel(this, endLabel); + return; } else if (operator_ != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { compiler::VReg lhsReg = pg->AllocReg(); diff --git a/es2panda/test/compiler/js/language/expressions/assignment/test-logic-assigment-expression-with-assignment-done-expected.txt b/es2panda/test/compiler/js/language/expressions/assignment/test-logic-assigment-expression-with-assignment-done-expected.txt new file mode 100644 index 00000000000..310be0621c3 --- /dev/null +++ b/es2panda/test/compiler/js/language/expressions/assignment/test-logic-assigment-expression-with-assignment-done-expected.txt @@ -0,0 +1,4 @@ +123 +123 +123 +123 diff --git a/es2panda/test/compiler/js/language/expressions/assignment/test-logic-assigment-expression-with-assignment-done.js b/es2panda/test/compiler/js/language/expressions/assignment/test-logic-assigment-expression-with-assignment-done.js new file mode 100644 index 00000000000..fa2b3e2cc14 --- /dev/null +++ b/es2panda/test/compiler/js/language/expressions/assignment/test-logic-assigment-expression-with-assignment-done.js @@ -0,0 +1,13 @@ +let a = false; +let b = true; +let c = null; +let d = undefined; +let e = 123; +a ||= e; +b &&= e; +c ??= e; +d ??= e; +print(a); +print(b); +print(c); +print(d); \ No newline at end of file diff --git a/es2panda/test/compiler/js/language/expressions/assignment/test-logic-assigment-expression-with-assignment-undone-expected.txt b/es2panda/test/compiler/js/language/expressions/assignment/test-logic-assigment-expression-with-assignment-undone-expected.txt new file mode 100644 index 00000000000..843e3b77c56 --- /dev/null +++ b/es2panda/test/compiler/js/language/expressions/assignment/test-logic-assigment-expression-with-assignment-undone-expected.txt @@ -0,0 +1,3 @@ +false +true +not null diff --git a/es2panda/test/compiler/js/language/expressions/assignment/test-logic-assigment-expression-with-assignment-undone.js b/es2panda/test/compiler/js/language/expressions/assignment/test-logic-assigment-expression-with-assignment-undone.js new file mode 100644 index 00000000000..a7812d7bbee --- /dev/null +++ b/es2panda/test/compiler/js/language/expressions/assignment/test-logic-assigment-expression-with-assignment-undone.js @@ -0,0 +1,10 @@ +let a = false; +let b = true; +let c = "not null"; +let e = 123; +b ||= e; +a &&= e; +c ??= e; +print(a); +print(b); +print(c); \ No newline at end of file diff --git a/test262/es2021_tests.txt b/test262/es2021_tests.txt index 97451dbb7d8..2c8dfed8b24 100644 --- a/test262/es2021_tests.txt +++ b/test262/es2021_tests.txt @@ -3366,3 +3366,57 @@ language/statements/for-await-of/let-identifier-with-newline.js language/statements/for-await-of/ticks-with-async-iter-resolved-promise-and-constructor-lookup.js language/statements/for-await-of/ticks-with-async-iter-resolved-promise-and-constructor-lookup-two.js language/statements/for-await-of/ticks-with-sync-iter-resolved-promise-and-constructor-lookup.js +language/expressions/logical-assignment/lgcl-nullish-non-simple.js +language/expressions/logical-assignment/lgcl-nullish-assignment-operator-lhs-before-rhs.js +language/expressions/logical-assignment/lgcl-and-assignment-operator-unresolved-rhs.js +language/expressions/logical-assignment/lgcl-nullish-arguments-strict.js +language/expressions/logical-assignment/lgcl-and-assignment-operator-non-simple-lhs.js +language/expressions/logical-assignment/lgcl-and-assignment-operator-lhs-before-rhs.js +language/expressions/logical-assignment/lgcl-nullish-assignment-operator-non-simple-lhs.js +language/expressions/logical-assignment/lgcl-nullish-assignment-operator-non-extensible.js +language/expressions/logical-assignment/lgcl-nullish-assignment-operator-unresolved-rhs.js +language/expressions/logical-assignment/lgcl-or-arguments-strict.js +language/expressions/logical-assignment/lgcl-nullish-assignment-operator-unresolved-rhs-put.js +language/expressions/logical-assignment/lgcl-and-assignment-operator-non-extensible.js +language/expressions/logical-assignment/lgcl-or-assignment-operator-non-writeable-put.js +language/expressions/logical-assignment/lgcl-nullish-assignment-operator-bigint.js +language/expressions/logical-assignment/lgcl-or-assignment-operator-unresolved-rhs-put.js +language/expressions/logical-assignment/lgcl-or-assignment-operator-namedevaluation-arrow-function.js +language/expressions/logical-assignment/lgcl-or-assignment-operator-namedevaluation-function.js +language/expressions/logical-assignment/lgcl-nullish-assignment-operator-namedevaluation-class-expression.js +language/expressions/logical-assignment/lgcl-and-assignment-operator-non-writeable.js +language/expressions/logical-assignment/lgcl-or-non-simple.js +language/expressions/logical-assignment/lgcl-and-assignment-operator-unresolved-rhs-put.js +language/expressions/logical-assignment/lgcl-nullish-assignment-operator-namedevaluation-function.js +language/expressions/logical-assignment/lgcl-or-assignment-operator-bigint.js +language/expressions/logical-assignment/lgcl-and-assignment-operator-unresolved-lhs.js +language/expressions/logical-assignment/lgcl-and-whitespace.js +language/expressions/logical-assignment/lgcl-or-assignment-operator.js +language/expressions/logical-assignment/lgcl-or-assignment-operator-unresolved-lhs.js +language/expressions/logical-assignment/lgcl-and-assignment-operator-no-set-put.js +language/expressions/logical-assignment/lgcl-and-assignment-operator-namedevaluation-function.js +language/expressions/logical-assignment/lgcl-nullish-assignment-operator-unresolved-lhs.js +language/expressions/logical-assignment/lgcl-nullish-whitespace.js +language/expressions/logical-assignment/lgcl-nullish-assignment-operator.js +language/expressions/logical-assignment/lgcl-nullish-assignment-operator-no-set.js +language/expressions/logical-assignment/lgcl-and-assignment-operator-no-set.js +language/expressions/logical-assignment/lgcl-or-assignment-operator-namedevaluation-class-expression.js +language/expressions/logical-assignment/lgcl-or-assignment-operator-no-set.js +language/expressions/logical-assignment/lgcl-or-whitespace.js +language/expressions/logical-assignment/lgcl-or-assignment-operator-no-set-put.js +language/expressions/logical-assignment/lgcl-nullish-assignment-operator-no-set-put.js +language/expressions/logical-assignment/lgcl-or-assignment-operator-unresolved-rhs.js +language/expressions/logical-assignment/lgcl-and-assignment-operator-bigint.js +language/expressions/logical-assignment/lgcl-and-arguments-strict.js +language/expressions/logical-assignment/lgcl-and-non-simple.js +language/expressions/logical-assignment/lgcl-and-assignment-operator-non-writeable-put.js +language/expressions/logical-assignment/lgcl-or-assignment-operator-non-writeable.js +language/expressions/logical-assignment/lgcl-and-assignment-operator-namedevaluation-class-expression.js +language/expressions/logical-assignment/lgcl-nullish-assignment-operator-non-writeable-put.js +language/expressions/logical-assignment/lgcl-or-assignment-operator-non-extensible.js +language/expressions/logical-assignment/lgcl-or-assignment-operator-lhs-before-rhs.js +language/expressions/logical-assignment/lgcl-nullish-assignment-operator-non-writeable.js +language/expressions/logical-assignment/lgcl-nullish-assignment-operator-namedevaluation-arrow-function.js +language/expressions/logical-assignment/lgcl-and-assignment-operator.js +language/expressions/logical-assignment/lgcl-or-assignment-operator-non-simple-lhs.js +language/expressions/logical-assignment/lgcl-and-assignment-operator-namedevaluation-arrow-function.js \ No newline at end of file -- Gitee