From ce604df9e50f1702f7cb3320a48d1ef16d049fff Mon Sep 17 00:00:00 2001 From: gavin1012_hw Date: Tue, 19 Jul 2022 17:04:37 +0800 Subject: [PATCH] Support chain expression Issue: I5IH79 Signed-off-by: gavin1012_hw Change-Id: I459aa005eedb7c2deb02ba958d4767585e7c888a --- es2panda/ir/expressions/chainExpression.cpp | 36 ++++++++++++++++++++- es2panda/ir/expressions/chainExpression.h | 2 +- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/es2panda/ir/expressions/chainExpression.cpp b/es2panda/ir/expressions/chainExpression.cpp index 16e2b3a299..6a49a01d90 100644 --- a/es2panda/ir/expressions/chainExpression.cpp +++ b/es2panda/ir/expressions/chainExpression.cpp @@ -14,8 +14,11 @@ */ #include "chainExpression.h" +#include #include +#include +#include namespace panda::es2panda::ir { @@ -29,7 +32,38 @@ void ChainExpression::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "ChainExpression"}, {"expression", expression_}}); } -void ChainExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void ChainExpression::Compile(compiler::PandaGen *pg) const +{ + // TODO: support continuous optional chain expression + compiler::RegScope rs(pg); + const MemberExpression *memberExpr = nullptr; + if (this->GetExpression()->IsMemberExpression()) { + memberExpr = this->GetExpression()->AsMemberExpression(); + } else { + auto callExpr = this->GetExpression()->AsCallExpression(); + memberExpr = callExpr->Callee()->AsMemberExpression(); + } + + compiler::VReg objReg = pg->AllocReg(); + auto *isNullOrUndefinedLabel = pg->AllocLabel(); + auto *endLabel = pg->AllocLabel(); + + memberExpr->CompileObject(pg, objReg); + pg->LoadConst(this, compiler::Constant::JS_NULL); + pg->Condition(this, lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL, objReg, isNullOrUndefinedLabel); + pg->LoadConst(this, compiler::Constant::JS_UNDEFINED); + pg->Condition(this, lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL, objReg, isNullOrUndefinedLabel); + + // obj (ahead ?.) is not null/undefined, continue to compile sub-expression) + this->GetExpression()->Compile(pg); + pg->Branch(this, endLabel); + + // obj (ahead ?.) is null/undefined, return undefined) + pg->SetLabel(this, isNullOrUndefinedLabel); + pg->LoadConst(this, compiler::Constant::JS_UNDEFINED); + + pg->SetLabel(this, endLabel); +} checker::Type *ChainExpression::Check([[maybe_unused]] checker::Checker *checker) const { diff --git a/es2panda/ir/expressions/chainExpression.h b/es2panda/ir/expressions/chainExpression.h index 571d10c89b..e31ed7c391 100644 --- a/es2panda/ir/expressions/chainExpression.h +++ b/es2panda/ir/expressions/chainExpression.h @@ -43,7 +43,7 @@ public: void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; - void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + void Compile(compiler::PandaGen *pg) const override; checker::Type *Check([[maybe_unused]] checker::Checker *checker) const override; private: -- Gitee