diff --git a/es2panda/compiler/core/pandagen.cpp b/es2panda/compiler/core/pandagen.cpp index cb818ac68f57e31e9ddd21af5ca4dae22c80ceee..8f73b7758a4f74ca6a6589943d43af6486934719 100644 --- a/es2panda/compiler/core/pandagen.cpp +++ b/es2panda/compiler/core/pandagen.cpp @@ -961,6 +961,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, 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 445d4abb0d11c42b2c9a16ded51ee42cca415b2f..640c497ba9f158f6294aa1c1953d40a03ff4078d 100644 --- a/es2panda/compiler/core/pandagen.h +++ b/es2panda/compiler/core/pandagen.h @@ -281,6 +281,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 b34d315374d101bd1318826ee4e66f230cd3c16a..c00c7d434de4f4e8d4a38063e17288cf5b54ce81 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..294f02e8dc5fe7c0d582271d309f9140ecfa4ab3 --- /dev/null +++ b/es2panda/test/compiler/js/binaryExpression/nullishCoalesce-expected.txt @@ -0,0 +1,5 @@ +2 +4 +52 +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..1d4d4f020825a800f560c6ad39f8bacd35d870b1 --- /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);