From 1b13df5e85327306a4e1f4352e40cdfac36a1c16 Mon Sep 17 00:00:00 2001 From: Csaba Hurton Date: Thu, 12 Oct 2023 12:09:49 +0300 Subject: [PATCH] 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: - TSSignatureDeclaration - ETSClassLiteral - ETSFunctionType - ETSLaunchExpression - ETSNewArrayInstanceExpression - ETSNewClassInstanceExpression - ETSNewMultiDimArrayInstanceExpression - ETSPackageDeclaration Linked Internal issue: 13840 Change-Id: I576825259e2363826b58e673d9b546745d533e5a Signed-off-by: Csaba Hurton --- ets2panda/checker/ETSAnalyzer.cpp | 201 +++++++++++++++--- ets2panda/checker/TSAnalyzer.cpp | 65 ++++-- ets2panda/compiler/core/ETSCompiler.cpp | 132 ++++++++++-- ets2panda/compiler/core/JSCompiler.cpp | 27 +-- ets2panda/ir/base/tsSignatureDeclaration.cpp | 59 ++--- ets2panda/ir/base/tsSignatureDeclaration.h | 13 +- ets2panda/ir/ets/etsClassLiteral.cpp | 44 ++-- ets2panda/ir/ets/etsClassLiteral.h | 20 +- ets2panda/ir/ets/etsFunctionType.cpp | 83 ++------ ets2panda/ir/ets/etsFunctionType.h | 14 +- ets2panda/ir/ets/etsLaunchExpression.cpp | 64 +----- ets2panda/ir/ets/etsLaunchExpression.h | 21 +- .../ir/ets/etsNewArrayInstanceExpression.cpp | 38 ++-- .../ir/ets/etsNewArrayInstanceExpression.h | 19 +- .../ir/ets/etsNewClassInstanceExpression.cpp | 130 +---------- .../ir/ets/etsNewClassInstanceExpression.h | 20 +- .../etsNewMultiDimArrayInstanceExpression.cpp | 33 ++- .../etsNewMultiDimArrayInstanceExpression.h | 16 +- ets2panda/ir/ets/etsPackageDeclaration.cpp | 20 +- ets2panda/ir/ets/etsPackageDeclaration.h | 8 +- 20 files changed, 537 insertions(+), 490 deletions(-) diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 1b18db86c4a..8d39009e2f6 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/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 { @@ -179,58 +171,213 @@ checker::Type *ETSAnalyzer::Check(ir::TSPropertySignature *node) const UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSSignatureDeclaration *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSSignatureDeclaration *node) const { - (void)node; UNREACHABLE(); } // from ets folder checker::Type *ETSAnalyzer::Check(ir::ETSClassLiteral *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + checker->ThrowTypeError("Class literal is not yet supported.", expr->expr_->Start()); + + expr->expr_->Check(checker); + auto *expr_type = expr->expr_->GetType(checker); + + if (expr_type->IsETSVoidType()) { + checker->ThrowTypeError("Invalid .class reference", expr->expr_->Start()); + } + + ArenaVector type_arg_types(checker->Allocator()->Adapter()); + type_arg_types.push_back(expr_type); // NOTE: Box it if it's a primitive type + + checker::InstantiationContext ctx(checker, checker->GlobalBuiltinTypeType(), type_arg_types, expr->range_.start); + expr->SetTsType(ctx.Result()); + return expr->TsType(); } checker::Type *ETSAnalyzer::Check(ir::ETSFunctionType *node) const { - (void)node; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + checker->CreateFunctionalInterfaceForFunctionType(node); + auto *interface_type = + checker->CreateETSObjectType(node->FunctionalInterface()->Id()->Name(), node->FunctionalInterface(), + checker::ETSObjectFlags::FUNCTIONAL_INTERFACE); + interface_type->SetSuperType(checker->GlobalETSObjectType()); + + auto *invoke_func = node->FunctionalInterface()->Body()->Body()[0]->AsMethodDefinition()->Function(); + auto *signature_info = checker->Allocator()->New(checker->Allocator()); + + for (auto *it : invoke_func->Params()) { + auto *const param = it->AsETSParameterExpression(); + if (param->IsRestParameter()) { + auto *rest_ident = param->Ident(); + + ASSERT(rest_ident->Variable()); + signature_info->rest_var = rest_ident->Variable()->AsLocalVariable(); + + ASSERT(param->TypeAnnotation()); + signature_info->rest_var->SetTsType(checker->GetTypeFromTypeAnnotation(param->TypeAnnotation())); + + auto array_type = signature_info->rest_var->TsType()->AsETSArrayType(); + checker->CreateBuiltinArraySignature(array_type, array_type->Rank()); + } else { + auto *param_ident = param->Ident(); + + ASSERT(param_ident->Variable()); + varbinder::Variable *param_var = param_ident->Variable(); + + ASSERT(param->TypeAnnotation()); + param_var->SetTsType(checker->GetTypeFromTypeAnnotation(param->TypeAnnotation())); + signature_info->params.push_back(param_var->AsLocalVariable()); + ++signature_info->min_arg_count; + } + } + + invoke_func->ReturnTypeAnnotation()->Check(checker); + auto *signature = checker->Allocator()->New(signature_info, + node->ReturnType()->GetType(checker), invoke_func); + signature->SetOwnerVar(invoke_func->Id()->Variable()->AsLocalVariable()); + signature->AddSignatureFlag(checker::SignatureFlags::FUNCTIONAL_INTERFACE_SIGNATURE); + signature->SetOwner(interface_type); + + auto *func_type = checker->CreateETSFunctionType(signature); + invoke_func->SetSignature(signature); + invoke_func->Id()->Variable()->SetTsType(func_type); + interface_type->AddProperty( + invoke_func->Id()->Variable()->AsLocalVariable()); + node->FunctionalInterface()->SetTsType(interface_type); + + auto *this_var = invoke_func->Scope()->ParamScope()->Params().front(); + this_var->SetTsType(interface_type); + checker->BuildFunctionalInterfaceName(node); + + node->SetTsType(interface_type); + return interface_type; } -checker::Type *ETSAnalyzer::Check(ir::ETSImportDeclaration *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSImportDeclaration *node) const { - (void)node; UNREACHABLE(); } checker::Type *ETSAnalyzer::Check(ir::ETSLaunchExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + expr->expr_->Check(checker); + auto *const launch_promise_type = + checker->GlobalBuiltinPromiseType() + ->Instantiate(checker->Allocator(), checker->Relation(), checker->GetGlobalTypesHolder()) + ->AsETSObjectType(); + launch_promise_type->AddTypeFlag(checker::TypeFlag::GENERIC); + + // Launch expression returns a Promise type, so we need to insert the expression's type + // as type parameter for the Promise class. + + auto *expr_type = + expr->expr_->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE) && !expr->expr_->TsType()->IsETSVoidType() + ? checker->PrimitiveTypeAsETSBuiltinType(expr->expr_->TsType()) + : expr->expr_->TsType(); + checker::Substitution *substitution = checker->NewSubstitution(); + ASSERT(launch_promise_type->TypeArguments().size() == 1); + substitution->emplace(checker->GetOriginalBaseType(launch_promise_type->TypeArguments()[0]), expr_type); + + expr->SetTsType(launch_promise_type->Substitute(checker->Relation(), substitution)); + return expr->TsType(); } checker::Type *ETSAnalyzer::Check(ir::ETSNewArrayInstanceExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + + auto *element_type = expr->type_reference_->GetType(checker); + checker->ValidateArrayIndex(expr->dimension_); + + expr->SetTsType(checker->CreateETSArrayType(element_type)); + checker->CreateBuiltinArraySignature(expr->TsType()->AsETSArrayType(), 1); + return expr->TsType(); } checker::Type *ETSAnalyzer::Check(ir::ETSNewClassInstanceExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + checker::Type *callee_type = expr->GetTypeRef()->Check(checker); + + if (!callee_type->IsETSObjectType()) { + checker->ThrowTypeError("This expression is not constructible.", expr->Start()); + } + + auto *callee_obj = callee_type->AsETSObjectType(); + expr->SetTsType(callee_obj); + + if (expr->ClassDefinition() != nullptr) { + if (!callee_obj->HasObjectFlag(checker::ETSObjectFlags::ABSTRACT) && callee_obj->GetDeclNode()->IsFinal()) { + checker->ThrowTypeError({"Class ", callee_obj->Name(), " cannot be both 'abstract' and 'final'."}, + callee_obj->GetDeclNode()->Start()); + } + + bool from_interface = callee_obj->HasObjectFlag(checker::ETSObjectFlags::INTERFACE); + auto *class_type = checker->BuildAnonymousClassProperties( + expr->ClassDefinition(), from_interface ? checker->GlobalETSObjectType() : callee_obj); + if (from_interface) { + class_type->AddInterface(callee_obj); + callee_obj = checker->GlobalETSObjectType(); + } + expr->ClassDefinition()->SetTsType(class_type); + checker->CheckClassDefinition(expr->ClassDefinition()); + checker->CheckInnerClassMembers(class_type); + expr->SetTsType(class_type); + } else if (callee_obj->HasObjectFlag(checker::ETSObjectFlags::ABSTRACT)) { + checker->ThrowTypeError({callee_obj->Name(), " is abstract therefore cannot be instantiated."}, expr->Start()); + } + + if (callee_type->IsETSDynamicType() && !callee_type->AsETSDynamicType()->HasDecl()) { + auto lang = callee_type->AsETSDynamicType()->Language(); + expr->signature_ = checker->ResolveDynamicCallExpression(expr->GetTypeRef(), expr->GetArguments(), lang, true); + } else { + auto *signature = checker->ResolveConstructExpression(callee_obj, expr->GetArguments(), expr->Start()); + + checker->CheckObjectLiteralArguments(signature, expr->GetArguments()); + checker->ValidateSignatureAccessibility(callee_obj, signature, expr->Start()); + + ASSERT(signature->Function() != nullptr); + + if (signature->Function()->IsThrowing() || signature->Function()->IsRethrowing()) { + checker->CheckThrowingStatements(expr); + } + + if (callee_type->IsETSDynamicType()) { + ASSERT(signature->Function()->IsDynamic()); + auto lang = callee_type->AsETSDynamicType()->Language(); + expr->signature_ = + checker->ResolveDynamicCallExpression(expr->GetTypeRef(), signature->Params(), lang, true); + } else { + ASSERT(!signature->Function()->IsDynamic()); + expr->signature_ = signature; + } + } + + return expr->TsType(); } checker::Type *ETSAnalyzer::Check(ir::ETSNewMultiDimArrayInstanceExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + auto *element_type = expr->type_reference_->GetType(checker); + + for (auto *dim : expr->dimensions_) { + checker->ValidateArrayIndex(dim); + element_type = checker->CreateETSArrayType(element_type); + } + + expr->SetTsType(element_type); + expr->signature_ = checker->CreateBuiltinArraySignature(element_type->AsETSArrayType(), expr->dimensions_.size()); + return expr->TsType(); } -checker::Type *ETSAnalyzer::Check(ir::ETSPackageDeclaration *st) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSPackageDeclaration *st) const { - (void)st; - UNREACHABLE(); + return nullptr; } checker::Type *ETSAnalyzer::Check(ir::ETSParameterExpression *expr) const diff --git a/ets2panda/checker/TSAnalyzer.cpp b/ets2panda/checker/TSAnalyzer.cpp index 6b42c2deb68..3a93fceff7e 100644 --- a/ets2panda/checker/TSAnalyzer.cpp +++ b/ets2panda/checker/TSAnalyzer.cpp @@ -134,55 +134,84 @@ checker::Type *TSAnalyzer::Check(ir::TSPropertySignature *node) const checker::Type *TSAnalyzer::Check(ir::TSSignatureDeclaration *node) const { - (void)node; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + if (node->TsType() != nullptr) { + return node->TsType(); + } + + checker::ScopeContext scope_ctx(checker, node->Scope()); + + auto *signature_info = checker->Allocator()->New(checker->Allocator()); + checker->CheckFunctionParameterDeclarations(node->Params(), signature_info); + + bool is_call_signature = (node->Kind() == ir::TSSignatureDeclaration::TSSignatureDeclarationKind::CALL_SIGNATURE); + + if (node->ReturnTypeAnnotation() == nullptr) { + if (is_call_signature) { + checker->ThrowTypeError( + "Call signature, which lacks return-type annotation, implicitly has an 'any' return type.", + node->Start()); + } + + checker->ThrowTypeError( + "Construct signature, which lacks return-type annotation, implicitly has an 'any' return type.", + node->Start()); + } + + node->return_type_annotation_->Check(checker); + checker::Type *return_type = node->return_type_annotation_->GetType(checker); + + auto *signature = checker->Allocator()->New(signature_info, return_type); + + checker::Type *placeholder_obj = nullptr; + + if (is_call_signature) { + placeholder_obj = checker->CreateObjectTypeWithCallSignature(signature); + } else { + placeholder_obj = checker->CreateObjectTypeWithConstructSignature(signature); + } + + node->SetTsType(placeholder_obj); + return placeholder_obj; } // from ets folder -checker::Type *TSAnalyzer::Check(ir::ETSClassLiteral *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSClassLiteral *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ETSFunctionType *node) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSFunctionType *node) const { - (void)node; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ETSImportDeclaration *node) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSImportDeclaration *node) const { - (void)node; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ETSLaunchExpression *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSLaunchExpression *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ETSNewArrayInstanceExpression *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSNewArrayInstanceExpression *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ETSNewClassInstanceExpression *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSNewClassInstanceExpression *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ETSNewMultiDimArrayInstanceExpression *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSNewMultiDimArrayInstanceExpression *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ETSPackageDeclaration *st) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSPackageDeclaration *st) const { - (void)st; UNREACHABLE(); } diff --git a/ets2panda/compiler/core/ETSCompiler.cpp b/ets2panda/compiler/core/ETSCompiler.cpp index 4770e12ab3c..06bf747af35 100644 --- a/ets2panda/compiler/core/ETSCompiler.cpp +++ b/ets2panda/compiler/core/ETSCompiler.cpp @@ -140,57 +140,151 @@ void ETSCompiler::Compile(const ir::TSPropertySignature *node) const UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSSignatureDeclaration *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSSignatureDeclaration *node) const { - (void)node; UNREACHABLE(); } // from ets folder void ETSCompiler::Compile(const ir::ETSClassLiteral *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + if (expr->expr_->TsType()->HasTypeFlag(checker::TypeFlag::ETS_ARRAY_OR_OBJECT)) { + expr->expr_->Compile(etsg); + etsg->GetType(expr, false); + } else { + ASSERT(expr->expr_->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)); + etsg->SetAccumulatorType(expr->expr_->TsType()); + etsg->GetType(expr, true); + } } -void ETSCompiler::Compile(const ir::ETSFunctionType *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::ETSFunctionType *node) const { - (void)node; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::ETSImportDeclaration *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::ETSImportDeclaration *node) const { - (void)node; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::ETSLaunchExpression *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::ETSLaunchExpression *expr) const { - (void)expr; - UNREACHABLE(); +#ifdef PANDA_WITH_ETS + ETSGen *etsg = GetETSGen(); + compiler::RegScope rs(etsg); + compiler::VReg callee_reg = etsg->AllocReg(); + checker::Signature *signature = expr->expr_->Signature(); + bool is_static = signature->HasSignatureFlag(checker::SignatureFlags::STATIC); + bool is_reference = signature->HasSignatureFlag(checker::SignatureFlags::TYPE); + + if (!is_reference && expr->expr_->Callee()->IsIdentifier()) { + if (!is_static) { + etsg->LoadThis(expr->expr_); + etsg->StoreAccumulator(expr, callee_reg); + } + } else if (!is_reference && expr->expr_->Callee()->IsMemberExpression()) { + if (!is_static) { + expr->expr_->Callee()->AsMemberExpression()->Object()->Compile(etsg); + etsg->StoreAccumulator(expr, callee_reg); + } + } else { + expr->expr_->Callee()->Compile(etsg); + etsg->StoreAccumulator(expr, callee_reg); + } + + if (is_static) { + etsg->LaunchStatic(expr, signature, expr->expr_->Arguments()); + } else if (signature->HasSignatureFlag(checker::SignatureFlags::PRIVATE)) { + etsg->LaunchThisStatic(expr, callee_reg, signature, expr->expr_->Arguments()); + } else { + etsg->LaunchThisVirtual(expr, callee_reg, signature, expr->expr_->Arguments()); + } + + etsg->SetAccumulatorType(expr->TsType()); +#endif // PANDA_WITH_ETS } void ETSCompiler::Compile(const ir::ETSNewArrayInstanceExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + compiler::RegScope rs(etsg); + compiler::TargetTypeContext ttctx(etsg, etsg->Checker()->GlobalIntType()); + + expr->dimension_->Compile(etsg); + + compiler::VReg arr = etsg->AllocReg(); + compiler::VReg dim = etsg->AllocReg(); + etsg->ApplyConversionAndStoreAccumulator(expr, dim, expr->dimension_->TsType()); + etsg->NewArray(expr, arr, dim, expr->TsType()); + etsg->SetVRegType(arr, expr->TsType()); + etsg->LoadAccumulator(expr, arr); +} + +static void CreateDynamicObject(const ir::AstNode *node, compiler::ETSGen *etsg, compiler::VReg &obj_reg, + ir::Expression *name, checker::Signature *signature, + const ArenaVector &arguments) +{ + auto qname_reg = etsg->AllocReg(); + + std::vector parts; + + while (name->IsTSQualifiedName()) { + auto *qname = name->AsTSQualifiedName(); + name = qname->Left(); + parts.push_back(qname->Right()->AsIdentifier()->Name()); + } + + auto *var = name->AsIdentifier()->Variable(); + auto *data = etsg->VarBinder()->DynamicImportDataForVar(var); + if (data != nullptr) { + auto *import = data->import; + auto *specifier = data->specifier; + ASSERT(import->Language().IsDynamic()); + etsg->LoadAccumulatorDynamicModule(node, import); + if (specifier->IsImportSpecifier()) { + parts.push_back(specifier->AsImportSpecifier()->Imported()->Name()); + } + } else { + name->Compile(etsg); + } + + etsg->StoreAccumulator(node, obj_reg); + + std::stringstream ss; + std::for_each(parts.rbegin(), parts.rend(), [&ss](util::StringView sv) { ss << "." << sv; }); + + etsg->LoadAccumulatorString(node, util::UString(ss.str(), etsg->Allocator()).View()); + etsg->StoreAccumulator(node, qname_reg); + + etsg->CallDynamic(node, obj_reg, qname_reg, signature, arguments); } void ETSCompiler::Compile(const ir::ETSNewClassInstanceExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + if (expr->TsType()->IsETSDynamicType()) { + auto obj_reg = etsg->AllocReg(); + auto *name = expr->GetTypeRef()->AsETSTypeReference()->Part()->Name(); + CreateDynamicObject(expr, etsg, obj_reg, name, expr->signature_, expr->GetArguments()); + } else { + etsg->InitObject(expr, expr->signature_, expr->GetArguments()); + } + + if (expr->GetBoxingUnboxingFlags() == ir::BoxingUnboxingFlags::NONE) { + etsg->SetAccumulatorType(expr->TsType()); + } } void ETSCompiler::Compile(const ir::ETSNewMultiDimArrayInstanceExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + etsg->InitObject(expr, expr->signature_, expr->dimensions_); + etsg->SetAccumulatorType(expr->TsType()); } -void ETSCompiler::Compile(const ir::ETSPackageDeclaration *st) const +void ETSCompiler::Compile([[maybe_unused]] const ir::ETSPackageDeclaration *st) const { - (void)st; UNREACHABLE(); } diff --git a/ets2panda/compiler/core/JSCompiler.cpp b/ets2panda/compiler/core/JSCompiler.cpp index 23fc28f983e..2dcf27bc845 100644 --- a/ets2panda/compiler/core/JSCompiler.cpp +++ b/ets2panda/compiler/core/JSCompiler.cpp @@ -461,57 +461,48 @@ void JSCompiler::Compile(const ir::TSPropertySignature *node) const UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSSignatureDeclaration *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSSignatureDeclaration *node) const { - (void)node; UNREACHABLE(); } // from ets folder -void JSCompiler::Compile(const ir::ETSClassLiteral *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::ETSClassLiteral *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::ETSFunctionType *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::ETSFunctionType *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::ETSImportDeclaration *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::ETSImportDeclaration *node) const { - (void)node; UNREACHABLE(); } -void JSCompiler::Compile(const ir::ETSLaunchExpression *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::ETSLaunchExpression *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::ETSNewArrayInstanceExpression *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::ETSNewArrayInstanceExpression *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::ETSNewClassInstanceExpression *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::ETSNewClassInstanceExpression *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::ETSNewMultiDimArrayInstanceExpression *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::ETSNewMultiDimArrayInstanceExpression *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::ETSPackageDeclaration *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::ETSPackageDeclaration *expr) const { - (void)expr; UNREACHABLE(); } diff --git a/ets2panda/ir/base/tsSignatureDeclaration.cpp b/ets2panda/ir/base/tsSignatureDeclaration.cpp index 734c4613f9c..306dccd59ca 100644 --- a/ets2panda/ir/base/tsSignatureDeclaration.cpp +++ b/ets2panda/ir/base/tsSignatureDeclaration.cpp @@ -16,12 +16,10 @@ #include "tsSignatureDeclaration.h" #include "varbinder/scope.h" -#include "ir/typeNode.h" -#include "ir/astDump.h" -#include "ir/ts/tsTypeParameter.h" -#include "ir/ts/tsTypeParameterDeclaration.h" - +#include "checker/ETSchecker.h" #include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" namespace panda::es2panda::ir { void TSSignatureDeclaration::TransformChildren(const NodeTransformer &cb) @@ -64,50 +62,23 @@ void TSSignatureDeclaration::Dump(ir::AstDumper *dumper) const {"returnType", AstDumper::Optional(return_type_annotation_)}}); } -void TSSignatureDeclaration::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} - -checker::Type *TSSignatureDeclaration::Check([[maybe_unused]] checker::TSChecker *checker) +void TSSignatureDeclaration::Compile(compiler::PandaGen *pg) const { - if (TsType() != nullptr) { - return TsType(); - } - - checker::ScopeContext scope_ctx(checker, scope_); - - auto *signature_info = checker->Allocator()->New(checker->Allocator()); - checker->CheckFunctionParameterDeclarations(params_, signature_info); - - bool is_call_signature = (Kind() == ir::TSSignatureDeclaration::TSSignatureDeclarationKind::CALL_SIGNATURE); - - if (return_type_annotation_ == nullptr) { - if (is_call_signature) { - checker->ThrowTypeError( - "Call signature, which lacks return-type annotation, implicitly has an 'any' return type.", Start()); - } - - checker->ThrowTypeError( - "Construct signature, which lacks return-type annotation, implicitly has an 'any' return type.", Start()); - } - - return_type_annotation_->Check(checker); - checker::Type *return_type = return_type_annotation_->GetType(checker); - - auto *signature = checker->Allocator()->New(signature_info, return_type); - - checker::Type *placeholder_obj = nullptr; + pg->GetAstCompiler()->Compile(this); +} - if (is_call_signature) { - placeholder_obj = checker->CreateObjectTypeWithCallSignature(signature); - } else { - placeholder_obj = checker->CreateObjectTypeWithConstructSignature(signature); - } +void TSSignatureDeclaration::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} - SetTsType(placeholder_obj); - return placeholder_obj; +checker::Type *TSSignatureDeclaration::Check(checker::TSChecker *checker) +{ + return checker->GetAnalyzer()->Check(this); } -checker::Type *TSSignatureDeclaration::Check([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *TSSignatureDeclaration::Check(checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/base/tsSignatureDeclaration.h b/ets2panda/ir/base/tsSignatureDeclaration.h index bd89af7fa3b..5df54c35554 100644 --- a/ets2panda/ir/base/tsSignatureDeclaration.h +++ b/ets2panda/ir/base/tsSignatureDeclaration.h @@ -18,6 +18,10 @@ #include "ir/statement.h" +namespace panda::es2panda::checker { +class TSAnalyzer; +} // namespace panda::es2panda::checker + namespace panda::es2panda::ir { class TSTypeParameterDeclaration; @@ -36,6 +40,8 @@ public: return_type_annotation_(return_type_annotation) { } + // TODO (csabahurton): friend relationship can be removed once there are getters for private fields + friend class checker::TSAnalyzer; bool IsScopeBearer() const override { @@ -70,9 +76,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: varbinder::Scope *scope_; diff --git a/ets2panda/ir/ets/etsClassLiteral.cpp b/ets2panda/ir/ets/etsClassLiteral.cpp index 4b8673ebdb5..cf48fe3f2e0 100644 --- a/ets2panda/ir/ets/etsClassLiteral.cpp +++ b/ets2panda/ir/ets/etsClassLiteral.cpp @@ -15,12 +15,10 @@ #include "etsClassLiteral.h" -#include "ir/astNode.h" -#include "ir/astDump.h" -#include "ir/typeNode.h" #include "checker/TSchecker.h" -#include "checker/ets/typeRelationContext.h" #include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" +#include "ir/astDump.h" namespace panda::es2panda::ir { void ETSClassLiteral::TransformChildren(const NodeTransformer &cb) @@ -38,42 +36,24 @@ void ETSClassLiteral::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "ETSClassLiteral"}}); } -void ETSClassLiteral::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} - -void ETSClassLiteral::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +void ETSClassLiteral::Compile(compiler::PandaGen *pg) const { - if (expr_->TsType()->HasTypeFlag(checker::TypeFlag::ETS_ARRAY_OR_OBJECT)) { - expr_->Compile(etsg); - etsg->GetType(this, false); - } else { - ASSERT(expr_->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)); - etsg->SetAccumulatorType(expr_->TsType()); - etsg->GetType(this, true); - } + pg->GetAstCompiler()->Compile(this); } -checker::Type *ETSClassLiteral::Check([[maybe_unused]] checker::TSChecker *checker) +void ETSClassLiteral::Compile(compiler::ETSGen *etsg) const { - return nullptr; + etsg->GetAstCompiler()->Compile(this); } -checker::Type *ETSClassLiteral::Check([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *ETSClassLiteral::Check(checker::TSChecker *checker) { - checker->ThrowTypeError("Class literal is not yet supported.", expr_->Start()); - - expr_->Check(checker); - auto *expr_type = expr_->GetType(checker); - - if (expr_type->IsETSVoidType()) { - checker->ThrowTypeError("Invalid .class reference", expr_->Start()); - } - - ArenaVector type_arg_types(checker->Allocator()->Adapter()); - type_arg_types.push_back(expr_type); // NOTE: Box it if it's a primitive type + return checker->GetAnalyzer()->Check(this); +} - checker::InstantiationContext ctx(checker, checker->GlobalBuiltinTypeType(), type_arg_types, range_.start); - SetTsType(ctx.Result()); - return TsType(); +checker::Type *ETSClassLiteral::Check(checker::ETSChecker *checker) +{ + return checker->GetAnalyzer()->Check(this); } // NOLINTNEXTLINE(google-default-arguments) diff --git a/ets2panda/ir/ets/etsClassLiteral.h b/ets2panda/ir/ets/etsClassLiteral.h index af4a875648c..6311c263200 100644 --- a/ets2panda/ir/ets/etsClassLiteral.h +++ b/ets2panda/ir/ets/etsClassLiteral.h @@ -18,6 +18,14 @@ #include "ir/expression.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 ETSClassLiteral : public Expression { @@ -33,13 +41,17 @@ public: // NOLINTNEXTLINE(google-default-arguments) [[nodiscard]] Expression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + // TODO (csabahurton): these friend relationships can be removed once there are getters for private fields + friend class checker::ETSAnalyzer; + friend class compiler::ETSCompiler; + 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: ir::TypeNode *expr_; diff --git a/ets2panda/ir/ets/etsFunctionType.cpp b/ets2panda/ir/ets/etsFunctionType.cpp index c4b962e10aa..20bd1e9350a 100644 --- a/ets2panda/ir/ets/etsFunctionType.cpp +++ b/ets2panda/ir/ets/etsFunctionType.cpp @@ -18,17 +18,9 @@ #include "varbinder/scope.h" #include "checker/TSchecker.h" #include "checker/ETSchecker.h" -#include "checker/types/signature.h" -#include "ir/astDump.h" -#include "ir/base/spreadElement.h" -#include "ir/base/methodDefinition.h" -#include "ir/base/scriptFunction.h" -#include "ir/expressions/identifier.h" -#include "ir/ts/tsTypeParameter.h" -#include "ir/ts/tsInterfaceDeclaration.h" -#include "ir/ts/tsInterfaceBody.h" -#include "ir/ts/tsTypeParameterDeclaration.h" -#include "ir/ets/etsParameterExpression.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" +// #include "ir/astDump.h" namespace panda::es2panda::ir { void ETSFunctionType::TransformChildren(const NodeTransformer &cb) @@ -73,11 +65,19 @@ void ETSFunctionType::Dump(ir::AstDumper *dumper) const } } -void ETSFunctionType::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void ETSFunctionType::Compile(compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} -checker::Type *ETSFunctionType::Check([[maybe_unused]] checker::TSChecker *checker) +void ETSFunctionType::Compile(compiler::ETSGen *etsg) const { - return nullptr; + etsg->GetAstCompiler()->Compile(this); +} + +checker::Type *ETSFunctionType::Check(checker::TSChecker *checker) +{ + return checker->GetAnalyzer()->Check(this); } checker::Type *ETSFunctionType::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -87,60 +87,7 @@ checker::Type *ETSFunctionType::GetType([[maybe_unused]] checker::TSChecker *che checker::Type *ETSFunctionType::Check(checker::ETSChecker *checker) { - checker->CreateFunctionalInterfaceForFunctionType(this); - auto *interface_type = checker->CreateETSObjectType(functional_interface_->Id()->Name(), functional_interface_, - checker::ETSObjectFlags::FUNCTIONAL_INTERFACE); - interface_type->SetSuperType(checker->GlobalETSObjectType()); - - auto *invoke_func = functional_interface_->Body()->Body()[0]->AsMethodDefinition()->Function(); - auto *signature_info = checker->Allocator()->New(checker->Allocator()); - - for (auto *it : invoke_func->Params()) { - auto *const param = it->AsETSParameterExpression(); - if (param->IsRestParameter()) { - auto *rest_ident = param->Ident(); - - ASSERT(rest_ident->Variable()); - signature_info->rest_var = rest_ident->Variable()->AsLocalVariable(); - - ASSERT(param->TypeAnnotation()); - signature_info->rest_var->SetTsType(checker->GetTypeFromTypeAnnotation(param->TypeAnnotation())); - - auto array_type = signature_info->rest_var->TsType()->AsETSArrayType(); - checker->CreateBuiltinArraySignature(array_type, array_type->Rank()); - } else { - auto *param_ident = param->Ident(); - - ASSERT(param_ident->Variable()); - varbinder::Variable *param_var = param_ident->Variable(); - - ASSERT(param->TypeAnnotation()); - param_var->SetTsType(checker->GetTypeFromTypeAnnotation(param->TypeAnnotation())); - signature_info->params.push_back(param_var->AsLocalVariable()); - ++signature_info->min_arg_count; - } - } - - invoke_func->ReturnTypeAnnotation()->Check(checker); - auto *signature = - checker->Allocator()->New(signature_info, return_type_->GetType(checker), invoke_func); - signature->SetOwnerVar(invoke_func->Id()->Variable()->AsLocalVariable()); - signature->AddSignatureFlag(checker::SignatureFlags::FUNCTIONAL_INTERFACE_SIGNATURE); - signature->SetOwner(interface_type); - - auto *func_type = checker->CreateETSFunctionType(signature); - invoke_func->SetSignature(signature); - invoke_func->Id()->Variable()->SetTsType(func_type); - interface_type->AddProperty( - invoke_func->Id()->Variable()->AsLocalVariable()); - functional_interface_->SetTsType(interface_type); - - auto *this_var = invoke_func->Scope()->ParamScope()->Params().front(); - this_var->SetTsType(interface_type); - checker->BuildFunctionalInterfaceName(this); - - ts_type_ = interface_type; - return interface_type; + return checker->GetAnalyzer()->Check(this); } checker::Type *ETSFunctionType::GetType(checker::ETSChecker *checker) diff --git a/ets2panda/ir/ets/etsFunctionType.h b/ets2panda/ir/ets/etsFunctionType.h index ca4cfcf2c7d..3a922a4196e 100644 --- a/ets2panda/ir/ets/etsFunctionType.h +++ b/ets2panda/ir/ets/etsFunctionType.h @@ -18,6 +18,10 @@ #include "ir/typeNode.h" +namespace panda::es2panda::checker { +class ETSAnalyzer; +} // namespace panda::es2panda::checker + namespace panda::es2panda::ir { class TSTypeParameterDeclaration; @@ -35,6 +39,9 @@ public: { } + // TODO (csabahurton): friend relationship can be removed once there are getters for private fields + friend class checker::ETSAnalyzer; + bool IsScopeBearer() const override { return true; @@ -88,10 +95,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; - 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/ets2panda/ir/ets/etsLaunchExpression.cpp b/ets2panda/ir/ets/etsLaunchExpression.cpp index 44976cdb5f7..0b8ac25d07b 100644 --- a/ets2panda/ir/ets/etsLaunchExpression.cpp +++ b/ets2panda/ir/ets/etsLaunchExpression.cpp @@ -19,10 +19,6 @@ #include "compiler/core/ETSGen.h" #include "checker/ETSchecker.h" #include "checker/TSchecker.h" -#include "ir/astDump.h" -#include "ir/expressions/identifier.h" -#include "ir/expressions/callExpression.h" -#include "ir/expressions/memberExpression.h" namespace panda::es2panda::ir { ETSLaunchExpression::ETSLaunchExpression(CallExpression *expr) @@ -45,70 +41,26 @@ void ETSLaunchExpression::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "ETSLaunchExpression"}, {"expr", expr_}}); } -void ETSLaunchExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void ETSLaunchExpression::Compile(compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} void ETSLaunchExpression::Compile([[maybe_unused]] compiler::ETSGen *etsg) const { #ifdef PANDA_WITH_ETS - compiler::RegScope rs(etsg); - compiler::VReg callee_reg = etsg->AllocReg(); - checker::Signature *signature = expr_->Signature(); - bool is_static = signature->HasSignatureFlag(checker::SignatureFlags::STATIC); - bool is_reference = signature->HasSignatureFlag(checker::SignatureFlags::TYPE); - if (!is_reference && expr_->Callee()->IsIdentifier()) { - if (!is_static) { - etsg->LoadThis(expr_); - etsg->StoreAccumulator(this, callee_reg); - } - } else if (!is_reference && expr_->Callee()->IsMemberExpression()) { - if (!is_static) { - expr_->Callee()->AsMemberExpression()->Object()->Compile(etsg); - etsg->StoreAccumulator(this, callee_reg); - } - } else { - expr_->Callee()->Compile(etsg); - etsg->StoreAccumulator(this, callee_reg); - } - - if (is_static) { - etsg->LaunchStatic(this, signature, expr_->Arguments()); - } else if (signature->HasSignatureFlag(checker::SignatureFlags::PRIVATE)) { - etsg->LaunchThisStatic(this, callee_reg, signature, expr_->Arguments()); - } else { - etsg->LaunchThisVirtual(this, callee_reg, signature, expr_->Arguments()); - } - - etsg->SetAccumulatorType(TsType()); + etsg->GetAstCompiler()->Compile(this); #endif // PANDA_WITH_ETS } -checker::Type *ETSLaunchExpression::Check([[maybe_unused]] checker::TSChecker *checker) +checker::Type *ETSLaunchExpression::Check(checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *ETSLaunchExpression::Check(checker::ETSChecker *checker) { - expr_->Check(checker); - auto *const launch_promise_type = - checker->GlobalBuiltinPromiseType() - ->Instantiate(checker->Allocator(), checker->Relation(), checker->GetGlobalTypesHolder()) - ->AsETSObjectType(); - launch_promise_type->AddTypeFlag(checker::TypeFlag::GENERIC); - - // Launch expression returns a Promise type, so we need to insert the expression's type - // as type parameter for the Promise class. - - auto *expr_type = - expr_->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE) && !expr_->TsType()->IsETSVoidType() - ? checker->PrimitiveTypeAsETSBuiltinType(expr_->TsType()) - : expr_->TsType(); - checker::Substitution *substitution = checker->NewSubstitution(); - ASSERT(launch_promise_type->TypeArguments().size() == 1); - substitution->emplace(checker->GetOriginalBaseType(launch_promise_type->TypeArguments()[0]), expr_type); - - SetTsType(launch_promise_type->Substitute(checker->Relation(), substitution)); - return TsType(); + return checker->GetAnalyzer()->Check(this); } bool ETSLaunchExpression::IsStaticCall() const diff --git a/ets2panda/ir/ets/etsLaunchExpression.h b/ets2panda/ir/ets/etsLaunchExpression.h index db99d9e6a58..70b2b565d34 100644 --- a/ets2panda/ir/ets/etsLaunchExpression.h +++ b/ets2panda/ir/ets/etsLaunchExpression.h @@ -18,6 +18,14 @@ #include "ir/expression.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 CallExpression; @@ -32,16 +40,19 @@ public: explicit ETSLaunchExpression(CallExpression *expr); + // TODO (csabahurton): these friend relationships can be removed once there are getters for private fields + friend class checker::ETSAnalyzer; + friend class compiler::ETSCompiler; + // NOLINTNEXTLINE(google-default-arguments) [[nodiscard]] Expression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; - 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; bool IsStaticCall() const; [[nodiscard]] const CallExpression *Call() const noexcept diff --git a/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp b/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp index e837295c0ed..2e8e69edfd8 100644 --- a/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp +++ b/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp @@ -15,10 +15,12 @@ #include "etsNewArrayInstanceExpression.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/typeNode.h" -#include "compiler/core/ETSGen.h" -#include "checker/ETSchecker.h" namespace panda::es2panda::ir { void ETSNewArrayInstanceExpression::TransformChildren(const NodeTransformer &cb) @@ -39,35 +41,23 @@ void ETSNewArrayInstanceExpression::Dump(ir::AstDumper *dumper) const {{"type", "ETSNewArrayInstanceExpression"}, {"typeReference", type_reference_}, {"dimension", dimension_}}); } -void ETSNewArrayInstanceExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} -void ETSNewArrayInstanceExpression::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +void ETSNewArrayInstanceExpression::Compile(compiler::PandaGen *pg) const { - compiler::RegScope rs(etsg); - compiler::TargetTypeContext ttctx(etsg, etsg->Checker()->GlobalIntType()); - - dimension_->Compile(etsg); - - compiler::VReg arr = etsg->AllocReg(); - compiler::VReg dim = etsg->AllocReg(); - etsg->ApplyConversionAndStoreAccumulator(this, dim, dimension_->TsType()); - etsg->NewArray(this, arr, dim, TsType()); - etsg->SetVRegType(arr, TsType()); - etsg->LoadAccumulator(this, arr); + pg->GetAstCompiler()->Compile(this); } - -checker::Type *ETSNewArrayInstanceExpression::Check([[maybe_unused]] checker::TSChecker *checker) +void ETSNewArrayInstanceExpression::Compile(compiler::ETSGen *etsg) const { - return nullptr; + etsg->GetAstCompiler()->Compile(this); } -checker::Type *ETSNewArrayInstanceExpression::Check([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *ETSNewArrayInstanceExpression::Check(checker::TSChecker *checker) { - auto *element_type = type_reference_->GetType(checker); - checker->ValidateArrayIndex(dimension_); + return checker->GetAnalyzer()->Check(this); +} - SetTsType(checker->CreateETSArrayType(element_type)); - checker->CreateBuiltinArraySignature(TsType()->AsETSArrayType(), 1); - return TsType(); +checker::Type *ETSNewArrayInstanceExpression::Check(checker::ETSChecker *checker) +{ + return checker->GetAnalyzer()->Check(this); } // NOLINTNEXTLINE(google-default-arguments) diff --git a/ets2panda/ir/ets/etsNewArrayInstanceExpression.h b/ets2panda/ir/ets/etsNewArrayInstanceExpression.h index 68b5f7d1340..fabcbfa641f 100644 --- a/ets2panda/ir/ets/etsNewArrayInstanceExpression.h +++ b/ets2panda/ir/ets/etsNewArrayInstanceExpression.h @@ -18,6 +18,14 @@ #include "ir/expression.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 ETSNewArrayInstanceExpression : public Expression { @@ -34,6 +42,9 @@ public: dimension_(dimension) { } + // TODO (csabahurton): these friend relationships can be removed once there are getters for private fields + friend class checker::ETSAnalyzer; + friend class compiler::ETSCompiler; // NOLINTNEXTLINE(google-default-arguments) [[nodiscard]] Expression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; @@ -41,10 +52,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: ir::TypeNode *type_reference_; diff --git a/ets2panda/ir/ets/etsNewClassInstanceExpression.cpp b/ets2panda/ir/ets/etsNewClassInstanceExpression.cpp index 37f27e54b81..480aa03e2d7 100644 --- a/ets2panda/ir/ets/etsNewClassInstanceExpression.cpp +++ b/ets2panda/ir/ets/etsNewClassInstanceExpression.cpp @@ -16,17 +16,9 @@ #include "etsNewClassInstanceExpression.h" #include "compiler/core/ETSGen.h" -#include "ir/base/classDefinition.h" -#include "ir/base/scriptFunction.h" -#include "ir/astDump.h" -#include "ir/ets/etsTypeReference.h" -#include "ir/ets/etsTypeReferencePart.h" -#include "ir/expressions/identifier.h" -#include "ir/statements/variableDeclarator.h" -#include "ir/ts/tsQualifiedName.h" +#include "compiler/core/pandagen.h" #include "checker/TSchecker.h" -#include "checker/ETSchecker.h" -#include "checker/types/ets/types.h" +#include "ir/astDump.h" namespace panda::es2panda::ir { void ETSNewClassInstanceExpression::TransformChildren(const NodeTransformer &cb) @@ -63,125 +55,23 @@ void ETSNewClassInstanceExpression::Dump(ir::AstDumper *dumper) const {"classBody", AstDumper::Optional(class_def_)}}); } -void ETSNewClassInstanceExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} - -void ETSNewClassInstanceExpression::CreateDynamicObject(const ir::AstNode *node, compiler::ETSGen *etsg, - compiler::VReg &obj_reg, ir::Expression *name, - checker::Signature *signature, - const ArenaVector &arguments) +void ETSNewClassInstanceExpression::Compile(compiler::PandaGen *pg) const { - auto qname_reg = etsg->AllocReg(); - - std::vector parts; - - while (name->IsTSQualifiedName()) { - auto *qname = name->AsTSQualifiedName(); - name = qname->Left(); - parts.push_back(qname->Right()->AsIdentifier()->Name()); - } - - auto *var = name->AsIdentifier()->Variable(); - auto *data = etsg->VarBinder()->DynamicImportDataForVar(var); - if (data != nullptr) { - auto *import = data->import; - auto *specifier = data->specifier; - ASSERT(import->Language().IsDynamic()); - etsg->LoadAccumulatorDynamicModule(node, import); - if (specifier->IsImportSpecifier()) { - parts.push_back(specifier->AsImportSpecifier()->Imported()->Name()); - } - } else { - name->Compile(etsg); - } - - etsg->StoreAccumulator(node, obj_reg); - - std::stringstream ss; - std::for_each(parts.rbegin(), parts.rend(), [&ss](util::StringView sv) { ss << "." << sv; }); - - etsg->LoadAccumulatorString(node, util::UString(ss.str(), etsg->Allocator()).View()); - etsg->StoreAccumulator(node, qname_reg); - - etsg->CallDynamic(node, obj_reg, qname_reg, signature, arguments); + pg->GetAstCompiler()->Compile(this); } -void ETSNewClassInstanceExpression::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +void ETSNewClassInstanceExpression::Compile(compiler::ETSGen *etsg) const { - if (TsType()->IsETSDynamicType()) { - auto obj_reg = etsg->AllocReg(); - auto *name = type_reference_->AsETSTypeReference()->Part()->Name(); - CreateDynamicObject(this, etsg, obj_reg, name, signature_, arguments_); - } else { - etsg->InitObject(this, signature_, arguments_); - } - - if (GetBoxingUnboxingFlags() == ir::BoxingUnboxingFlags::NONE) { - etsg->SetAccumulatorType(TsType()); - } + etsg->GetAstCompiler()->Compile(this); } -checker::Type *ETSNewClassInstanceExpression::Check([[maybe_unused]] checker::TSChecker *checker) +checker::Type *ETSNewClassInstanceExpression::Check(checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } -checker::Type *ETSNewClassInstanceExpression::Check([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *ETSNewClassInstanceExpression::Check(checker::ETSChecker *checker) { - checker::Type *callee_type = type_reference_->Check(checker); - - if (!callee_type->IsETSObjectType()) { - checker->ThrowTypeError("This expression is not constructible.", Start()); - } - - auto *callee_obj = callee_type->AsETSObjectType(); - SetTsType(callee_obj); - - if (class_def_ != nullptr) { - if (!callee_obj->HasObjectFlag(checker::ETSObjectFlags::ABSTRACT) && callee_obj->GetDeclNode()->IsFinal()) { - checker->ThrowTypeError({"Class ", callee_obj->Name(), " cannot be both 'abstract' and 'final'."}, - callee_obj->GetDeclNode()->Start()); - } - - bool from_interface = callee_obj->HasObjectFlag(checker::ETSObjectFlags::INTERFACE); - auto *class_type = checker->BuildAnonymousClassProperties( - class_def_, from_interface ? checker->GlobalETSObjectType() : callee_obj); - if (from_interface) { - class_type->AddInterface(callee_obj); - callee_obj = checker->GlobalETSObjectType(); - } - class_def_->SetTsType(class_type); - checker->CheckClassDefinition(class_def_); - checker->CheckInnerClassMembers(class_type); - SetTsType(class_type); - } else if (callee_obj->HasObjectFlag(checker::ETSObjectFlags::ABSTRACT)) { - checker->ThrowTypeError({callee_obj->Name(), " is abstract therefore cannot be instantiated."}, Start()); - } - - if (callee_type->IsETSDynamicType() && !callee_type->AsETSDynamicType()->HasDecl()) { - auto lang = callee_type->AsETSDynamicType()->Language(); - signature_ = checker->ResolveDynamicCallExpression(type_reference_, arguments_, lang, true); - } else { - auto *signature = checker->ResolveConstructExpression(callee_obj, arguments_, Start()); - - checker->CheckObjectLiteralArguments(signature, arguments_); - checker->ValidateSignatureAccessibility(callee_obj, signature, Start()); - - ASSERT(signature->Function() != nullptr); - - if (signature->Function()->IsThrowing() || signature->Function()->IsRethrowing()) { - checker->CheckThrowingStatements(this); - } - - if (callee_type->IsETSDynamicType()) { - ASSERT(signature->Function()->IsDynamic()); - auto lang = callee_type->AsETSDynamicType()->Language(); - signature_ = checker->ResolveDynamicCallExpression(type_reference_, signature->Params(), lang, true); - } else { - ASSERT(!signature->Function()->IsDynamic()); - signature_ = signature; - } - } - - return TsType(); + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ets/etsNewClassInstanceExpression.h b/ets2panda/ir/ets/etsNewClassInstanceExpression.h index e35c911063d..ba9e65665ad 100644 --- a/ets2panda/ir/ets/etsNewClassInstanceExpression.h +++ b/ets2panda/ir/ets/etsNewClassInstanceExpression.h @@ -20,9 +20,14 @@ #include "ir/expression.h" namespace panda::es2panda::checker { +class ETSAnalyzer; class Signature; } // namespace panda::es2panda::checker +namespace panda::es2panda::compiler { +class ETSCompiler; +} // namespace panda::es2panda::compiler + namespace panda::es2panda::ir { class ClassDefinition; @@ -37,6 +42,9 @@ public: class_def_(class_definition) { } + // TODO (csabahurton): these friend relationships can be removed once there are getters for private fields + friend class checker::ETSAnalyzer; + friend class compiler::ETSCompiler; ir::ClassDefinition *ClassDefinition() { @@ -63,17 +71,13 @@ public: signature_ = signature; } - static void CreateDynamicObject(const ir::AstNode *node, compiler::ETSGen *etsg, compiler::VReg &obj_reg, - ir::Expression *name, checker::Signature *signature, - const ArenaVector &arguments); - 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: ir::Expression *type_reference_; diff --git a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp index d9b5d78eb10..9df831b864d 100644 --- a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp +++ b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp @@ -16,11 +16,9 @@ #include "etsNewMultiDimArrayInstanceExpression.h" #include "varbinder/ETSBinder.h" -#include "ir/astDump.h" -#include "ir/typeNode.h" +#include "checker/TSchecker.h" #include "compiler/core/ETSGen.h" -#include "checker/ETSchecker.h" -#include "checker/types/signature.h" +#include "compiler/core/pandagen.h" namespace panda::es2panda::ir { void ETSNewMultiDimArrayInstanceExpression::TransformChildren(const NodeTransformer &cb) @@ -46,29 +44,22 @@ void ETSNewMultiDimArrayInstanceExpression::Dump(ir::AstDumper *dumper) const {"dimensions", dimensions_}}); } -void ETSNewMultiDimArrayInstanceExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} -void ETSNewMultiDimArrayInstanceExpression::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +void ETSNewMultiDimArrayInstanceExpression::Compile(compiler::PandaGen *pg) const { - etsg->InitObject(this, signature_, dimensions_); - etsg->SetAccumulatorType(TsType()); + pg->GetAstCompiler()->Compile(this); } - -checker::Type *ETSNewMultiDimArrayInstanceExpression::Check([[maybe_unused]] checker::TSChecker *checker) +void ETSNewMultiDimArrayInstanceExpression::Compile(compiler::ETSGen *etsg) const { - return nullptr; + etsg->GetAstCompiler()->Compile(this); } -checker::Type *ETSNewMultiDimArrayInstanceExpression::Check([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *ETSNewMultiDimArrayInstanceExpression::Check(checker::TSChecker *checker) { - auto *element_type = type_reference_->GetType(checker); - - for (auto *dim : dimensions_) { - checker->ValidateArrayIndex(dim); - element_type = checker->CreateETSArrayType(element_type); - } + return checker->GetAnalyzer()->Check(this); +} - SetTsType(element_type); - signature_ = checker->CreateBuiltinArraySignature(element_type->AsETSArrayType(), dimensions_.size()); - return TsType(); +checker::Type *ETSNewMultiDimArrayInstanceExpression::Check(checker::ETSChecker *checker) +{ + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h index 1cf38efa643..e7ecee053e2 100644 --- a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h +++ b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h @@ -19,9 +19,14 @@ #include "ir/expression.h" namespace panda::es2panda::checker { +class ETSAnalyzer; class Signature; } // namespace panda::es2panda::checker +namespace panda::es2panda::compiler { +class ETSCompiler; +} // namespace panda::es2panda::compiler + namespace panda::es2panda::ir { class ETSNewMultiDimArrayInstanceExpression : public Expression { @@ -33,6 +38,9 @@ public: dimensions_(std::move(dimensions)) { } + // TODO (csabahurton): these friend relationships can be removed once there are getters for private fields + friend class checker::ETSAnalyzer; + friend class compiler::ETSCompiler; checker::Signature *Signature() { @@ -47,10 +55,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: ir::TypeNode *type_reference_; diff --git a/ets2panda/ir/ets/etsPackageDeclaration.cpp b/ets2panda/ir/ets/etsPackageDeclaration.cpp index 9ed77697fb0..1ae4b8c58a2 100644 --- a/ets2panda/ir/ets/etsPackageDeclaration.cpp +++ b/ets2panda/ir/ets/etsPackageDeclaration.cpp @@ -15,9 +15,10 @@ #include "etsPackageDeclaration.h" -#include "ir/astDump.h" #include "checker/TSchecker.h" #include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" +#include "ir/astDump.h" namespace panda::es2panda::ir { void ETSPackageDeclaration::TransformChildren(const NodeTransformer &cb) @@ -35,19 +36,22 @@ void ETSPackageDeclaration::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "ETSPackageDeclaration"}, {"name", name_}}); } -void ETSPackageDeclaration::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} -void ETSPackageDeclaration::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +void ETSPackageDeclaration::Compile(compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void ETSPackageDeclaration::Compile(compiler::ETSGen *etsg) const { - UNREACHABLE(); + etsg->GetAstCompiler()->Compile(this); } -checker::Type *ETSPackageDeclaration::Check([[maybe_unused]] checker::TSChecker *checker) +checker::Type *ETSPackageDeclaration::Check(checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } -checker::Type *ETSPackageDeclaration::Check([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *ETSPackageDeclaration::Check(checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ets/etsPackageDeclaration.h b/ets2panda/ir/ets/etsPackageDeclaration.h index 6a843313d2c..1a431dc3985 100644 --- a/ets2panda/ir/ets/etsPackageDeclaration.h +++ b/ets2panda/ir/ets/etsPackageDeclaration.h @@ -29,10 +29,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: ir::Expression *name_; -- Gitee