From 8bb1d8a98beb9f8b4e1ef139c619bbdd9c66ba96 Mon Sep 17 00:00:00 2001 From: Tatiana Date: Thu, 12 Oct 2023 16:36:22 +0300 Subject: [PATCH 1/3] Add AST Verifier feature Signed-off-by: Tatiana --- BUILD.gn | 1 + CMakeLists.txt | 1 + compiler/core/ASTVerifier.cpp | 409 ++++++++++++++++++++++++++++++ compiler/core/ASTVerifier.h | 55 ++++ compiler/lowering/phase.cpp | 9 + ir/astNode.h | 10 + test/CMakeLists.txt | 12 + test/public/ast_verifier_test.cpp | 71 ++++++ 8 files changed, 568 insertions(+) create mode 100644 compiler/core/ASTVerifier.cpp create mode 100644 compiler/core/ASTVerifier.h create mode 100644 test/public/ast_verifier_test.cpp diff --git a/BUILD.gn b/BUILD.gn index 99b4a26ef..8663df872 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -138,6 +138,7 @@ libes2panda_sources = [ "compiler/core/JSCompiler.cpp", "compiler/core/JSemitter.cpp", "compiler/core/codeGen.cpp", + "compiler/core/ASTVerifier.cpp", "compiler/core/compileJob.cpp", "compiler/core/compileQueue.cpp", "compiler/core/compilerContext.cpp", diff --git a/CMakeLists.txt b/CMakeLists.txt index e49880048..b34882d04 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -102,6 +102,7 @@ set(ES2PANDA_LIB_SRC compiler/base/literals.cpp compiler/base/lreference.cpp compiler/base/optionalChain.cpp + compiler/core/ASTVerifier.cpp compiler/core/codeGen.cpp compiler/core/compileJob.cpp compiler/core/compileQueue.cpp diff --git a/compiler/core/ASTVerifier.cpp b/compiler/core/ASTVerifier.cpp new file mode 100644 index 000000000..f59438c30 --- /dev/null +++ b/compiler/core/ASTVerifier.cpp @@ -0,0 +1,409 @@ +/** + * 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. + */ + +#include "ASTVerifier.h" + +#include "es2panda.h" +#include "binder/variableFlags.h" +#include "binder/scope.h" +#include "ir/astNode.h" +#include "ir/base/catchClause.h" +#include "ir/base/classDefinition.h" +#include "ir/base/classStaticBlock.h" +#include "ir/base/methodDefinition.h" +#include "ir/base/scriptFunction.h" +#include "ir/ets/etsFunctionType.h" +#include "ir/ets/etsNewClassInstanceExpression.h" +#include "ir/ets/etsPackageDeclaration.h" +#include "ir/ets/etsParameterExpression.h" +#include "ir/ets/etsTypeReference.h" +#include "ir/ets/etsTypeReferencePart.h" +#include "ir/expressions/callExpression.h" +#include "ir/expressions/functionExpression.h" +#include "ir/expressions/identifier.h" +#include "ir/expressions/memberExpression.h" +#include "ir/expressions/literals/numberLiteral.h" +#include "ir/expressions/literals/stringLiteral.h" +#include "ir/statements/blockStatement.h" +#include "ir/statements/classDeclaration.h" +#include "ir/statements/expressionStatement.h" +#include "ir/statements/throwStatement.h" +#include "ir/statements/tryStatement.h" +#include "ir/statements/variableDeclaration.h" +#include "ir/statements/variableDeclarator.h" +#include "ir/ts/tsClassImplements.h" +#include "ir/ts/tsTypeParameter.h" +#include "ir/ts/tsTypeParameterDeclaration.h" +#include "ir/ts/tsTypeParameterInstantiation.h" + +namespace panda::es2panda::compiler { + +bool ASTVerifier::IsCorrectProgram(const parser::Program *program) +{ + bool is_correct = true; + error_messages_.clear(); + + for (auto *statement : program->Ast()->Statements()) { + is_correct &= HaveParents(statement); + } + is_correct &= HaveParents(program->GlobalClass()); + + for (auto *statement : program->Ast()->Statements()) { + is_correct &= HaveTypes(statement); + } + is_correct &= HaveTypes(program->GlobalClass()); + + for (auto *statement : program->Ast()->Statements()) { + is_correct &= HaveVariables(statement); + } + is_correct &= HaveVariables(program->GlobalClass()); + + for (auto *statement : program->Ast()->Statements()) { + is_correct &= HaveScopes(statement); + } + is_correct &= HaveScopes(program->GlobalClass()); + +#ifndef NDEBUG + std::for_each(error_messages_.begin(), error_messages_.end(), [](auto const msg) { LOG(INFO, COMMON) << msg; }); +#endif // NDEBUG + return is_correct; +} + +std::string ToStringHelper(const binder::ScopeType type) +{ + switch (type) { + case binder::ScopeType::CATCH: { + return "CATCH"; + } + case binder::ScopeType::CATCH_PARAM: { + return "CATCH_PARAM"; + } + case binder::ScopeType::CLASS: { + return "CLASS"; + } + case binder::ScopeType::FUNCTION: { + return "FUNCTION"; + } + case binder::ScopeType::FUNCTION_PARAM: { + return "FUNCTION_PARAM"; + } + case binder::ScopeType::GLOBAL: { + return "GLOBAL"; + } + case binder::ScopeType::LOCAL: { + return "LOCAL"; + } + case binder::ScopeType::LOOP: { + return "LOOP"; + } + case binder::ScopeType::LOOP_DECL: { + return "LOOP_DECL"; + } + case binder::ScopeType::MODULE: { + return "MODULE"; + } + case binder::ScopeType::PARAM: { + return "PARAM"; + } + default: { + return "MUST BE UNREACHABLE"; + } + } +} + +std::string ToStringHelper(const util::StringView &name) +{ + return name == nullptr ? "" : name.Mutf8(); +} + +std::string ToStringHelper(const binder::Scope *scope) +{ + if (scope == nullptr) { + return ""; + } + + switch (scope->Type()) { + case binder::ScopeType::FUNCTION: { + return "FUNC_SCOPE " + ToStringHelper(scope->AsFunctionScope()->Name()); + } + case binder::ScopeType::LOCAL: { + return "LOCAL_SCOPE "; + } + case binder::ScopeType::CATCH: { + return "CATCH_SCOPE "; + } + default: { + return "MUST BE UNREACHABLE"; + } + } +} + +std::string ToStringHelper(const binder::Variable *var) +{ + if (var == nullptr) { + return ""; + } + + switch (var->Type()) { + case binder::VariableType::LOCAL: { + return "LOCAL_VAR " + ToStringHelper(var->Name()); + } + case binder::VariableType::MODULE: { + return "MODULE_VAR " + ToStringHelper(var->Name()); + } + case binder::VariableType::GLOBAL: { + return "GLOBAL_VAR " + ToStringHelper(var->Name()); + } + case binder::VariableType::ENUM: { + return "ENUM_VAR " + ToStringHelper(var->Name()); + } + default: { + return "MUST BE UNREACHABLE"; + } + } +} + +template +std::string ToStringParamsHelper(const ir::AstNode *parent, const ArenaVector ¶ms) +{ + std::string name; + if (parent != nullptr) { + name = ToStringHelper(parent) + " "; + } + + name += "("; + for (auto const *param : params) { + name += ToStringHelper(param); + } + + return name + ")"; +} + +std::string ToStringHelper(const ir::AstNode *ast) +{ + if (ast == nullptr) { + return ""; + } + + switch (ast->Type()) { + case ir::AstNodeType::IDENTIFIER: { + return "ID " + ToStringHelper(ast->AsIdentifier()->Name()); + } + case ir::AstNodeType::CLASS_DEFINITION: { + return "CLS_DEF " + ToStringHelper(ast->AsClassDefinition()->Ident()); + } + case ir::AstNodeType::CLASS_DECLARATION: { + return "CLS_DECL " + ToStringHelper(ast->AsClassDeclaration()->Definition()); + } + case ir::AstNodeType::BLOCK_STATEMENT: { + return "BLOCK " + ToStringHelper(ast->AsBlockStatement()->Scope()); + } + case ir::AstNodeType::SCRIPT_FUNCTION: { + auto const *sf = ast->AsScriptFunction(); + return "SCRIPT_FUN " + ToStringHelper(sf->Scope()) + "::" + ToStringHelper(sf->Id()); + } + case ir::AstNodeType::FUNCTION_EXPRESSION: { + return "FUN_EXPR " + ToStringHelper(ast->AsFunctionExpression()->Function()); + } + case ir::AstNodeType::METHOD_DEFINITION: { + return "METHOD_DEF " + ToStringHelper(ast->AsMethodDefinition()->Value()); + } + case ir::AstNodeType::ETS_TYPE_REFERENCE_PART: { + return "TYPE_REF_PART " + ToStringHelper(ast->AsETSTypeReferencePart()->Name()); + } + case ir::AstNodeType::ETS_TYPE_REFERENCE: { + return "TYPE_REF " + ToStringHelper(ast->AsETSTypeReference()->Part()); + } + case ir::AstNodeType::VARIABLE_DECLARATOR: { + return "VAR_DECLARATOR " + ToStringHelper(ast->AsVariableDeclarator()->Id()); + } + case ir::AstNodeType::VARIABLE_DECLARATION: { + if (ast->AsVariableDeclaration()->Declarators().empty()) { + return "VAR_DECLARATION "; + } + return "VAR_DECLARATION " + ToStringHelper(ast->AsVariableDeclaration()->Declarators().at(0)); + } + case ir::AstNodeType::CALL_EXPRESSION: { + return "CALL_EXPR " + ToStringHelper(ast->AsCallExpression()->Callee()) + "(...)"; + } + case ir::AstNodeType::EXPRESSION_STATEMENT: { + return "EXPR_STMT " + ToStringHelper(ast->AsExpressionStatement()->GetExpression()); + } + case ir::AstNodeType::MEMBER_EXPRESSION: { + auto const *me = ast->AsMemberExpression(); + return "MEMBER_EXPR " + ToStringHelper(me->Object()) + "." + ToStringHelper(me->Property()); + } + case ir::AstNodeType::CLASS_STATIC_BLOCK: { + return "CLS_STATIC_BLOCK " + ToStringHelper(ast->AsClassStaticBlock()->Function()); + } + case ir::AstNodeType::ETS_PACKAGE_DECLARATION: { + return "PKG_DECL "; + } + case ir::AstNodeType::TS_TYPE_PARAMETER_DECLARATION: { + return "PARAM_DECL " + ToStringParamsHelper( + ast->Parent(), ast->AsTSTypeParameterDeclaration()->Params()); + } + case ir::AstNodeType::TS_TYPE_PARAMETER: { + return "TYPE_PARAM " + ToStringHelper(ast->AsTSTypeParameter()->Name()); + } + case ir::AstNodeType::TS_TYPE_PARAMETER_INSTANTIATION: { + return "PARAM_INSTANTIATION " + + ToStringParamsHelper(ast->Parent(), ast->AsTSTypeParameterInstantiation()->Params()); + } + case ir::AstNodeType::THROW_STATEMENT: { + return "THROW_STMT " + ToStringHelper(ast->AsThrowStatement()->Argument()); + } + case ir::AstNodeType::ETS_NEW_CLASS_INSTANCE_EXPRESSION: { + return "NEW_CLS_INSTANCE " + ToStringHelper(ast->AsETSNewClassInstanceExpression()->GetTypeRef()); + } + case ir::AstNodeType::STRING_LITERAL: { + return "STR_LITERAL " + ToStringHelper(ast->AsStringLiteral()->Str()); + } + case ir::AstNodeType::TRY_STATEMENT: { + return "TRY_STMT " + ToStringHelper(ast->AsTryStatement()->Block()); + } + case ir::AstNodeType::CATCH_CLAUSE: { + return "CATCH_CLAUSE "; + } + case ir::AstNodeType::NUMBER_LITERAL: { + return "NUMBER_LITERAL " + ToStringHelper(ast->AsNumberLiteral()->Str()); + } + case ir::AstNodeType::ETS_PARAMETER_EXPRESSION: { + return "ETS_PARAM_EXPR " + ToStringHelper(ast->AsETSParameterExpression()->Ident()); + } + case ir::AstNodeType::TS_INTERFACE_DECLARATION: { + return "TS_INTERFACE_DECL " + ToStringHelper(ast->AsTSInterfaceDeclaration()->Id()); + } + case ir::AstNodeType::TS_INTERFACE_BODY: { + return "TS_INTERFACE_BODY "; + } + case ir::AstNodeType::ETS_FUNCTION_TYPE: { + return "ETS_FUNC_TYPE " + + ToStringParamsHelper(ast->Parent(), ast->AsETSFunctionType()->Params()); + } + case ir::AstNodeType::TS_CLASS_IMPLEMENTS: { + return "TS_CLASS_IMPL " + ToStringHelper(ast->AsTSClassImplements()->Expr()); + } + default: { + return "MUST BE UNREACHABLE"; + } + } +} + +bool ASTVerifier::HasParent(const ir::AstNode *ast) +{ + if (ast == nullptr) { + return false; + } + + if (ast->Parent() == nullptr) { + error_messages_.push_back("NULL_PARENT: " + ToStringHelper(ast)); + return false; + } + + return true; +} + +bool ASTVerifier::HaveParents(const ir::AstNode *ast) +{ + if (ast == nullptr) { + return false; + } + + bool has_parent = HasParent(ast); + ast->IterateRecursively([this, &has_parent](ir::AstNode *child) { has_parent &= HasParent(child); }); + return has_parent; +} + +bool ASTVerifier::HasType(const ir::AstNode *ast) +{ + if (ast == nullptr) { + return false; + } + + if (ast->IsTyped() && static_cast(ast)->TsType() == nullptr) { + error_messages_.push_back("NULL_TS_TYPE: " + ToStringHelper(ast)); + return false; + } + return true; +} + +bool ASTVerifier::HaveTypes(const ir::AstNode *ast) +{ + if (ast == nullptr) { + return false; + } + + bool has_type = HasType(ast); + ast->IterateRecursively([this, &has_type](ir::AstNode *child) { has_type &= HasType(child); }); + return has_type; +} + +bool ASTVerifier::HasVariable(const ir::AstNode *ast) +{ + if (ast == nullptr) { + return false; + } + + if (!ast->IsIdentifier() || ast->AsIdentifier()->Variable() != nullptr) { + return true; + } + + error_messages_.push_back("NULL_VARIABLE: " + ToStringHelper(ast->AsIdentifier())); + return false; +} + +bool ASTVerifier::HaveVariables(const ir::AstNode *ast) +{ + if (ast == nullptr) { + return false; + } + + bool has_variable = HasVariable(ast); + ast->IterateRecursively([this, &has_variable](ir::AstNode *child) { has_variable &= HasVariable(child); }); + return has_variable; +} + +bool ASTVerifier::HasScope(const ir::AstNode *ast) +{ + if (ast == nullptr) { + return false; + } + + if (!ast->IsIdentifier()) { + return true; // we will check only Identifier + } + // we will check only local variables of identifiers + if (HasVariable(ast) && ast->AsIdentifier()->Variable()->IsLocalVariable() && + ast->AsIdentifier()->Variable()->AsLocalVariable()->GetScope() == nullptr) { + error_messages_.push_back("NULL_SCOPE_LOCAL_VAR: " + ToStringHelper(ast)); + return false; + } + // TODO(tatiana): Add check that the scope enclose this identifier + return true; +} + +bool ASTVerifier::HaveScopes(const ir::AstNode *ast) +{ + if (ast == nullptr) { + return false; + } + + bool has_scope = HasScope(ast); + ast->IterateRecursively([this, &has_scope](ir::AstNode *child) { has_scope &= HasScope(child); }); + return has_scope; +} + +} // namespace panda::es2panda::compiler diff --git a/compiler/core/ASTVerifier.h b/compiler/core/ASTVerifier.h new file mode 100644 index 000000000..d9bdba118 --- /dev/null +++ b/compiler/core/ASTVerifier.h @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2021-2022 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. + */ + +#ifndef ES2PANDA_COMPILER_CORE_ASTVERIFIER_H +#define ES2PANDA_COMPILER_CORE_ASTVERIFIER_H + +#include "parser/program/program.h" + +namespace panda::es2panda::compiler { + +class ASTVerifier { +public: + using ErrorMessages = std::vector; + NO_COPY_SEMANTIC(ASTVerifier); + NO_MOVE_SEMANTIC(ASTVerifier); + + ASTVerifier() = default; + ~ASTVerifier() = default; + + bool IsCorrectProgram(const parser::Program *program); + bool HaveParents(const ir::AstNode *ast); + bool HasParent(const ir::AstNode *ast); + bool HaveTypes(const ir::AstNode *ast); + bool HasType(const ir::AstNode *ast); + bool HaveVariables(const ir::AstNode *ast); + bool HasVariable(const ir::AstNode *ast); + bool HasScope(const ir::AstNode *ast); + bool HaveScopes(const ir::AstNode *ast); + + ErrorMessages GetErrorMessages() + { + return error_messages_; + } + +private: + ErrorMessages error_messages_; +}; + +std::string ToStringHelper(const ir::AstNode *ast); + +} // namespace panda::es2panda::compiler + +#endif // ES2PANDA_COMPILER_CORE_ASTVERIFIER_H diff --git a/compiler/lowering/phase.cpp b/compiler/lowering/phase.cpp index 5877c6e49..0b7c30057 100644 --- a/compiler/lowering/phase.cpp +++ b/compiler/lowering/phase.cpp @@ -15,6 +15,7 @@ #include "phase.h" #include "checker/checker.h" +#include "compiler/core/ASTVerifier.h" #include "compiler/core/compilerContext.h" #include "lexer/token/sourceLocation.h" #include "compiler/lowering/checkerPhase.h" @@ -57,6 +58,10 @@ bool Phase::Apply(CompilerContext *ctx, parser::Program *program) } #ifndef NDEBUG + ASTVerifier ast_before; + if (!ast_before.IsCorrectProgram(program)) { + // TODO(tatiana): Add some error processing + } if (!Precondition(ctx, program)) { ctx->Checker()->ThrowTypeError({"Precondition check failed for ", Name()}, lexer::SourcePosition {}); } @@ -72,6 +77,10 @@ bool Phase::Apply(CompilerContext *ctx, parser::Program *program) } #ifndef NDEBUG + ASTVerifier ast_after; + if (!ast_after.IsCorrectProgram(program)) { + // TODO(tatiana): Add some error processing + } if (!Postcondition(ctx, program)) { ctx->Checker()->ThrowTypeError({"Postcondition check failed for ", Name()}, lexer::SourcePosition {}); } diff --git a/ir/astNode.h b/ir/astNode.h index b9558663a..5accd1e72 100644 --- a/ir/astNode.h +++ b/ir/astNode.h @@ -227,6 +227,11 @@ public: return false; } + virtual bool IsTyped() const + { + return false; + } + // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define DECLARE_AS_CASTS(nodeType, className) \ className *As##className() \ @@ -587,6 +592,11 @@ public: ts_type_ = ts_type; } + bool IsTyped() const override + { + return true; + } + protected: explicit Typed(AstNodeType const type) : T(type) {} explicit Typed(AstNodeType const type, ModifierFlags const flags) : T(type, flags) {} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f40aed24b..ff14df7c4 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -92,5 +92,17 @@ if(PANDA_WITH_ETS) add_dependencies(ets_tests es2panda_tests) endif() + panda_add_gtest( + NAME es2panda_astverifier_tests + SOURCES + public/ast_verifier_test.cpp + LIBRARIES + es2panda-lib + INCLUDE_DIRS + ${ES2PANDA_PATH} + SANITIZERS + ${PANDA_SANITIZERS_LIST} + ) + add_subdirectory(tsconfig) endif() diff --git a/test/public/ast_verifier_test.cpp b/test/public/ast_verifier_test.cpp new file mode 100644 index 000000000..dd36a1937 --- /dev/null +++ b/test/public/ast_verifier_test.cpp @@ -0,0 +1,71 @@ +/** + * 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. + */ + +#include +#include +#include "macros.h" + +#include "compiler/core/ASTVerifier.h" +#include "ir/astDump.h" +#include "ir/expressions/literals/stringLiteral.h" + +class ASTVerifierTest : public testing::Test { +public: + ASTVerifierTest() = default; + ~ASTVerifierTest() override = default; + + NO_COPY_SEMANTIC(ASTVerifierTest); + NO_MOVE_SEMANTIC(ASTVerifierTest); + +private: +}; + +TEST_F(ASTVerifierTest, NullParent) +{ + panda::es2panda::compiler::ASTVerifier verifier {}; + panda::es2panda::ir::StringLiteral empty_node; + + bool has_parent = verifier.HasParent(&empty_node); + auto messages = verifier.GetErrorMessages(); + + ASSERT_EQ(has_parent, false); + ASSERT_NE(messages.size(), 0); + ASSERT_EQ(messages[0], "NULL_PARENT: STR_LITERAL "); +} + +TEST_F(ASTVerifierTest, NullType) +{ + panda::es2panda::compiler::ASTVerifier verifier {}; + panda::es2panda::ir::StringLiteral empty_node; + + bool has_type = verifier.HasType(&empty_node); + auto messages = verifier.GetErrorMessages(); + + ASSERT_EQ(has_type, false); + ASSERT_NE(messages.size(), 0); + ASSERT_EQ(messages[0], "NULL_TS_TYPE: STR_LITERAL "); +} + +TEST_F(ASTVerifierTest, WithoutScope) +{ + panda::es2panda::compiler::ASTVerifier verifier {}; + panda::es2panda::ir::StringLiteral empty_node; + + bool has_scope = verifier.HasScope(&empty_node); + auto messages = verifier.GetErrorMessages(); + + ASSERT_EQ(has_scope, true); + ASSERT_EQ(messages.size(), 0); +} -- Gitee From 3bbd75fe73c352d5a5ee373b596440cd1d16af54 Mon Sep 17 00:00:00 2001 From: Csaba Hurton Date: Fri, 13 Oct 2023 16:02:57 +0200 Subject: [PATCH 2/3] Move Compile and Check Logic from ASTNode classes Round #4 Linked Internal Issue 13840 Signed-off-by: Csaba Hurton --- checker/ETSAnalyzer.cpp | 112 +++++++++++++--- checker/SemanticAnalyzer.h | 146 +++++++++++++++++++++ checker/TSAnalyzer.cpp | 56 +++++--- compiler/core/ASTCompiler.h | 146 +++++++++++++++++++++ compiler/core/ETSCompiler.cpp | 51 ++++--- compiler/core/JSCompiler.cpp | 34 ++--- ir/ets/etsParameterExpression.cpp | 37 ++---- ir/ets/etsParameterExpression.h | 7 + ir/ets/etsPrimitiveType.cpp | 20 +-- ir/ets/etsPrimitiveType.h | 8 +- ir/ets/etsStructDeclaration.cpp | 16 +-- ir/ets/etsStructDeclaration.h | 8 +- ir/ets/etsTypeReference.cpp | 21 +-- ir/ets/etsTypeReference.h | 8 +- ir/ets/etsTypeReferencePart.cpp | 22 ++-- ir/ets/etsTypeReferencePart.h | 8 +- ir/ets/etsWildcardType.cpp | 24 ++-- ir/ets/etsWildcardType.h | 8 +- ir/expressions/arrowFunctionExpression.cpp | 111 +--------------- ir/expressions/arrowFunctionExpression.h | 12 +- ir/statements/tryStatement.h | 2 +- 21 files changed, 576 insertions(+), 281 deletions(-) diff --git a/checker/ETSAnalyzer.cpp b/checker/ETSAnalyzer.cpp index 2e05e528f..33a317b03 100644 --- a/checker/ETSAnalyzer.cpp +++ b/checker/ETSAnalyzer.cpp @@ -16,6 +16,8 @@ #include "binder/binder.h" #include "binder/ETSBinder.h" +#include "checker/ETSchecker.h" +#include "checker/ets/castingContext.h" #include "checker/ets/typeRelationContext.h" #include "ir/base/catchClause.h" #include "ir/base/classProperty.h" @@ -233,37 +235,55 @@ checker::Type *ETSAnalyzer::Check(ir::ETSPackageDeclaration *st) const checker::Type *ETSAnalyzer::Check(ir::ETSParameterExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + if (expr->TsType() == nullptr) { + checker::Type *param_type; + + if (expr->Ident()->TsType() != nullptr) { + param_type = expr->Ident()->TsType(); + } else { + param_type = !expr->IsRestParameter() ? expr->Ident()->Check(checker) : expr->spread_->Check(checker); + if (expr->IsDefault()) { + [[maybe_unused]] auto *const init_type = expr->Initializer()->Check(checker); + // TODO(ttamas) : fix this aftet nullable fix + // const checker::AssignmentContext ctx(checker->Relation(), initializer_, init_type, name_type, + // initializer_->Start(), + // {"Initializers type is not assignable to the target type"}); + } + } + + expr->SetTsType(param_type); + } + + return expr->TsType(); } -checker::Type *ETSAnalyzer::Check(ir::ETSPrimitiveType *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSPrimitiveType *node) const { - (void)node; - UNREACHABLE(); + return nullptr; } checker::Type *ETSAnalyzer::Check(ir::ETSStructDeclaration *node) const { - (void)node; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + node->Definition()->Check(checker); + return nullptr; } checker::Type *ETSAnalyzer::Check(ir::ETSTypeReference *node) const { - (void)node; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + return node->GetType(checker); } checker::Type *ETSAnalyzer::Check(ir::ETSTypeReferencePart *node) const { - (void)node; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + return node->GetType(checker); } -checker::Type *ETSAnalyzer::Check(ir::ETSWildcardType *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSWildcardType *node) const { - (void)node; UNREACHABLE(); } // compile methods for EXPRESSIONS in alphabetical order @@ -275,8 +295,70 @@ checker::Type *ETSAnalyzer::Check(ir::ArrayExpression *expr) const checker::Type *ETSAnalyzer::Check(ir::ArrowFunctionExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + if (expr->TsType() != nullptr) { + return expr->TsType(); + } + + auto *func_type = checker->BuildFunctionSignature(expr->Function(), false); + + if (expr->Function()->IsAsyncFunc()) { + auto *ret_type = static_cast(expr->Function()->Signature()->ReturnType()); + if (ret_type->AssemblerName() != checker->GlobalBuiltinPromiseType()->AssemblerName()) { + checker->ThrowTypeError("Return type of async lambda must be 'Promise'", expr->Function()->Start()); + } + } + + checker::ScopeContext scope_ctx(checker, expr->Function()->Scope()); + + if (checker->HasStatus(checker::CheckerStatus::IN_INSTANCE_EXTENSION_METHOD)) { + /* + example code: + ``` + class A { + prop:number + } + function A.method() { + let a = () => { + console.println(this.prop) + } + } + ``` + here the enclosing class of arrow function should be Class A + */ + checker->Context().SetContainingClass( + checker->Scope()->Find(binder::Binder::MANDATORY_PARAM_THIS).variable->TsType()->AsETSObjectType()); + } + + checker::SavedCheckerContext saved_context(checker, checker->Context().Status(), + checker->Context().ContainingClass()); + checker->AddStatus(checker::CheckerStatus::IN_LAMBDA); + checker->Context().SetContainingSignature(func_type->CallSignatures()[0]); + + auto *body_type = expr->Function()->Body()->Check(checker); + + if (expr->Function()->Body()->IsExpression()) { + if (expr->Function()->ReturnTypeAnnotation() == nullptr) { + func_type->CallSignatures()[0]->SetReturnType(body_type); + } + + checker::AssignmentContext( + checker->Relation(), expr->Function()->Body()->AsExpression(), body_type, + func_type->CallSignatures()[0]->ReturnType(), expr->Function()->Start(), + {"Return statements return type is not compatible with the containing functions return type"}, + checker::TypeRelationFlag::DIRECT_RETURN); + } + + checker->Context().SetContainingSignature(nullptr); + checker->CheckCapturedVariables(); + + for (auto [var, _] : checker->Context().CapturedVars()) { + (void)_; + expr->CapturedVars().push_back(var); + } + + expr->SetTsType(func_type); + return expr->TsType(); } checker::Type *ETSAnalyzer::Check(ir::AssignmentExpression *expr) const diff --git a/checker/SemanticAnalyzer.h b/checker/SemanticAnalyzer.h index 72cfe3735..8cc27451f 100644 --- a/checker/SemanticAnalyzer.h +++ b/checker/SemanticAnalyzer.h @@ -17,6 +17,152 @@ #define ES2PANDA_CHECKER_SEMANTICANALYZER_H #include "compiler/core/dynamicContext.h" +#include "ir/opaqueTypeNode.h" +#include "ir/as/namedType.h" +#include "ir/as/prefixAssertionExpression.h" +#include "ir/base/catchClause.h" +#include "ir/base/classDefinition.h" +#include "ir/base/classProperty.h" +#include "ir/base/classStaticBlock.h" +#include "ir/base/decorator.h" +#include "ir/base/metaProperty.h" +#include "ir/base/methodDefinition.h" +#include "ir/base/property.h" +#include "ir/base/scriptFunction.h" +#include "ir/base/spreadElement.h" +#include "ir/base/templateElement.h" +#include "ir/base/tsIndexSignature.h" +#include "ir/base/tsMethodSignature.h" +#include "ir/base/tsPropertySignature.h" +#include "ir/base/tsSignatureDeclaration.h" +#include "ir/ets/etsClassLiteral.h" +#include "ir/ets/etsFunctionType.h" +#include "ir/ets/etsImportDeclaration.h" +#include "ir/ets/etsLaunchExpression.h" +#include "ir/ets/etsNewArrayInstanceExpression.h" +#include "ir/ets/etsNewClassInstanceExpression.h" +#include "ir/ets/etsNewMultiDimArrayInstanceExpression.h" +#include "ir/ets/etsPackageDeclaration.h" +#include "ir/ets/etsParameterExpression.h" +#include "ir/ets/etsPrimitiveType.h" +#include "ir/ets/etsScript.h" +#include "ir/ets/etsStructDeclaration.h" +#include "ir/ets/etsTypeReference.h" +#include "ir/ets/etsTypeReferencePart.h" +#include "ir/ets/etsWildcardType.h" +#include "ir/expressions/arrayExpression.h" +#include "ir/expressions/arrowFunctionExpression.h" +#include "ir/expressions/assignmentExpression.h" +#include "ir/expressions/awaitExpression.h" +#include "ir/expressions/binaryExpression.h" +#include "ir/expressions/callExpression.h" +#include "ir/expressions/chainExpression.h" +#include "ir/expressions/classExpression.h" +#include "ir/expressions/conditionalExpression.h" +#include "ir/expressions/directEvalExpression.h" +#include "ir/expressions/functionExpression.h" +#include "ir/expressions/identifier.h" +#include "ir/expressions/importExpression.h" +#include "ir/expressions/memberExpression.h" +#include "ir/expressions/newExpression.h" +#include "ir/expressions/objectExpression.h" +#include "ir/expressions/omittedExpression.h" +#include "ir/expressions/sequenceExpression.h" +#include "ir/expressions/superExpression.h" +#include "ir/expressions/taggedTemplateExpression.h" +#include "ir/expressions/templateLiteral.h" +#include "ir/expressions/thisExpression.h" +#include "ir/expressions/unaryExpression.h" +#include "ir/expressions/updateExpression.h" +#include "ir/expressions/yieldExpression.h" +#include "ir/expressions/literals/bigIntLiteral.h" +#include "ir/expressions/literals/booleanLiteral.h" +#include "ir/expressions/literals/charLiteral.h" +#include "ir/expressions/literals/nullLiteral.h" +#include "ir/expressions/literals/numberLiteral.h" +#include "ir/expressions/literals/regExpLiteral.h" +#include "ir/expressions/literals/stringLiteral.h" +#include "ir/module/exportAllDeclaration.h" +#include "ir/module/exportDefaultDeclaration.h" +#include "ir/module/exportNamedDeclaration.h" +#include "ir/module/exportSpecifier.h" +#include "ir/module/importDeclaration.h" +#include "ir/module/importDefaultSpecifier.h" +#include "ir/module/importNamespaceSpecifier.h" +#include "ir/module/importSpecifier.h" +#include "ir/statements/assertStatement.h" +#include "ir/statements/blockStatement.h" +#include "ir/statements/breakStatement.h" +#include "ir/statements/classDeclaration.h" +#include "ir/statements/continueStatement.h" +#include "ir/statements/debuggerStatement.h" +#include "ir/statements/doWhileStatement.h" +#include "ir/statements/emptyStatement.h" +#include "ir/statements/expressionStatement.h" +#include "ir/statements/forInStatement.h" +#include "ir/statements/forOfStatement.h" +#include "ir/statements/forUpdateStatement.h" +#include "ir/statements/functionDeclaration.h" +#include "ir/statements/ifStatement.h" +#include "ir/statements/labelledStatement.h" +#include "ir/statements/returnStatement.h" +#include "ir/statements/switchCaseStatement.h" +#include "ir/statements/switchStatement.h" +#include "ir/statements/throwStatement.h" +#include "ir/statements/tryStatement.h" +#include "ir/statements/variableDeclaration.h" +#include "ir/statements/variableDeclarator.h" +#include "ir/statements/whileStatement.h" +#include "ir/ts/tsAnyKeyword.h" +#include "ir/ts/tsArrayType.h" +#include "ir/ts/tsAsExpression.h" +#include "ir/ts/tsBigintKeyword.h" +#include "ir/ts/tsBooleanKeyword.h" +#include "ir/ts/tsClassImplements.h" +#include "ir/ts/tsConditionalType.h" +#include "ir/ts/tsConstructorType.h" +#include "ir/ts/tsEnumDeclaration.h" +#include "ir/ts/tsEnumMember.h" +#include "ir/ts/tsExternalModuleReference.h" +#include "ir/ts/tsFunctionType.h" +#include "ir/ts/tsImportEqualsDeclaration.h" +#include "ir/ts/tsImportType.h" +#include "ir/ts/tsIndexedAccessType.h" +#include "ir/ts/tsInferType.h" +#include "ir/ts/tsInterfaceBody.h" +#include "ir/ts/tsInterfaceDeclaration.h" +#include "ir/ts/tsInterfaceHeritage.h" +#include "ir/ts/tsIntersectionType.h" +#include "ir/ts/tsLiteralType.h" +#include "ir/ts/tsMappedType.h" +#include "ir/ts/tsModuleBlock.h" +#include "ir/ts/tsModuleDeclaration.h" +#include "ir/ts/tsNamedTupleMember.h" +#include "ir/ts/tsNeverKeyword.h" +#include "ir/ts/tsNonNullExpression.h" +#include "ir/ts/tsNullKeyword.h" +#include "ir/ts/tsNumberKeyword.h" +#include "ir/ts/tsObjectKeyword.h" +#include "ir/ts/tsParameterProperty.h" +#include "ir/ts/tsParenthesizedType.h" +#include "ir/ts/tsQualifiedName.h" +#include "ir/ts/tsStringKeyword.h" +#include "ir/ts/tsThisType.h" +#include "ir/ts/tsTupleType.h" +#include "ir/ts/tsTypeAliasDeclaration.h" +#include "ir/ts/tsTypeAssertion.h" +#include "ir/ts/tsTypeLiteral.h" +#include "ir/ts/tsTypeOperator.h" +#include "ir/ts/tsTypeParameterDeclaration.h" +#include "ir/ts/tsTypeParameter.h" +#include "ir/ts/tsTypeParameterInstantiation.h" +#include "ir/ts/tsTypePredicate.h" +#include "ir/ts/tsTypeQuery.h" +#include "ir/ts/tsTypeReference.h" +#include "ir/ts/tsUndefinedKeyword.h" +#include "ir/ts/tsUnionType.h" +#include "ir/ts/tsUnknownKeyword.h" +#include "ir/ts/tsVoidKeyword.h" namespace panda::es2panda::checker { class Checker; diff --git a/checker/TSAnalyzer.cpp b/checker/TSAnalyzer.cpp index f5bfa79b2..62f2f79a9 100644 --- a/checker/TSAnalyzer.cpp +++ b/checker/TSAnalyzer.cpp @@ -16,12 +16,7 @@ #include "TSAnalyzer.h" #include "checker/TSchecker.h" -#include "ir/base/catchClause.h" -#include "ir/base/methodDefinition.h" -#include "ir/base/scriptFunction.h" -#include "ir/statements/blockStatement.h" -#include "ir/statements/returnStatement.h" -#include "ir/typeNode.h" +#include "checker/ts/destructuringContext.h" #include "util/helpers.h" namespace panda::es2panda::checker { @@ -191,39 +186,33 @@ checker::Type *TSAnalyzer::Check(ir::ETSPackageDeclaration *st) const UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ETSParameterExpression *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSParameterExpression *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ETSPrimitiveType *node) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSPrimitiveType *node) const { - (void)node; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ETSStructDeclaration *node) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSStructDeclaration *node) const { - (void)node; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ETSTypeReference *node) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSTypeReference *node) const { - (void)node; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ETSTypeReferencePart *node) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSTypeReferencePart *node) const { - (void)node; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ETSWildcardType *node) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSWildcardType *node) const { - (void)node; UNREACHABLE(); } // compile methods for EXPRESSIONS in alphabetical order @@ -235,8 +224,35 @@ checker::Type *TSAnalyzer::Check(ir::ArrayExpression *expr) const checker::Type *TSAnalyzer::Check(ir::ArrowFunctionExpression *expr) const { - (void)expr; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + binder::Variable *func_var = nullptr; + + if (expr->Function()->Parent()->Parent() != nullptr && + expr->Function()->Parent()->Parent()->IsVariableDeclarator() && + expr->Function()->Parent()->Parent()->AsVariableDeclarator()->Id()->IsIdentifier()) { + func_var = expr->Function()->Parent()->Parent()->AsVariableDeclarator()->Id()->AsIdentifier()->Variable(); + } + + checker::ScopeContext scope_ctx(checker, expr->Function()->Scope()); + + auto *signature_info = checker->Allocator()->New(checker->Allocator()); + checker->CheckFunctionParameterDeclarations(expr->Function()->Params(), signature_info); + + auto *signature = checker->Allocator()->New( + signature_info, checker->GlobalResolvingReturnType(), expr->Function()); + checker::Type *func_type = checker->CreateFunctionTypeWithSignature(signature); + + if (func_var != nullptr && func_var->TsType() == nullptr) { + func_var->SetTsType(func_type); + } + + signature->SetReturnType(checker->HandleFunctionReturn(expr->Function())); + + if (!expr->Function()->Body()->IsExpression()) { + expr->Function()->Body()->Check(checker); + } + + return func_type; } checker::Type *TSAnalyzer::Check(ir::AssignmentExpression *expr) const diff --git a/compiler/core/ASTCompiler.h b/compiler/core/ASTCompiler.h index b5bd66617..03fdde033 100644 --- a/compiler/core/ASTCompiler.h +++ b/compiler/core/ASTCompiler.h @@ -17,6 +17,152 @@ #define ES2PANDA_COMPILER_CORE_ASTCOMPILER_H #include "compiler/core/dynamicContext.h" +#include "ir/opaqueTypeNode.h" +#include "ir/as/namedType.h" +#include "ir/as/prefixAssertionExpression.h" +#include "ir/base/catchClause.h" +#include "ir/base/classDefinition.h" +#include "ir/base/classProperty.h" +#include "ir/base/classStaticBlock.h" +#include "ir/base/decorator.h" +#include "ir/base/metaProperty.h" +#include "ir/base/methodDefinition.h" +#include "ir/base/property.h" +#include "ir/base/scriptFunction.h" +#include "ir/base/spreadElement.h" +#include "ir/base/templateElement.h" +#include "ir/base/tsIndexSignature.h" +#include "ir/base/tsMethodSignature.h" +#include "ir/base/tsPropertySignature.h" +#include "ir/base/tsSignatureDeclaration.h" +#include "ir/ets/etsClassLiteral.h" +#include "ir/ets/etsFunctionType.h" +#include "ir/ets/etsImportDeclaration.h" +#include "ir/ets/etsLaunchExpression.h" +#include "ir/ets/etsNewArrayInstanceExpression.h" +#include "ir/ets/etsNewClassInstanceExpression.h" +#include "ir/ets/etsNewMultiDimArrayInstanceExpression.h" +#include "ir/ets/etsPackageDeclaration.h" +#include "ir/ets/etsParameterExpression.h" +#include "ir/ets/etsPrimitiveType.h" +#include "ir/ets/etsScript.h" +#include "ir/ets/etsStructDeclaration.h" +#include "ir/ets/etsTypeReference.h" +#include "ir/ets/etsTypeReferencePart.h" +#include "ir/ets/etsWildcardType.h" +#include "ir/expressions/arrayExpression.h" +#include "ir/expressions/arrowFunctionExpression.h" +#include "ir/expressions/assignmentExpression.h" +#include "ir/expressions/awaitExpression.h" +#include "ir/expressions/binaryExpression.h" +#include "ir/expressions/callExpression.h" +#include "ir/expressions/chainExpression.h" +#include "ir/expressions/classExpression.h" +#include "ir/expressions/conditionalExpression.h" +#include "ir/expressions/directEvalExpression.h" +#include "ir/expressions/functionExpression.h" +#include "ir/expressions/identifier.h" +#include "ir/expressions/importExpression.h" +#include "ir/expressions/memberExpression.h" +#include "ir/expressions/newExpression.h" +#include "ir/expressions/objectExpression.h" +#include "ir/expressions/omittedExpression.h" +#include "ir/expressions/sequenceExpression.h" +#include "ir/expressions/superExpression.h" +#include "ir/expressions/taggedTemplateExpression.h" +#include "ir/expressions/templateLiteral.h" +#include "ir/expressions/thisExpression.h" +#include "ir/expressions/unaryExpression.h" +#include "ir/expressions/updateExpression.h" +#include "ir/expressions/yieldExpression.h" +#include "ir/expressions/literals/bigIntLiteral.h" +#include "ir/expressions/literals/booleanLiteral.h" +#include "ir/expressions/literals/charLiteral.h" +#include "ir/expressions/literals/nullLiteral.h" +#include "ir/expressions/literals/numberLiteral.h" +#include "ir/expressions/literals/regExpLiteral.h" +#include "ir/expressions/literals/stringLiteral.h" +#include "ir/module/exportAllDeclaration.h" +#include "ir/module/exportDefaultDeclaration.h" +#include "ir/module/exportNamedDeclaration.h" +#include "ir/module/exportSpecifier.h" +#include "ir/module/importDeclaration.h" +#include "ir/module/importDefaultSpecifier.h" +#include "ir/module/importNamespaceSpecifier.h" +#include "ir/module/importSpecifier.h" +#include "ir/statements/assertStatement.h" +#include "ir/statements/blockStatement.h" +#include "ir/statements/breakStatement.h" +#include "ir/statements/classDeclaration.h" +#include "ir/statements/continueStatement.h" +#include "ir/statements/debuggerStatement.h" +#include "ir/statements/doWhileStatement.h" +#include "ir/statements/emptyStatement.h" +#include "ir/statements/expressionStatement.h" +#include "ir/statements/forInStatement.h" +#include "ir/statements/forOfStatement.h" +#include "ir/statements/forUpdateStatement.h" +#include "ir/statements/functionDeclaration.h" +#include "ir/statements/ifStatement.h" +#include "ir/statements/labelledStatement.h" +#include "ir/statements/returnStatement.h" +#include "ir/statements/switchCaseStatement.h" +#include "ir/statements/switchStatement.h" +#include "ir/statements/throwStatement.h" +#include "ir/statements/tryStatement.h" +#include "ir/statements/variableDeclaration.h" +#include "ir/statements/variableDeclarator.h" +#include "ir/statements/whileStatement.h" +#include "ir/ts/tsAnyKeyword.h" +#include "ir/ts/tsArrayType.h" +#include "ir/ts/tsAsExpression.h" +#include "ir/ts/tsBigintKeyword.h" +#include "ir/ts/tsBooleanKeyword.h" +#include "ir/ts/tsClassImplements.h" +#include "ir/ts/tsConditionalType.h" +#include "ir/ts/tsConstructorType.h" +#include "ir/ts/tsEnumDeclaration.h" +#include "ir/ts/tsEnumMember.h" +#include "ir/ts/tsExternalModuleReference.h" +#include "ir/ts/tsFunctionType.h" +#include "ir/ts/tsImportEqualsDeclaration.h" +#include "ir/ts/tsImportType.h" +#include "ir/ts/tsIndexedAccessType.h" +#include "ir/ts/tsInferType.h" +#include "ir/ts/tsInterfaceBody.h" +#include "ir/ts/tsInterfaceDeclaration.h" +#include "ir/ts/tsInterfaceHeritage.h" +#include "ir/ts/tsIntersectionType.h" +#include "ir/ts/tsLiteralType.h" +#include "ir/ts/tsMappedType.h" +#include "ir/ts/tsModuleBlock.h" +#include "ir/ts/tsModuleDeclaration.h" +#include "ir/ts/tsNamedTupleMember.h" +#include "ir/ts/tsNeverKeyword.h" +#include "ir/ts/tsNonNullExpression.h" +#include "ir/ts/tsNullKeyword.h" +#include "ir/ts/tsNumberKeyword.h" +#include "ir/ts/tsObjectKeyword.h" +#include "ir/ts/tsParameterProperty.h" +#include "ir/ts/tsParenthesizedType.h" +#include "ir/ts/tsQualifiedName.h" +#include "ir/ts/tsStringKeyword.h" +#include "ir/ts/tsThisType.h" +#include "ir/ts/tsTupleType.h" +#include "ir/ts/tsTypeAliasDeclaration.h" +#include "ir/ts/tsTypeAssertion.h" +#include "ir/ts/tsTypeLiteral.h" +#include "ir/ts/tsTypeOperator.h" +#include "ir/ts/tsTypeParameterDeclaration.h" +#include "ir/ts/tsTypeParameter.h" +#include "ir/ts/tsTypeParameterInstantiation.h" +#include "ir/ts/tsTypePredicate.h" +#include "ir/ts/tsTypeQuery.h" +#include "ir/ts/tsTypeReference.h" +#include "ir/ts/tsUndefinedKeyword.h" +#include "ir/ts/tsUnionType.h" +#include "ir/ts/tsUnknownKeyword.h" +#include "ir/ts/tsVoidKeyword.h" namespace panda::es2panda::compiler { class CodeGen; diff --git a/compiler/core/ETSCompiler.cpp b/compiler/core/ETSCompiler.cpp index c7f91c0d7..ffff9fe9d 100644 --- a/compiler/core/ETSCompiler.cpp +++ b/compiler/core/ETSCompiler.cpp @@ -15,13 +15,11 @@ #include "ETSCompiler.h" +#include "checker/types/ets/etsDynamicFunctionType.h" +#include "compiler/base/condition.h" #include "compiler/base/lreference.h" #include "compiler/core/ETSGen.h" -#include "ir/base/catchClause.h" -#include "ir/base/classProperty.h" -#include "ir/expressions/identifier.h" -#include "ir/statements/blockStatement.h" -#include "ir/statements/returnStatement.h" +#include "compiler/function/functionBuilder.h" namespace panda::es2panda::compiler { @@ -198,38 +196,36 @@ void ETSCompiler::Compile(const ir::ETSPackageDeclaration *st) const void ETSCompiler::Compile(const ir::ETSParameterExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + expr->Ident()->Identifier::Compile(etsg); } -void ETSCompiler::Compile(const ir::ETSPrimitiveType *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::ETSPrimitiveType *node) const { - (void)node; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::ETSStructDeclaration *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::ETSStructDeclaration *node) const { - (void)node; UNREACHABLE(); } void ETSCompiler::Compile(const ir::ETSTypeReference *node) const { - (void)node; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + node->Part()->Compile(etsg); } void ETSCompiler::Compile(const ir::ETSTypeReferencePart *node) const { - (void)node; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + node->Name()->Compile(etsg); } -void ETSCompiler::Compile(const ir::ETSWildcardType *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::ETSWildcardType *node) const { - (void)node; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + etsg->Unimplemented(); } // compile methods for EXPRESSIONS in alphabetical order void ETSCompiler::Compile(const ir::ArrayExpression *expr) const @@ -240,8 +236,23 @@ void ETSCompiler::Compile(const ir::ArrayExpression *expr) const void ETSCompiler::Compile(const ir::ArrowFunctionExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + ASSERT(expr->ResolvedLambda() != nullptr); + auto *ctor = expr->ResolvedLambda()->TsType()->AsETSObjectType()->ConstructSignatures()[0]; + std::vector arguments; + + for (auto *it : expr->CapturedVars()) { + if (it->HasFlag(binder::VariableFlags::LOCAL)) { + arguments.push_back(it->AsLocalVariable()->Vreg()); + } + } + + if (expr->propagate_this_) { + arguments.push_back(etsg->GetThisReg()); + } + + etsg->InitLambdaObject(expr, ctor, arguments); + etsg->SetAccumulatorType(expr->resolved_lambda_->TsType()); } void ETSCompiler::Compile(const ir::AssignmentExpression *expr) const diff --git a/compiler/core/JSCompiler.cpp b/compiler/core/JSCompiler.cpp index a0b481589..5be37688d 100644 --- a/compiler/core/JSCompiler.cpp +++ b/compiler/core/JSCompiler.cpp @@ -15,18 +15,10 @@ #include "JSCompiler.h" +#include "compiler/base/condition.h" #include "compiler/base/lreference.h" #include "compiler/core/pandagen.h" -#include "ir/base/catchClause.h" -#include "ir/base/classDefinition.h" -#include "ir/base/classProperty.h" -#include "ir/base/classStaticBlock.h" -#include "ir/base/methodDefinition.h" -#include "ir/base/scriptFunction.h" -#include "ir/expressions/functionExpression.h" -#include "ir/expressions/identifier.h" -#include "ir/statements/blockStatement.h" -#include "ir/statements/returnStatement.h" +#include "compiler/function/functionBuilder.h" #include "util/helpers.h" namespace panda::es2panda::compiler { @@ -523,39 +515,33 @@ void JSCompiler::Compile(const ir::ETSPackageDeclaration *expr) const UNREACHABLE(); } -void JSCompiler::Compile(const ir::ETSParameterExpression *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::ETSParameterExpression *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::ETSPrimitiveType *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::ETSPrimitiveType *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::ETSStructDeclaration *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::ETSStructDeclaration *node) const { - (void)node; UNREACHABLE(); } -void JSCompiler::Compile(const ir::ETSTypeReference *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::ETSTypeReference *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::ETSTypeReferencePart *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::ETSTypeReferencePart *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::ETSWildcardType *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::ETSWildcardType *expr) const { - (void)expr; UNREACHABLE(); } @@ -568,8 +554,8 @@ void JSCompiler::Compile(const ir::ArrayExpression *expr) const void JSCompiler::Compile(const ir::ArrowFunctionExpression *expr) const { - (void)expr; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + pg->DefineFunction(expr->Function(), expr->Function(), expr->Function()->Scope()->InternalName()); } void JSCompiler::Compile(const ir::AssignmentExpression *expr) const diff --git a/ir/ets/etsParameterExpression.cpp b/ir/ets/etsParameterExpression.cpp index c862ffe69..30fee78aa 100644 --- a/ir/ets/etsParameterExpression.cpp +++ b/ir/ets/etsParameterExpression.cpp @@ -15,9 +15,11 @@ #include "etsParameterExpression.h" -#include "compiler/core/pandagen.h" #include "checker/ETSchecker.h" #include "checker/ets/typeRelationContext.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "ir/typeNode.h" #include "ir/expressions/identifier.h" @@ -140,43 +142,24 @@ void ETSParameterExpression::Dump(ir::AstDumper *const dumper) const } } -void ETSParameterExpression::Compile([[maybe_unused]] compiler::PandaGen *const pg) const +void ETSParameterExpression::Compile(compiler::PandaGen *const pg) const { - UNREACHABLE(); + pg->GetAstCompiler()->Compile(this); } -void ETSParameterExpression::Compile([[maybe_unused]] compiler::ETSGen *const etsg) const +void ETSParameterExpression::Compile(compiler::ETSGen *const etsg) const { - ident_->Identifier::Compile(etsg); + etsg->GetAstCompiler()->Compile(this); } -checker::Type *ETSParameterExpression::Check([[maybe_unused]] checker::TSChecker *const checker) +checker::Type *ETSParameterExpression::Check(checker::TSChecker *const checker) { - UNREACHABLE(); + return checker->GetAnalyzer()->Check(this); } checker::Type *ETSParameterExpression::Check(checker::ETSChecker *const checker) { - if (TsType() == nullptr) { - checker::Type *param_type; - - if (ident_->TsType() != nullptr) { - param_type = ident_->TsType(); - } else { - param_type = !IsRestParameter() ? ident_->Check(checker) : spread_->Check(checker); - if (IsDefault()) { - [[maybe_unused]] auto *const init_type = initializer_->Check(checker); - // TODO(ttamas) : fix this aftet nullable fix - // const checker::AssignmentContext ctx(checker->Relation(), initializer_, init_type, name_type, - // initializer_->Start(), - // {"Initializers type is not assignable to the target type"}); - } - } - - SetTsType(param_type); - } - - return TsType(); + return checker->GetAnalyzer()->Check(this); } // NOLINTNEXTLINE(google-default-arguments) diff --git a/ir/ets/etsParameterExpression.h b/ir/ets/etsParameterExpression.h index d63a3dd88..1160289e8 100644 --- a/ir/ets/etsParameterExpression.h +++ b/ir/ets/etsParameterExpression.h @@ -18,6 +18,10 @@ #include "ir/expression.h" +namespace panda::es2panda::checker { +class ETSAnalyzer; +} // namespace panda::es2panda::checker + namespace panda::es2panda::ir { class ETSParameterExpression final : public Expression { public: @@ -29,6 +33,9 @@ public: explicit ETSParameterExpression(AnnotatedExpression *ident_or_spread, Expression *initializer); + // TODO (csabahurton): friend relationship can be removed once there are getters for private fields + friend class checker::ETSAnalyzer; + [[nodiscard]] const Identifier *Ident() const noexcept; [[nodiscard]] Identifier *Ident() noexcept; diff --git a/ir/ets/etsPrimitiveType.cpp b/ir/ets/etsPrimitiveType.cpp index 820b6fb54..7e722d78c 100644 --- a/ir/ets/etsPrimitiveType.cpp +++ b/ir/ets/etsPrimitiveType.cpp @@ -15,10 +15,11 @@ #include "etsPrimitiveType.h" -#include "ir/astDump.h" #include "checker/TSchecker.h" #include "checker/ETSchecker.h" #include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" +#include "ir/astDump.h" namespace panda::es2panda::ir { void ETSPrimitiveType::TransformChildren([[maybe_unused]] const NodeTransformer &cb) {} @@ -29,16 +30,19 @@ void ETSPrimitiveType::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "ETSPrimitiveType"}}); } -void ETSPrimitiveType::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void ETSPrimitiveType::Compile(compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} -void ETSPrimitiveType::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +void ETSPrimitiveType::Compile(compiler::ETSGen *etsg) const { - UNREACHABLE(); + etsg->GetAstCompiler()->Compile(this); } -checker::Type *ETSPrimitiveType::Check([[maybe_unused]] checker::TSChecker *checker) +checker::Type *ETSPrimitiveType::Check(checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *ETSPrimitiveType::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -46,9 +50,9 @@ checker::Type *ETSPrimitiveType::GetType([[maybe_unused]] checker::TSChecker *ch return checker->GlobalAnyType(); } -checker::Type *ETSPrimitiveType::Check([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *ETSPrimitiveType::Check(checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *ETSPrimitiveType::GetType([[maybe_unused]] checker::ETSChecker *checker) diff --git a/ir/ets/etsPrimitiveType.h b/ir/ets/etsPrimitiveType.h index c8ae085f4..c394b0019 100644 --- a/ir/ets/etsPrimitiveType.h +++ b/ir/ets/etsPrimitiveType.h @@ -33,11 +33,11 @@ public: void TransformChildren(const NodeTransformer &cb) override; 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([[maybe_unused]] compiler::ETSGen *etsg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; + void Compile(compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; + checker::Type *Check(checker::TSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; private: diff --git a/ir/ets/etsStructDeclaration.cpp b/ir/ets/etsStructDeclaration.cpp index 62f8b74cd..3b05f2717 100644 --- a/ir/ets/etsStructDeclaration.cpp +++ b/ir/ets/etsStructDeclaration.cpp @@ -15,6 +15,7 @@ #include "etsStructDeclaration.h" +#include "checker/TSchecker.h" #include "compiler/base/lreference.h" #include "compiler/core/pandagen.h" #include "compiler/core/ETSGen.h" @@ -48,24 +49,23 @@ void ETSStructDeclaration::Dump(ir::AstDumper *dumper) const {{"type", "ETSStructDeclaration"}, {"definition", def_}, {"decorators", AstDumper::Optional(decorators_)}}); } -void ETSStructDeclaration::Compile([[maybe_unused]] compiler::PandaGen *pg) const +void ETSStructDeclaration::Compile(compiler::PandaGen *pg) const { - UNREACHABLE(); + pg->GetAstCompiler()->Compile(this); } -void ETSStructDeclaration::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +void ETSStructDeclaration::Compile(compiler::ETSGen *etsg) const { - UNREACHABLE(); + etsg->GetAstCompiler()->Compile(this); } -checker::Type *ETSStructDeclaration::Check([[maybe_unused]] checker::TSChecker *checker) +checker::Type *ETSStructDeclaration::Check(checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *ETSStructDeclaration::Check(checker::ETSChecker *checker) { - def_->Check(checker); - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ir/ets/etsStructDeclaration.h b/ir/ets/etsStructDeclaration.h index 7a52e9b80..10a2201ab 100644 --- a/ir/ets/etsStructDeclaration.h +++ b/ir/ets/etsStructDeclaration.h @@ -54,11 +54,11 @@ public: void TransformChildren(const NodeTransformer &cb) override; 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([[maybe_unused]] compiler::ETSGen *etsg) const override; + void Compile(compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *Check(checker::TSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; private: ClassDefinition *def_; diff --git a/ir/ets/etsTypeReference.cpp b/ir/ets/etsTypeReference.cpp index 849f52346..7ac21bd51 100644 --- a/ir/ets/etsTypeReference.cpp +++ b/ir/ets/etsTypeReference.cpp @@ -15,11 +15,13 @@ #include "etsTypeReference.h" +#include "checker/ETSchecker.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "ir/ts/tsQualifiedName.h" #include "ir/ets/etsTypeReferencePart.h" -#include "checker/ETSchecker.h" -#include "compiler/core/ETSGen.h" namespace panda::es2panda::ir { void ETSTypeReference::TransformChildren(const NodeTransformer &cb) @@ -60,20 +62,23 @@ void ETSTypeReference::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "ETSTypeReference"}, {"part", part_}}); } -void ETSTypeReference::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} -void ETSTypeReference::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +void ETSTypeReference::Compile(compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void ETSTypeReference::Compile(compiler::ETSGen *etsg) const { - part_->Compile(etsg); + etsg->GetAstCompiler()->Compile(this); } -checker::Type *ETSTypeReference::Check([[maybe_unused]] checker::TSChecker *checker) +checker::Type *ETSTypeReference::Check(checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *ETSTypeReference::Check(checker::ETSChecker *checker) { - return GetType(checker); + return checker->GetAnalyzer()->Check(this); } checker::Type *ETSTypeReference::GetType(checker::ETSChecker *checker) diff --git a/ir/ets/etsTypeReference.h b/ir/ets/etsTypeReference.h index 17b8ef6ce..d771dcceb 100644 --- a/ir/ets/etsTypeReference.h +++ b/ir/ets/etsTypeReference.h @@ -41,10 +41,10 @@ public: void TransformChildren(const NodeTransformer &cb) override; 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([[maybe_unused]] compiler::ETSGen *etsg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + void Compile(compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; + checker::Type *Check(checker::TSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; private: diff --git a/ir/ets/etsTypeReferencePart.cpp b/ir/ets/etsTypeReferencePart.cpp index 4d86e0905..79a2b4e97 100644 --- a/ir/ets/etsTypeReferencePart.cpp +++ b/ir/ets/etsTypeReferencePart.cpp @@ -15,13 +15,12 @@ #include "etsTypeReferencePart.h" -#include "ir/astDump.h" -#include "ir/expressions/identifier.h" -#include "ir/ts/tsTypeParameterInstantiation.h" -#include "checker/TSchecker.h" #include "checker/ETSchecker.h" #include "checker/ets/typeRelationContext.h" +#include "checker/TSchecker.h" #include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" +#include "ir/astDump.h" namespace panda::es2panda::ir { void ETSTypeReferencePart::TransformChildren(const NodeTransformer &cb) @@ -58,20 +57,23 @@ void ETSTypeReferencePart::Dump(ir::AstDumper *dumper) const {"previous", AstDumper::Optional(prev_)}}); } -void ETSTypeReferencePart::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} -void ETSTypeReferencePart::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +void ETSTypeReferencePart::Compile(compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void ETSTypeReferencePart::Compile(compiler::ETSGen *etsg) const { - name_->Compile(etsg); + etsg->GetAstCompiler()->Compile(this); } -checker::Type *ETSTypeReferencePart::Check([[maybe_unused]] checker::TSChecker *checker) +checker::Type *ETSTypeReferencePart::Check(checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *ETSTypeReferencePart::Check(checker::ETSChecker *checker) { - return GetType(checker); + return checker->GetAnalyzer()->Check(this); } checker::Type *ETSTypeReferencePart::GetType(checker::ETSChecker *checker) diff --git a/ir/ets/etsTypeReferencePart.h b/ir/ets/etsTypeReferencePart.h index f8d82bcf2..f3e4b8aaf 100644 --- a/ir/ets/etsTypeReferencePart.h +++ b/ir/ets/etsTypeReferencePart.h @@ -58,10 +58,10 @@ public: void TransformChildren(const NodeTransformer &cb) override; 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([[maybe_unused]] compiler::ETSGen *etsg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + void Compile(compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; + checker::Type *Check(checker::TSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; private: diff --git a/ir/ets/etsWildcardType.cpp b/ir/ets/etsWildcardType.cpp index 07db87b9c..76c5ea1cc 100644 --- a/ir/ets/etsWildcardType.cpp +++ b/ir/ets/etsWildcardType.cpp @@ -15,11 +15,12 @@ #include "etsWildcardType.h" -#include "ir/astDump.h" -#include "ir/ets/etsTypeReference.h" -#include "checker/TSchecker.h" #include "checker/ETSchecker.h" +#include "checker/TSchecker.h" #include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" +#include "ir/astDump.h" +#include "ir/ets/etsTypeReference.h" namespace panda::es2panda::ir { void ETSWildcardType::TransformChildren(const NodeTransformer &cb) @@ -44,16 +45,19 @@ void ETSWildcardType::Dump(ir::AstDumper *dumper) const {"out", AstDumper::Optional(IsOut())}}); } -void ETSWildcardType::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void ETSWildcardType::Compile(compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} -void ETSWildcardType::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +void ETSWildcardType::Compile(compiler::ETSGen *etsg) const { - etsg->Unimplemented(); + etsg->GetAstCompiler()->Compile(this); } -checker::Type *ETSWildcardType::Check([[maybe_unused]] checker::TSChecker *checker) +checker::Type *ETSWildcardType::Check(checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *ETSWildcardType::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -61,9 +65,9 @@ checker::Type *ETSWildcardType::GetType([[maybe_unused]] checker::TSChecker *che return nullptr; } -checker::Type *ETSWildcardType::Check([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *ETSWildcardType::Check(checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *ETSWildcardType::GetType([[maybe_unused]] checker::ETSChecker *checker) diff --git a/ir/ets/etsWildcardType.h b/ir/ets/etsWildcardType.h index 4ce8ce2ad..ca14342e0 100644 --- a/ir/ets/etsWildcardType.h +++ b/ir/ets/etsWildcardType.h @@ -36,11 +36,11 @@ public: void TransformChildren(const NodeTransformer &cb) override; 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([[maybe_unused]] compiler::ETSGen *etsg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; + void Compile(compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; + checker::Type *Check(checker::TSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; private: diff --git a/ir/expressions/arrowFunctionExpression.cpp b/ir/expressions/arrowFunctionExpression.cpp index a7ceaf07c..0cb1b3b65 100644 --- a/ir/expressions/arrowFunctionExpression.cpp +++ b/ir/expressions/arrowFunctionExpression.cpp @@ -44,124 +44,21 @@ void ArrowFunctionExpression::Dump(ir::AstDumper *dumper) const void ArrowFunctionExpression::Compile(compiler::PandaGen *pg) const { - pg->DefineFunction(func_, func_, func_->Scope()->InternalName()); + pg->GetAstCompiler()->Compile(this); } void ArrowFunctionExpression::Compile(compiler::ETSGen *etsg) const { - ASSERT(resolved_lambda_ != nullptr); - auto *ctor = resolved_lambda_->TsType()->AsETSObjectType()->ConstructSignatures()[0]; - std::vector arguments; - - for (auto *it : captured_vars_) { - if (it->HasFlag(binder::VariableFlags::LOCAL)) { - arguments.push_back(it->AsLocalVariable()->Vreg()); - } - } - - if (propagate_this_) { - arguments.push_back(etsg->GetThisReg()); - } - - etsg->InitLambdaObject(this, ctor, arguments); - etsg->SetAccumulatorType(resolved_lambda_->TsType()); + etsg->GetAstCompiler()->Compile(this); } checker::Type *ArrowFunctionExpression::Check(checker::TSChecker *checker) { - binder::Variable *func_var = nullptr; - - if (func_->Parent()->Parent() != nullptr && func_->Parent()->Parent()->IsVariableDeclarator() && - func_->Parent()->Parent()->AsVariableDeclarator()->Id()->IsIdentifier()) { - func_var = func_->Parent()->Parent()->AsVariableDeclarator()->Id()->AsIdentifier()->Variable(); - } - - checker::ScopeContext scope_ctx(checker, func_->Scope()); - - auto *signature_info = checker->Allocator()->New(checker->Allocator()); - checker->CheckFunctionParameterDeclarations(func_->Params(), signature_info); - - auto *signature = - checker->Allocator()->New(signature_info, checker->GlobalResolvingReturnType(), func_); - checker::Type *func_type = checker->CreateFunctionTypeWithSignature(signature); - - if (func_var != nullptr && func_var->TsType() == nullptr) { - func_var->SetTsType(func_type); - } - - signature->SetReturnType(checker->HandleFunctionReturn(func_)); - - if (!func_->Body()->IsExpression()) { - func_->Body()->Check(checker); - } - - return func_type; + return checker->GetAnalyzer()->Check(this); } checker::Type *ArrowFunctionExpression::Check(checker::ETSChecker *checker) { - if (TsType() != nullptr) { - return TsType(); - } - - auto *func_type = checker->BuildFunctionSignature(func_, false); - - if (Function()->IsAsyncFunc()) { - auto *ret_type = static_cast(Function()->Signature()->ReturnType()); - if (ret_type->AssemblerName() != checker->GlobalBuiltinPromiseType()->AssemblerName()) { - checker->ThrowTypeError("Return type of async lambda must be 'Promise'", Function()->Start()); - } - } - - checker::ScopeContext scope_ctx(checker, func_->Scope()); - - if (checker->HasStatus(checker::CheckerStatus::IN_INSTANCE_EXTENSION_METHOD)) { - /* - example code: - ``` - class A { - prop:number - } - function A.method() { - let a = () => { - console.println(this.prop) - } - } - ``` - here the enclosing class of arrow function should be Class A - */ - checker->Context().SetContainingClass( - checker->Scope()->Find(binder::Binder::MANDATORY_PARAM_THIS).variable->TsType()->AsETSObjectType()); - } - - checker::SavedCheckerContext saved_context(checker, checker->Context().Status(), - checker->Context().ContainingClass()); - checker->AddStatus(checker::CheckerStatus::IN_LAMBDA); - checker->Context().SetContainingSignature(func_type->CallSignatures()[0]); - - auto *body_type = func_->Body()->Check(checker); - - if (func_->Body()->IsExpression()) { - if (func_->ReturnTypeAnnotation() == nullptr) { - func_type->CallSignatures()[0]->SetReturnType(body_type); - } - - checker::AssignmentContext( - checker->Relation(), func_->Body()->AsExpression(), body_type, func_type->CallSignatures()[0]->ReturnType(), - func_->Start(), - {"Return statements return type is not compatible with the containing functions return type"}, - checker::TypeRelationFlag::DIRECT_RETURN); - } - - checker->Context().SetContainingSignature(nullptr); - checker->CheckCapturedVariables(); - - for (auto [var, _] : checker->Context().CapturedVars()) { - (void)_; - captured_vars_.push_back(var); - } - - SetTsType(func_type); - return TsType(); + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ir/expressions/arrowFunctionExpression.h b/ir/expressions/arrowFunctionExpression.h index 5bcefdb81..204ce84ac 100644 --- a/ir/expressions/arrowFunctionExpression.h +++ b/ir/expressions/arrowFunctionExpression.h @@ -18,6 +18,10 @@ #include "ir/expression.h" +namespace panda::es2panda::compiler { +class ETSCompiler; +} // namespace panda::es2panda::compiler + namespace panda::es2panda::ir { class ScriptFunction; @@ -27,6 +31,8 @@ public: : Expression(AstNodeType::ARROW_FUNCTION_EXPRESSION), func_(func), captured_vars_(allocator->Adapter()) { } + // TODO (csabahurton): friend relationship can be removed once there are getters for private fields + friend class compiler::ETSCompiler; const ScriptFunction *Function() const { @@ -71,10 +77,10 @@ public: void TransformChildren(const NodeTransformer &cb) override; 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; void Compile(compiler::ETSGen *etsg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *Check(checker::TSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; private: ScriptFunction *func_; diff --git a/ir/statements/tryStatement.h b/ir/statements/tryStatement.h index 74b955c87..af69c1eb9 100644 --- a/ir/statements/tryStatement.h +++ b/ir/statements/tryStatement.h @@ -16,7 +16,7 @@ #ifndef ES2PANDA_IR_STATEMENT_TRY_STATEMENT_H #define ES2PANDA_IR_STATEMENT_TRY_STATEMENT_H -#include "compiler/core/ETSGen.h" +#include "compiler/core/labelPair.h" #include "ir/statement.h" namespace panda::es2panda::compiler { -- Gitee From 2418808040a490ab3379915cf7a3e4ec95574c5c Mon Sep 17 00:00:00 2001 From: Csaba Hurton Date: Thu, 26 Oct 2023 11:44:01 +0200 Subject: [PATCH 3/3] [eTS] (8) Move Compile and Check Logic from ASTNode classes Compile logic is moved to JSCompiler and ETSCompiler classes. Check logic with their helper functions is moved to TSAnalyzer and ETSAnalyzer classes. AstNodes that are being moved: - nodes inside ir/module: - ImportDeclaration - ImportDefaultSpecifier - ImportNamespaceSpecifier - ImportNamespaceSpecifier - nodes inside ir/statements: - ClassDeclaration - ContinueStatement - DebuggerStatement - DoWhileStatement Linked Internal Issue 13840 Signed-off-by: Csaba Hurton --- checker/ETSAnalyzer.cpp | 117 ++++++++++++++++++++----- checker/TSAnalyzer.cpp | 28 +++--- compiler/core/ETSCompiler.cpp | 55 ++++++++---- compiler/core/JSCompiler.cpp | 57 +++++++----- ir/module/importDeclaration.cpp | 30 +++---- ir/module/importDeclaration.h | 8 +- ir/module/importDefaultSpecifier.cpp | 26 +++--- ir/module/importDefaultSpecifier.h | 7 +- ir/module/importNamespaceSpecifier.cpp | 91 ++++--------------- ir/module/importNamespaceSpecifier.h | 7 +- ir/module/importSpecifier.cpp | 23 ++--- ir/module/importSpecifier.h | 8 +- ir/statements/classDeclaration.cpp | 25 ++---- ir/statements/classDeclaration.h | 8 +- ir/statements/continueStatement.cpp | 30 ++----- ir/statements/continueStatement.h | 20 ++++- ir/statements/debuggerStatement.cpp | 22 +++-- ir/statements/debuggerStatement.h | 7 +- ir/statements/doWhileStatement.cpp | 57 +++--------- ir/statements/doWhileStatement.h | 8 +- 20 files changed, 326 insertions(+), 308 deletions(-) diff --git a/checker/ETSAnalyzer.cpp b/checker/ETSAnalyzer.cpp index 33a317b03..d4423b285 100644 --- a/checker/ETSAnalyzer.cpp +++ b/checker/ETSAnalyzer.cpp @@ -19,14 +19,6 @@ #include "checker/ETSchecker.h" #include "checker/ets/castingContext.h" #include "checker/ets/typeRelationContext.h" -#include "ir/base/catchClause.h" -#include "ir/base/classProperty.h" -#include "ir/base/classStaticBlock.h" -#include "ir/expressions/identifier.h" -#include "ir/expressions/objectExpression.h" -#include "ir/expressions/arrayExpression.h" -#include "ir/statements/blockStatement.h" -#include "ir/statements/returnStatement.h" #include "util/helpers.h" namespace panda::es2panda::checker { @@ -573,25 +565,96 @@ checker::Type *ETSAnalyzer::Check(ir::ExportSpecifier *st) const checker::Type *ETSAnalyzer::Check(ir::ImportDeclaration *st) const { - (void)st; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + checker::Type *type = nullptr; + for (auto *spec : st->Specifiers()) { + if (spec->IsImportNamespaceSpecifier()) { + type = spec->AsImportNamespaceSpecifier()->Check(checker); + } + } + + return type; } -checker::Type *ETSAnalyzer::Check(ir::ImportDefaultSpecifier *st) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ImportDefaultSpecifier *st) const { - (void)st; UNREACHABLE(); } checker::Type *ETSAnalyzer::Check(ir::ImportNamespaceSpecifier *st) const { - (void)st; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + if (st->Local()->Name().Empty()) { + return nullptr; + } + + if (st->Local()->AsIdentifier()->TsType() != nullptr) { + return st->Local()->TsType(); + } + + auto *import_decl = st->Parent()->AsETSImportDeclaration(); + auto import_path = import_decl->Source()->Str(); + + if (import_decl->IsPureDynamic()) { + auto *type = checker->GlobalBuiltinDynamicType(import_decl->Language()); + checker->SetrModuleObjectTsType(st->Local(), type); + return type; + } + + std::string package_name = + (import_decl->Module() == nullptr) ? import_path.Mutf8() : import_decl->Module()->Str().Mutf8(); + + std::replace(package_name.begin(), package_name.end(), '/', '.'); + util::UString package_path(package_name, checker->Allocator()); + std::vector synthetic_names = checker->GetNameForSynteticObjectType(package_path.View()); + + ASSERT(!synthetic_names.empty()); + + auto assembler_name = synthetic_names[0]; + if (import_decl->Module() != nullptr) { + assembler_name = util::UString(assembler_name.Mutf8().append(".").append(compiler::Signatures::ETS_GLOBAL), + checker->Allocator()) + .View(); + } + + auto *module_object_type = + checker->Allocator()->New(checker->Allocator(), synthetic_names[0], assembler_name, + st->Local()->AsIdentifier(), checker::ETSObjectFlags::CLASS); + + auto *root_decl = checker->Allocator()->New(synthetic_names[0]); + binder::LocalVariable *root_var = + checker->Allocator()->New(root_decl, binder::VariableFlags::NONE); + root_var->SetTsType(module_object_type); + + synthetic_names.erase(synthetic_names.begin()); + checker::ETSObjectType *last_object_type(module_object_type); + + for (const auto &synthetic_name : synthetic_names) { + auto *synthetic_obj_type = checker->Allocator()->New( + checker->Allocator(), synthetic_name, synthetic_name, st->Local()->AsIdentifier(), + checker::ETSObjectFlags::NO_OPTS); + + auto *class_decl = checker->Allocator()->New(synthetic_name); + binder::LocalVariable *var = + checker->Allocator()->New(class_decl, binder::VariableFlags::CLASS); + var->SetTsType(synthetic_obj_type); + last_object_type->AddProperty(var); + synthetic_obj_type->SetEnclosingType(last_object_type); + last_object_type = synthetic_obj_type; + } + + checker->SetPropertiesForModuleObject( + last_object_type, + (import_decl->Module() != nullptr) + ? util::UString(import_path.Mutf8() + import_decl->Module()->Str().Mutf8(), checker->Allocator()).View() + : import_path); + checker->SetrModuleObjectTsType(st->Local(), last_object_type); + + return module_object_type; } -checker::Type *ETSAnalyzer::Check(ir::ImportSpecifier *st) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ImportSpecifier *st) const { - (void)st; UNREACHABLE(); } // compile methods for STATEMENTS in alphabetical order @@ -615,26 +678,32 @@ checker::Type *ETSAnalyzer::Check(ir::BreakStatement *st) const checker::Type *ETSAnalyzer::Check(ir::ClassDeclaration *st) const { - (void)st; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + st->Definition()->Check(checker); + return nullptr; } checker::Type *ETSAnalyzer::Check(ir::ContinueStatement *st) const { - (void)st; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + st->target_ = checker->FindJumpTarget(st->Type(), st, st->Ident()); + return nullptr; } -checker::Type *ETSAnalyzer::Check(ir::DebuggerStatement *st) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::DebuggerStatement *st) const { - (void)st; UNREACHABLE(); } checker::Type *ETSAnalyzer::Check(ir::DoWhileStatement *st) const { - (void)st; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + checker::ScopeContext scope_ctx(checker, st->Scope()); + + checker->CheckTruthinessOfType(st->Test()); + st->Body()->Check(checker); + + return nullptr; } checker::Type *ETSAnalyzer::Check(ir::EmptyStatement *st) const diff --git a/checker/TSAnalyzer.cpp b/checker/TSAnalyzer.cpp index 62f2f79a9..b7b55e561 100644 --- a/checker/TSAnalyzer.cpp +++ b/checker/TSAnalyzer.cpp @@ -465,27 +465,23 @@ checker::Type *TSAnalyzer::Check(ir::ExportSpecifier *st) const UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ImportDeclaration *st) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ImportDeclaration *st) const { - (void)st; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ImportDefaultSpecifier *st) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ImportDefaultSpecifier *st) const { - (void)st; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ImportNamespaceSpecifier *st) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ImportNamespaceSpecifier *st) const { - (void)st; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ImportSpecifier *st) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ImportSpecifier *st) const { - (void)st; UNREACHABLE(); } // compile methods for STATEMENTS in alphabetical order @@ -507,9 +503,8 @@ checker::Type *TSAnalyzer::Check(ir::BreakStatement *st) const UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ClassDeclaration *st) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ClassDeclaration *st) const { - (void)st; UNREACHABLE(); } @@ -519,16 +514,21 @@ checker::Type *TSAnalyzer::Check(ir::ContinueStatement *st) const UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::DebuggerStatement *st) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::DebuggerStatement *st) const { - (void)st; UNREACHABLE(); } checker::Type *TSAnalyzer::Check(ir::DoWhileStatement *st) const { - (void)st; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + checker::ScopeContext scope_ctx(checker, st->Scope()); + + checker::Type *test_type = st->Test()->Check(checker); + checker->CheckTruthinessOfType(test_type, st->Test()->Start()); + st->Body()->Check(checker); + + return nullptr; } checker::Type *TSAnalyzer::Check(ir::EmptyStatement *st) const diff --git a/compiler/core/ETSCompiler.cpp b/compiler/core/ETSCompiler.cpp index ffff9fe9d..104ff2b4b 100644 --- a/compiler/core/ETSCompiler.cpp +++ b/compiler/core/ETSCompiler.cpp @@ -465,27 +465,23 @@ void ETSCompiler::Compile(const ir::ExportSpecifier *st) const UNREACHABLE(); } -void ETSCompiler::Compile(const ir::ImportDeclaration *st) const +void ETSCompiler::Compile([[maybe_unused]] const ir::ImportDeclaration *st) const { - (void)st; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::ImportDefaultSpecifier *st) const +void ETSCompiler::Compile([[maybe_unused]] const ir::ImportDefaultSpecifier *st) const { - (void)st; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::ImportNamespaceSpecifier *st) const +void ETSCompiler::Compile([[maybe_unused]] const ir::ImportNamespaceSpecifier *st) const { - (void)st; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::ImportSpecifier *st) const +void ETSCompiler::Compile([[maybe_unused]] const ir::ImportSpecifier *st) const { - (void)st; UNREACHABLE(); } // compile methods for STATEMENTS in alphabetical order @@ -507,28 +503,55 @@ void ETSCompiler::Compile(const ir::BreakStatement *st) const UNREACHABLE(); } -void ETSCompiler::Compile(const ir::ClassDeclaration *st) const +void ETSCompiler::Compile([[maybe_unused]] const ir::ClassDeclaration *st) const { - (void)st; UNREACHABLE(); } +static void CompileImpl(const ir::ContinueStatement *self, ETSGen *etsg) +{ + compiler::Label *target = etsg->ControlFlowChangeContinue(self->Ident()); + etsg->Branch(self, target); +} + void ETSCompiler::Compile(const ir::ContinueStatement *st) const { - (void)st; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + if (etsg->ExtendWithFinalizer(st->parent_, st)) { + return; + } + CompileImpl(st, etsg); } -void ETSCompiler::Compile(const ir::DebuggerStatement *st) const +void ETSCompiler::Compile([[maybe_unused]] const ir::DebuggerStatement *st) const { - (void)st; UNREACHABLE(); } +void CompileImpl(const ir::DoWhileStatement *self, ETSGen *etsg) +{ + auto *start_label = etsg->AllocLabel(); + compiler::LabelTarget label_target(etsg); + + etsg->SetLabel(self, start_label); + + { + compiler::LocalRegScope reg_scope(etsg, self->Scope()); + compiler::LabelContext label_ctx(etsg, label_target); + self->Body()->Compile(etsg); + } + + etsg->SetLabel(self, label_target.ContinueTarget()); + compiler::Condition::Compile(etsg, self->Test(), label_target.BreakTarget()); + + etsg->Branch(self, start_label); + etsg->SetLabel(self, label_target.BreakTarget()); +} + void ETSCompiler::Compile(const ir::DoWhileStatement *st) const { - (void)st; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + CompileImpl(st, etsg); } void ETSCompiler::Compile(const ir::EmptyStatement *st) const diff --git a/compiler/core/JSCompiler.cpp b/compiler/core/JSCompiler.cpp index 5be37688d..732540bd4 100644 --- a/compiler/core/JSCompiler.cpp +++ b/compiler/core/JSCompiler.cpp @@ -768,27 +768,20 @@ void JSCompiler::Compile(const ir::ExportSpecifier *st) const UNREACHABLE(); } -void JSCompiler::Compile(const ir::ImportDeclaration *st) const -{ - (void)st; - UNREACHABLE(); -} +void JSCompiler::Compile([[maybe_unused]] const ir::ImportDeclaration *st) const {} -void JSCompiler::Compile(const ir::ImportDefaultSpecifier *st) const +void JSCompiler::Compile([[maybe_unused]] const ir::ImportDefaultSpecifier *st) const { - (void)st; UNREACHABLE(); } -void JSCompiler::Compile(const ir::ImportNamespaceSpecifier *st) const +void JSCompiler::Compile([[maybe_unused]] const ir::ImportNamespaceSpecifier *st) const { - (void)st; UNREACHABLE(); } -void JSCompiler::Compile(const ir::ImportSpecifier *st) const +void JSCompiler::Compile([[maybe_unused]] const ir::ImportSpecifier *st) const { - (void)st; UNREACHABLE(); } // Compile methods for STATEMENTS in alphabetical order @@ -812,26 +805,50 @@ void JSCompiler::Compile(const ir::BreakStatement *st) const void JSCompiler::Compile(const ir::ClassDeclaration *st) const { - (void)st; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + auto lref = compiler::JSLReference::Create(pg, st->Definition()->Ident(), true); + st->Definition()->Compile(pg); + lref.SetValue(); +} + +static void CompileImpl(const ir::ContinueStatement *self, PandaGen *cg) +{ + compiler::Label *target = cg->ControlFlowChangeContinue(self->Ident()); + cg->Branch(self, target); } void JSCompiler::Compile(const ir::ContinueStatement *st) const { - (void)st; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + CompileImpl(st, pg); } -void JSCompiler::Compile(const ir::DebuggerStatement *st) const +void JSCompiler::Compile([[maybe_unused]] const ir::DebuggerStatement *st) const {} + +static void CompileImpl(const ir::DoWhileStatement *self, PandaGen *cg) { - (void)st; - UNREACHABLE(); + auto *start_label = cg->AllocLabel(); + compiler::LabelTarget label_target(cg); + + cg->SetLabel(self, start_label); + + { + compiler::LocalRegScope reg_scope(cg, self->Scope()); + compiler::LabelContext label_ctx(cg, label_target); + self->Body()->Compile(cg); + } + + cg->SetLabel(self, label_target.ContinueTarget()); + compiler::Condition::Compile(cg, self->Test(), label_target.BreakTarget()); + + cg->Branch(self, start_label); + cg->SetLabel(self, label_target.BreakTarget()); } void JSCompiler::Compile(const ir::DoWhileStatement *st) const { - (void)st; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + CompileImpl(st, pg); } void JSCompiler::Compile(const ir::EmptyStatement *st) const diff --git a/ir/module/importDeclaration.cpp b/ir/module/importDeclaration.cpp index b946fbd1b..e1208b0d0 100644 --- a/ir/module/importDeclaration.cpp +++ b/ir/module/importDeclaration.cpp @@ -15,11 +15,9 @@ #include "importDeclaration.h" +#include "checker/TSchecker.h" #include "compiler/core/ETSGen.h" -#include "ir/astDump.h" -#include "ir/expressions/literals/stringLiteral.h" -#include "ir/module/importNamespaceSpecifier.h" -#include "ir/module/importSpecifier.h" +#include "compiler/core/pandagen.h" namespace panda::es2panda::ir { void ImportDeclaration::TransformChildren(const NodeTransformer &cb) @@ -45,27 +43,23 @@ void ImportDeclaration::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "ImportDeclaration"}, {"source", source_}, {"specifiers", specifiers_}}); } -void ImportDeclaration::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} - -void ImportDeclaration::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +void ImportDeclaration::Compile(compiler::PandaGen *pg) const { - UNREACHABLE(); + pg->GetAstCompiler()->Compile(this); } -checker::Type *ImportDeclaration::Check([[maybe_unused]] checker::TSChecker *checker) +void ImportDeclaration::Compile(compiler::ETSGen *etsg) const { - return nullptr; + etsg->GetAstCompiler()->Compile(this); } -checker::Type *ImportDeclaration::Check([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *ImportDeclaration::Check(checker::TSChecker *checker) { - checker::Type *type = nullptr; - for (auto *spec : specifiers_) { - if (spec->IsImportNamespaceSpecifier()) { - type = spec->AsImportNamespaceSpecifier()->Check(checker); - } - } + return checker->GetAnalyzer()->Check(this); +} - return type; +checker::Type *ImportDeclaration::Check(checker::ETSChecker *checker) +{ + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ir/module/importDeclaration.h b/ir/module/importDeclaration.h index 18594b35e..fc8e92388 100644 --- a/ir/module/importDeclaration.h +++ b/ir/module/importDeclaration.h @@ -47,10 +47,10 @@ public: void TransformChildren(const NodeTransformer &cb) override; 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([[maybe_unused]] compiler::ETSGen *etsg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + void Compile(compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; + checker::Type *Check(checker::TSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; private: StringLiteral *source_; diff --git a/ir/module/importDefaultSpecifier.cpp b/ir/module/importDefaultSpecifier.cpp index 2413efb89..ea4a43b93 100644 --- a/ir/module/importDefaultSpecifier.cpp +++ b/ir/module/importDefaultSpecifier.cpp @@ -15,11 +15,9 @@ #include "importDefaultSpecifier.h" -#include "checker/ETSchecker.h" -#include "ir/astDump.h" -#include "ir/expressions/identifier.h" -#include "ir/module/importDeclaration.h" -#include "ir/expressions/literals/stringLiteral.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" namespace panda::es2panda::ir { void ImportDefaultSpecifier::TransformChildren(const NodeTransformer &cb) @@ -37,15 +35,23 @@ void ImportDefaultSpecifier::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "ImportDefaultSpecifier"}, {"local", local_}}); } -void ImportDefaultSpecifier::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void ImportDefaultSpecifier::Compile(compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} + +void ImportDefaultSpecifier::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} -checker::Type *ImportDefaultSpecifier::Check([[maybe_unused]] checker::TSChecker *checker) +checker::Type *ImportDefaultSpecifier::Check(checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } -checker::Type *ImportDefaultSpecifier::Check([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *ImportDefaultSpecifier::Check(checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ir/module/importDefaultSpecifier.h b/ir/module/importDefaultSpecifier.h index 7d39425a0..0ad735084 100644 --- a/ir/module/importDefaultSpecifier.h +++ b/ir/module/importDefaultSpecifier.h @@ -35,9 +35,10 @@ public: void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; - void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + void Compile(compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; + checker::Type *Check(checker::TSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; private: Identifier *local_; diff --git a/ir/module/importNamespaceSpecifier.cpp b/ir/module/importNamespaceSpecifier.cpp index 466ed4e40..dc138e163 100644 --- a/ir/module/importNamespaceSpecifier.cpp +++ b/ir/module/importNamespaceSpecifier.cpp @@ -15,12 +15,9 @@ #include "importNamespaceSpecifier.h" -#include "checker/ETSchecker.h" -#include "binder/ETSBinder.h" -#include "ir/astDump.h" -#include "ir/expressions/identifier.h" -#include "ir/module/importDeclaration.h" -#include "ir/expressions/literals/stringLiteral.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" namespace panda::es2panda::ir { void ImportNamespaceSpecifier::TransformChildren(const NodeTransformer &cb) @@ -38,81 +35,23 @@ void ImportNamespaceSpecifier::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "ImportNamespaceSpecifier"}, {"local", local_}}); } -void ImportNamespaceSpecifier::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} - -checker::Type *ImportNamespaceSpecifier::Check([[maybe_unused]] checker::TSChecker *checker) +void ImportNamespaceSpecifier::Compile(compiler::PandaGen *pg) const { - return nullptr; + pg->GetAstCompiler()->Compile(this); } -checker::Type *ImportNamespaceSpecifier::Check([[maybe_unused]] checker::ETSChecker *checker) +void ImportNamespaceSpecifier::Compile(compiler::ETSGen *etsg) const { - if (Local()->Name().Empty()) { - return nullptr; - } - - if (Local()->AsIdentifier()->TsType() != nullptr) { - return local_->TsType(); - } - - auto *import_decl = Parent()->AsETSImportDeclaration(); - auto import_path = import_decl->Source()->Str(); - - if (import_decl->IsPureDynamic()) { - auto *type = checker->GlobalBuiltinDynamicType(import_decl->Language()); - checker->SetrModuleObjectTsType(local_, type); - return type; - } - - std::string package_name = - (import_decl->Module() == nullptr) ? import_path.Mutf8() : import_decl->Module()->Str().Mutf8(); - - std::replace(package_name.begin(), package_name.end(), '/', '.'); - util::UString package_path(package_name, checker->Allocator()); - std::vector synthetic_names = checker->GetNameForSynteticObjectType(package_path.View()); - - ASSERT(!synthetic_names.empty()); - - auto assembler_name = synthetic_names[0]; - if (import_decl->Module() != nullptr) { - assembler_name = util::UString(assembler_name.Mutf8().append(".").append(compiler::Signatures::ETS_GLOBAL), - checker->Allocator()) - .View(); - } - - auto *module_object_type = - checker->Allocator()->New(checker->Allocator(), synthetic_names[0], assembler_name, - local_->AsIdentifier(), checker::ETSObjectFlags::CLASS); - - auto *root_decl = checker->Allocator()->New(synthetic_names[0]); - binder::LocalVariable *root_var = - checker->Allocator()->New(root_decl, binder::VariableFlags::NONE); - root_var->SetTsType(module_object_type); - - synthetic_names.erase(synthetic_names.begin()); - checker::ETSObjectType *last_object_type(module_object_type); - - for (const auto &synthetic_name : synthetic_names) { - auto *synthetic_obj_type = - checker->Allocator()->New(checker->Allocator(), synthetic_name, synthetic_name, - local_->AsIdentifier(), checker::ETSObjectFlags::NO_OPTS); - - auto *class_decl = checker->Allocator()->New(synthetic_name); - binder::LocalVariable *var = - checker->Allocator()->New(class_decl, binder::VariableFlags::CLASS); - var->SetTsType(synthetic_obj_type); - last_object_type->AddProperty(var); - synthetic_obj_type->SetEnclosingType(last_object_type); - last_object_type = synthetic_obj_type; - } + etsg->GetAstCompiler()->Compile(this); +} - checker->SetPropertiesForModuleObject( - last_object_type, - (import_decl->Module() != nullptr) - ? util::UString(import_path.Mutf8() + import_decl->Module()->Str().Mutf8(), checker->Allocator()).View() - : import_path); - checker->SetrModuleObjectTsType(local_, last_object_type); +checker::Type *ImportNamespaceSpecifier::Check(checker::TSChecker *checker) +{ + return checker->GetAnalyzer()->Check(this); +} - return module_object_type; +checker::Type *ImportNamespaceSpecifier::Check(checker::ETSChecker *checker) +{ + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ir/module/importNamespaceSpecifier.h b/ir/module/importNamespaceSpecifier.h index 0af20262b..e725cce1a 100644 --- a/ir/module/importNamespaceSpecifier.h +++ b/ir/module/importNamespaceSpecifier.h @@ -41,9 +41,10 @@ public: void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; - void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + void Compile(compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; + checker::Type *Check(checker::TSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; private: Identifier *local_; diff --git a/ir/module/importSpecifier.cpp b/ir/module/importSpecifier.cpp index 343614347..984e4137d 100644 --- a/ir/module/importSpecifier.cpp +++ b/ir/module/importSpecifier.cpp @@ -15,11 +15,9 @@ #include "importSpecifier.h" +#include "checker/TSchecker.h" #include "compiler/core/ETSGen.h" -#include "ir/astDump.h" -#include "ir/expressions/identifier.h" -#include "ir/expressions/literals/stringLiteral.h" -#include "ir/module/importDeclaration.h" +#include "compiler/core/pandagen.h" namespace panda::es2panda::ir { void ImportSpecifier::TransformChildren(const NodeTransformer &cb) @@ -43,19 +41,22 @@ void ImportSpecifier::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "ImportSpecifier"}, {"local", ir::AstDumper::Optional(local_)}, {"imported", imported_}}); } -void ImportSpecifier::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} -void ImportSpecifier::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +void ImportSpecifier::Compile(compiler::PandaGen *pg) const { - UNREACHABLE(); + pg->GetAstCompiler()->Compile(this); +} +void ImportSpecifier::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); } -checker::Type *ImportSpecifier::Check([[maybe_unused]] checker::TSChecker *checker) +checker::Type *ImportSpecifier::Check(checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } -checker::Type *ImportSpecifier::Check([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *ImportSpecifier::Check(checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ir/module/importSpecifier.h b/ir/module/importSpecifier.h index 9a0c1311a..c59fba3be 100644 --- a/ir/module/importSpecifier.h +++ b/ir/module/importSpecifier.h @@ -51,10 +51,10 @@ public: void TransformChildren(const NodeTransformer &cb) override; 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([[maybe_unused]] compiler::ETSGen *etsg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + void Compile(compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; + checker::Type *Check(checker::TSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; private: Identifier *imported_; diff --git a/ir/statements/classDeclaration.cpp b/ir/statements/classDeclaration.cpp index 6c0822d5f..627e9bece 100644 --- a/ir/statements/classDeclaration.cpp +++ b/ir/statements/classDeclaration.cpp @@ -15,13 +15,9 @@ #include "classDeclaration.h" -#include "compiler/base/lreference.h" -#include "compiler/core/pandagen.h" +#include "checker/TSchecker.h" #include "compiler/core/ETSGen.h" -#include "ir/astDump.h" -#include "ir/base/classDefinition.h" -#include "ir/base/decorator.h" -#include "ir/expressions/identifier.h" +#include "compiler/core/pandagen.h" namespace panda::es2panda::ir { void ClassDeclaration::TransformChildren(const NodeTransformer &cb) @@ -47,26 +43,23 @@ void ClassDeclaration::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "ClassDeclaration"}, {"definition", def_}, {"decorators", AstDumper::Optional(decorators_)}}); } -void ClassDeclaration::Compile([[maybe_unused]] compiler::PandaGen *pg) const +void ClassDeclaration::Compile(compiler::PandaGen *pg) const { - auto lref = compiler::JSLReference::Create(pg, def_->Ident(), true); - def_->Compile(pg); - lref.SetValue(); + pg->GetAstCompiler()->Compile(this); } -void ClassDeclaration::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +void ClassDeclaration::Compile(compiler::ETSGen *etsg) const { - UNREACHABLE(); + etsg->GetAstCompiler()->Compile(this); } -checker::Type *ClassDeclaration::Check([[maybe_unused]] checker::TSChecker *checker) +checker::Type *ClassDeclaration::Check(checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *ClassDeclaration::Check(checker::ETSChecker *checker) { - def_->Check(checker); - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ir/statements/classDeclaration.h b/ir/statements/classDeclaration.h index c2e535c07..8984cf065 100644 --- a/ir/statements/classDeclaration.h +++ b/ir/statements/classDeclaration.h @@ -54,11 +54,11 @@ public: void TransformChildren(const NodeTransformer &cb) override; 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([[maybe_unused]] compiler::ETSGen *etsg) const override; + void Compile(compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *Check(checker::TSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; private: ClassDefinition *def_; diff --git a/ir/statements/continueStatement.cpp b/ir/statements/continueStatement.cpp index 47cc3d6e7..0dbdedb73 100644 --- a/ir/statements/continueStatement.cpp +++ b/ir/statements/continueStatement.cpp @@ -15,10 +15,9 @@ #include "continueStatement.h" -#include "compiler/core/pandagen.h" +#include "checker/TSchecker.h" #include "compiler/core/ETSGen.h" -#include "ir/astDump.h" -#include "checker/ETSchecker.h" +#include "compiler/core/pandagen.h" namespace panda::es2panda::ir { void ContinueStatement::TransformChildren(const NodeTransformer &cb) @@ -40,34 +39,23 @@ void ContinueStatement::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "ContinueStatement"}, {"label", AstDumper::Nullable(ident_)}}); } -template -void CompileImpl(const ContinueStatement *self, [[maybe_unused]] CodeGen *cg) -{ - compiler::Label *target = cg->ControlFlowChangeContinue(self->Ident()); - cg->Branch(self, target); -} - -void ContinueStatement::Compile([[maybe_unused]] compiler::PandaGen *pg) const +void ContinueStatement::Compile(compiler::PandaGen *pg) const { - CompileImpl(this, pg); + pg->GetAstCompiler()->Compile(this); } -void ContinueStatement::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +void ContinueStatement::Compile(compiler::ETSGen *etsg) const { - if (etsg->ExtendWithFinalizer(parent_, this)) { - return; - } - CompileImpl(this, etsg); + etsg->GetAstCompiler()->Compile(this); } -checker::Type *ContinueStatement::Check([[maybe_unused]] checker::TSChecker *checker) +checker::Type *ContinueStatement::Check(checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *ContinueStatement::Check(checker::ETSChecker *checker) { - target_ = checker->FindJumpTarget(Type(), this, ident_); - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ir/statements/continueStatement.h b/ir/statements/continueStatement.h index 2eead3db0..804670d2a 100644 --- a/ir/statements/continueStatement.h +++ b/ir/statements/continueStatement.h @@ -19,12 +19,24 @@ #include "ir/statement.h" #include "ir/expressions/identifier.h" +namespace panda::es2panda::checker { +class ETSAnalyzer; +} // namespace panda::es2panda::checker + +namespace panda::es2panda::compiler { +class ETSCompiler; +} // namespace panda::es2panda::compiler + namespace panda::es2panda::ir { class ContinueStatement : public Statement { public: explicit ContinueStatement() : Statement(AstNodeType::CONTINUE_STATEMENT) {} explicit ContinueStatement(Identifier *ident) : Statement(AstNodeType::CONTINUE_STATEMENT), ident_(ident) {} + // TODO (csabahurton): these friend relationships can be removed once there are getters for private fields + friend class checker::ETSAnalyzer; + friend class compiler::ETSCompiler; + const Identifier *Ident() const { return ident_; @@ -38,10 +50,10 @@ public: void TransformChildren(const NodeTransformer &cb) override; 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([[maybe_unused]] compiler::ETSGen *etsg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + void Compile(compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; + checker::Type *Check(checker::TSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; private: Identifier *ident_ {}; diff --git a/ir/statements/debuggerStatement.cpp b/ir/statements/debuggerStatement.cpp index 506daf50a..b0bb23faa 100644 --- a/ir/statements/debuggerStatement.cpp +++ b/ir/statements/debuggerStatement.cpp @@ -15,7 +15,9 @@ #include "debuggerStatement.h" -#include "ir/astDump.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" namespace panda::es2panda::ir { void DebuggerStatement::TransformChildren([[maybe_unused]] const NodeTransformer &cb) {} @@ -26,15 +28,23 @@ void DebuggerStatement::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "DebuggerStatement"}}); } -void DebuggerStatement::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void DebuggerStatement::Compile(compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} + +void DebuggerStatement::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} -checker::Type *DebuggerStatement::Check([[maybe_unused]] checker::TSChecker *checker) +checker::Type *DebuggerStatement::Check(checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } -checker::Type *DebuggerStatement::Check([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *DebuggerStatement::Check(checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ir/statements/debuggerStatement.h b/ir/statements/debuggerStatement.h index d9858dbfd..792af73b9 100644 --- a/ir/statements/debuggerStatement.h +++ b/ir/statements/debuggerStatement.h @@ -26,9 +26,10 @@ public: void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; - void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + void Compile(compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; + checker::Type *Check(checker::TSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; private: }; diff --git a/ir/statements/doWhileStatement.cpp b/ir/statements/doWhileStatement.cpp index d7a875423..4e39a23ba 100644 --- a/ir/statements/doWhileStatement.cpp +++ b/ir/statements/doWhileStatement.cpp @@ -15,14 +15,9 @@ #include "doWhileStatement.h" -#include "binder/scope.h" -#include "compiler/base/condition.h" -#include "compiler/core/labelTarget.h" -#include "compiler/core/pandagen.h" -#include "compiler/core/ETSGen.h" #include "checker/TSchecker.h" -#include "ir/astDump.h" -#include "ir/expression.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" namespace panda::es2panda::ir { void DoWhileStatement::TransformChildren(const NodeTransformer &cb) @@ -42,55 +37,23 @@ void DoWhileStatement::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "DoWhileStatement"}, {"body", body_}, {"test", test_}}); } -template -void CompileImpl(const DoWhileStatement *self, [[maybe_unused]] CodeGen *cg) +void DoWhileStatement::Compile(compiler::PandaGen *pg) const { - auto *start_label = cg->AllocLabel(); - compiler::LabelTarget label_target(cg); - - cg->SetLabel(self, start_label); - - { - compiler::LocalRegScope reg_scope(cg, self->Scope()); - compiler::LabelContext label_ctx(cg, label_target); - self->Body()->Compile(cg); - } - - cg->SetLabel(self, label_target.ContinueTarget()); - compiler::Condition::Compile(cg, self->Test(), label_target.BreakTarget()); - - cg->Branch(self, start_label); - cg->SetLabel(self, label_target.BreakTarget()); + pg->GetAstCompiler()->Compile(this); } -void DoWhileStatement::Compile([[maybe_unused]] compiler::PandaGen *pg) const +void DoWhileStatement::Compile(compiler::ETSGen *etsg) const { - CompileImpl(this, pg); + etsg->GetAstCompiler()->Compile(this); } -void DoWhileStatement::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +checker::Type *DoWhileStatement::Check(checker::TSChecker *checker) { - CompileImpl(this, etsg); + return checker->GetAnalyzer()->Check(this); } -checker::Type *DoWhileStatement::Check([[maybe_unused]] checker::TSChecker *checker) +checker::Type *DoWhileStatement::Check(checker::ETSChecker *checker) { - checker::ScopeContext scope_ctx(checker, Scope()); - - checker::Type *test_type = Test()->Check(checker); - checker->CheckTruthinessOfType(test_type, Test()->Start()); - Body()->Check(checker); - - return nullptr; -} - -checker::Type *DoWhileStatement::Check([[maybe_unused]] checker::ETSChecker *checker) -{ - checker::ScopeContext scope_ctx(checker, Scope()); - - checker->CheckTruthinessOfType(Test()); - Body()->Check(checker); - - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ir/statements/doWhileStatement.h b/ir/statements/doWhileStatement.h index 58cf43cfc..ee5fef663 100644 --- a/ir/statements/doWhileStatement.h +++ b/ir/statements/doWhileStatement.h @@ -62,10 +62,10 @@ 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([[maybe_unused]] compiler::ETSGen *etsg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + void Compile(compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; + checker::Type *Check(checker::TSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; private: Statement *body_; -- Gitee