From a6afd2c9966d1da5e858bd04c2a2927072614e53 Mon Sep 17 00:00:00 2001 From: Csaba Hurton Date: Thu, 12 Oct 2023 12:09:49 +0300 Subject: [PATCH] [eTS] 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 Signed-off-by: Csaba Hurton --- checker/ETSAnalyzer.cpp | 203 +++++++++++++++--- checker/SemanticAnalyzer.h | 146 +++++++++++++ checker/TSAnalyzer.cpp | 72 ++++--- compiler/core/ASTCompiler.h | 146 +++++++++++++ compiler/core/ETSCompiler.cpp | 136 ++++++++++-- compiler/core/JSCompiler.cpp | 39 +--- ir/base/tsSignatureDeclaration.cpp | 62 ++---- ir/base/tsSignatureDeclaration.h | 13 +- ir/ets/etsClassLiteral.cpp | 44 ++-- ir/ets/etsClassLiteral.h | 20 +- ir/ets/etsFunctionType.cpp | 82 ++----- ir/ets/etsFunctionType.h | 14 +- ir/ets/etsLaunchExpression.cpp | 65 +----- 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 | 36 ++-- .../etsNewMultiDimArrayInstanceExpression.h | 16 +- ir/ets/etsPackageDeclaration.cpp | 20 +- ir/ets/etsPackageDeclaration.h | 8 +- ir/statements/tryStatement.h | 2 +- 23 files changed, 839 insertions(+), 513 deletions(-) diff --git a/checker/ETSAnalyzer.cpp b/checker/ETSAnalyzer.cpp index 2e05e528f..7483849a3 100644 --- a/checker/ETSAnalyzer.cpp +++ b/checker/ETSAnalyzer.cpp @@ -16,15 +16,9 @@ #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" -#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 { @@ -177,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); // TODO(user): 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()); + binder::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->ts_type_ = 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/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..528a7c772 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 { @@ -139,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/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..cd49c3295 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 { @@ -142,57 +140,149 @@ 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)expr; - UNREACHABLE(); + 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()); } 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->Binder()->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/compiler/core/JSCompiler.cpp b/compiler/core/JSCompiler.cpp index a0b481589..af45f9136 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 { @@ -469,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/ir/base/tsSignatureDeclaration.cpp b/ir/base/tsSignatureDeclaration.cpp index e121ff54f..7b61d802e 100644 --- a/ir/base/tsSignatureDeclaration.cpp +++ b/ir/base/tsSignatureDeclaration.cpp @@ -15,13 +15,12 @@ #include "tsSignatureDeclaration.h" -#include "binder/scope.h" -#include "ir/typeNode.h" -#include "ir/astDump.h" -#include "ir/ts/tsTypeParameter.h" -#include "ir/ts/tsTypeParameterDeclaration.h" - +// #include "binder/scope.h" +#include "checker/ETSchecker.h" #include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" +#include "ir/astDump.h" namespace panda::es2panda::ir { void TSSignatureDeclaration::TransformChildren(const NodeTransformer &cb) @@ -64,50 +63,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/ir/base/tsSignatureDeclaration.h b/ir/base/tsSignatureDeclaration.h index a83caebc7..d7d2f0c9f 100644 --- a/ir/base/tsSignatureDeclaration.h +++ b/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: binder::Scope *scope_; diff --git a/ir/ets/etsClassLiteral.cpp b/ir/ets/etsClassLiteral.cpp index 3a2abcd43..709ce48e4 100644 --- a/ir/ets/etsClassLiteral.cpp +++ b/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); // TODO(user): 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/ir/ets/etsClassLiteral.h b/ir/ets/etsClassLiteral.h index cc9d4f365..e607ec466 100644 --- a/ir/ets/etsClassLiteral.h +++ b/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/ir/ets/etsFunctionType.cpp b/ir/ets/etsFunctionType.cpp index 311491a21..03b550ea5 100644 --- a/ir/ets/etsFunctionType.cpp +++ b/ir/ets/etsFunctionType.cpp @@ -15,20 +15,11 @@ #include "etsFunctionType.h" -#include "binder/scope.h" #include "checker/TSchecker.h" #include "checker/ETSchecker.h" -#include "checker/types/signature.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.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" namespace panda::es2panda::ir { void ETSFunctionType::TransformChildren(const NodeTransformer &cb) @@ -73,11 +64,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 +86,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()); - binder::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/ir/ets/etsFunctionType.h b/ir/ets/etsFunctionType.h index b0b0e646f..d82a745a5 100644 --- a/ir/ets/etsFunctionType.h +++ b/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/ir/ets/etsLaunchExpression.cpp b/ir/ets/etsLaunchExpression.cpp index fbc3336dd..6fc034f16 100644 --- a/ir/ets/etsLaunchExpression.cpp +++ b/ir/ets/etsLaunchExpression.cpp @@ -20,9 +20,7 @@ #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,71 +43,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 +void ETSLaunchExpression::Compile(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/ir/ets/etsLaunchExpression.h b/ir/ets/etsLaunchExpression.h index 9857e8517..ded2aafac 100644 --- a/ir/ets/etsLaunchExpression.h +++ b/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/ir/ets/etsNewArrayInstanceExpression.cpp b/ir/ets/etsNewArrayInstanceExpression.cpp index 9483123e2..9ed5d4304 100644 --- a/ir/ets/etsNewArrayInstanceExpression.cpp +++ b/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/ir/ets/etsNewArrayInstanceExpression.h b/ir/ets/etsNewArrayInstanceExpression.h index 22a3f89ed..c15fb4c6e 100644 --- a/ir/ets/etsNewArrayInstanceExpression.h +++ b/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/ir/ets/etsNewClassInstanceExpression.cpp b/ir/ets/etsNewClassInstanceExpression.cpp index 60d66c48d..a2a73bcbf 100644 --- a/ir/ets/etsNewClassInstanceExpression.cpp +++ b/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->Binder()->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/ir/ets/etsNewClassInstanceExpression.h b/ir/ets/etsNewClassInstanceExpression.h index 739368683..6d5da31bc 100644 --- a/ir/ets/etsNewClassInstanceExpression.h +++ b/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/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp b/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp index d04ddd358..8006b9b7f 100644 --- a/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp +++ b/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp @@ -15,12 +15,11 @@ #include "etsNewMultiDimArrayInstanceExpression.h" -#include "binder/ETSBinder.h" -#include "ir/astDump.h" -#include "ir/typeNode.h" -#include "compiler/core/ETSGen.h" #include "checker/ETSchecker.h" -#include "checker/types/signature.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" +#include "ir/astDump.h" namespace panda::es2panda::ir { void ETSNewMultiDimArrayInstanceExpression::TransformChildren(const NodeTransformer &cb) @@ -46,29 +45,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/ir/ets/etsNewMultiDimArrayInstanceExpression.h b/ir/ets/etsNewMultiDimArrayInstanceExpression.h index 1cf38efa6..e7ecee053 100644 --- a/ir/ets/etsNewMultiDimArrayInstanceExpression.h +++ b/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/ir/ets/etsPackageDeclaration.cpp b/ir/ets/etsPackageDeclaration.cpp index cda0cbfbf..bd32531af 100644 --- a/ir/ets/etsPackageDeclaration.cpp +++ b/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/ir/ets/etsPackageDeclaration.h b/ir/ets/etsPackageDeclaration.h index 0a1b6a3eb..aff7ce5fa 100644 --- a/ir/ets/etsPackageDeclaration.h +++ b/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_; 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