diff --git a/es2panda/compiler/core/pandagen.cpp b/es2panda/compiler/core/pandagen.cpp index 3488d439f952da11a35264406b67230d14273577..ed81f39bda747cb44eb20fb1f2ce7059381ed9ba 100644 --- a/es2panda/compiler/core/pandagen.cpp +++ b/es2panda/compiler/core/pandagen.cpp @@ -1071,6 +1071,16 @@ void PandaGen::BranchIfFalse(const ir::AstNode *node, Label *target) sa_.Emit(node, target); } +void PandaGen::BranchIfStrictNull(const ir::AstNode *node, class Label *target) +{ + RegScope rs(this); + VReg tmp = AllocReg(); + StoreAccumulator(node, tmp); + LoadConst(node, Constant::JS_NULL); + ra_.Emit(node, 0, tmp); + sa_.Emit(node, target); +} + void PandaGen::EmitThrow(const ir::AstNode *node) { sa_.Emit(node); diff --git a/es2panda/compiler/core/pandagen.h b/es2panda/compiler/core/pandagen.h index cdc5a69bc9ed5f42fb9da97f9fd51da737b5fb8d..02f17f126c47a1ff4fc5e9a07f92a24a23c8b918 100644 --- a/es2panda/compiler/core/pandagen.h +++ b/es2panda/compiler/core/pandagen.h @@ -313,6 +313,7 @@ public: void BranchIfNotTrue(const ir::AstNode *node, class Label *target); void BranchIfFalse(const ir::AstNode *node, class Label *target); void BranchIfNotFalse(const ir::AstNode *node, class Label *target); + void BranchIfStrictNull(const ir::AstNode *node, class Label *target); void EmitThrow(const ir::AstNode *node); void EmitRethrow(const ir::AstNode *node); diff --git a/es2panda/ir/expressions/binaryExpression.cpp b/es2panda/ir/expressions/binaryExpression.cpp index 58fafd3d1a41622633100c6088c0469c3a934243..526685b4539eab37581d8a00f570c329290018f7 100644 --- a/es2panda/ir/expressions/binaryExpression.cpp +++ b/es2panda/ir/expressions/binaryExpression.cpp @@ -43,13 +43,9 @@ void BinaryExpression::CompileLogical(compiler::PandaGen *pg) const compiler::RegScope rs(pg); compiler::VReg lhs = pg->AllocReg(); - if (operator_ == lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING) { - // TODO(parser): Nullish Coalesce - compiler::PandaGen::Unimplemented(); - } - ASSERT(operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_AND || - operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_OR); + operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_OR || + operator_ == lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING); auto *skipRight = pg->AllocLabel(); auto *endLabel = pg->AllocLabel(); @@ -59,9 +55,17 @@ void BinaryExpression::CompileLogical(compiler::PandaGen *pg) const if (operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_AND) { pg->BranchIfFalse(this, skipRight); - } else { - ASSERT(operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_OR); + } else if (operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_OR) { pg->BranchIfTrue(this, skipRight); + } else { + ASSERT(operator_ == lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING); + auto *nullish = pg->AllocLabel(); + // if lhs === null + pg->BranchIfStrictNull(this, nullish); + pg->LoadAccumulator(this, lhs); + // if lhs === undefined + pg->BranchIfStrictNotUndefined(this, skipRight); + pg->SetLabel(this, nullish); } // left is true/false(and/or) then right -> acc diff --git a/es2panda/test/compiler/js/binaryExpression/nullishCoalesce-expected.txt b/es2panda/test/compiler/js/binaryExpression/nullishCoalesce-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..0429fae9e5f6d96184dd0c4c28363722419c29ae --- /dev/null +++ b/es2panda/test/compiler/js/binaryExpression/nullishCoalesce-expected.txt @@ -0,0 +1,3 @@ +2 +4 +5 diff --git a/es2panda/test/compiler/js/binaryExpression/nullishCoalesce.js b/es2panda/test/compiler/js/binaryExpression/nullishCoalesce.js new file mode 100644 index 0000000000000000000000000000000000000000..45d895e52b0c7698db93bde72f804725bda90863 --- /dev/null +++ b/es2panda/test/compiler/js/binaryExpression/nullishCoalesce.js @@ -0,0 +1,9 @@ +let a = 2; +let b = a ?? 3; +print(b); +a = null; +b = a ?? 4; +print(b); +a = undefined; +b = a ?? 5; +print(b); \ No newline at end of file