From 5ecc43a7f86971ce25a04fee201e69747868ab7a Mon Sep 17 00:00:00 2001 From: Csaba Hurton Date: Thu, 19 Oct 2023 14:03:32 +0200 Subject: [PATCH] [eTS] Move Compile and Check Logic from ASTNode classes AstNodes that are being moved: - nodes inside ir/expressions: - Identifier - ImportExpression - MemberExpression - NewExpression - OmittedExpression - SequenceExpression - SuperExpression - nodes inside ir/expressions/literals: - BigIntLiteral Linked Internal Issue 13840 Signed-off-by: Csaba Hurton --- checker/ETSAnalyzer.cpp | 144 ++++++++-- checker/SemanticAnalyzer.h | 146 ++++++++++ checker/TSAnalyzer.cpp | 149 +++++++++-- compiler/core/ASTCompiler.h | 146 ++++++++++ compiler/core/ETSCompiler.cpp | 199 ++++++++++++-- compiler/core/JSCompiler.cpp | 110 ++++++-- ir/expressions/identifier.cpp | 87 +----- ir/expressions/identifier.h | 8 +- ir/expressions/importExpression.cpp | 19 +- ir/expressions/importExpression.h | 7 +- ir/expressions/literals/bigIntLiteral.cpp | 21 +- ir/expressions/literals/bigIntLiteral.h | 7 +- ir/expressions/memberExpression.cpp | 308 +--------------------- ir/expressions/memberExpression.h | 11 +- ir/expressions/newExpression.cpp | 54 +--- ir/expressions/newExpression.h | 10 +- ir/expressions/omittedExpression.cpp | 22 +- ir/expressions/omittedExpression.h | 7 +- ir/expressions/sequenceExpression.cpp | 28 +- ir/expressions/sequenceExpression.h | 4 +- ir/expressions/superExpression.cpp | 29 +- ir/expressions/superExpression.h | 2 +- ir/statements/tryStatement.h | 2 +- 23 files changed, 914 insertions(+), 606 deletions(-) diff --git a/checker/ETSAnalyzer.cpp b/checker/ETSAnalyzer.cpp index 2e05e528f..55cfefa27 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 { @@ -335,25 +329,117 @@ checker::Type *ETSAnalyzer::Check(ir::FunctionExpression *expr) const checker::Type *ETSAnalyzer::Check(ir::Identifier *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + + expr->SetTsType(checker->ResolveIdentifier(expr)); + return expr->TsType(); + + if (expr->TsType() != nullptr) { + return expr->TsType(); + } + + expr->SetTsType(checker->ResolveIdentifier(expr)); + if (expr->TsType()->IsETSFunctionType()) { + for (auto *sig : expr->TsType()->AsETSFunctionType()->CallSignatures()) { + if (sig->HasSignatureFlag(checker::SignatureFlags::NEED_RETURN_TYPE)) { + sig->OwnerVar()->Declaration()->Node()->Check(checker); + } + } + } + return expr->TsType(); } -checker::Type *ETSAnalyzer::Check(ir::ImportExpression *expr) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ImportExpression *expr) const { - (void)expr; UNREACHABLE(); } checker::Type *ETSAnalyzer::Check(ir::MemberExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + if (expr->TsType() != nullptr) { + return expr->TsType(); + } + + if (expr->IsComputed()) { + expr->SetTsType(checker->CheckArrayElementAccess(expr)); + return expr->TsType(); + } + + checker::Type *const base_type = expr->Object()->Check(checker); + + if (!base_type->IsETSObjectType()) { + if (base_type->IsETSArrayType() && expr->Property()->AsIdentifier()->Name().Is("length")) { + expr->SetTsType(checker->GlobalIntType()); + return expr->TsType(); + } + + if (base_type->IsETSEnumType() || base_type->IsETSStringEnumType()) { + auto const *const enum_interface = [base_type]() -> checker::ETSEnumInterface const * { + if (base_type->IsETSEnumType()) { + return base_type->AsETSEnumType(); + } + return base_type->AsETSStringEnumType(); + }(); + + if (expr->Parent()->Type() == ir::AstNodeType::CALL_EXPRESSION && + expr->Parent()->AsCallExpression()->Callee() == expr) { + auto *const enum_method_type = + enum_interface->LookupMethod(checker, expr->Object(), expr->Property()->AsIdentifier()); + expr->SetTsType(enum_method_type); + return expr->TsType(); + } + + auto *const enum_literal_type = + enum_interface->LookupConstant(checker, expr->Object(), expr->Property()->AsIdentifier()); + expr->SetTsType(enum_literal_type); + expr->SetPropVar(enum_literal_type->GetMemberVar()); + return expr->TsType(); + } + + checker->ThrowTypeError({"Cannot access property of non-object or non-enum type"}, expr->Object()->Start()); + } + + expr->SetObjectType(base_type->AsETSObjectType()); + auto resolve_res = checker->ResolveMemberReference(expr, expr->ObjType()); + ASSERT(!resolve_res.empty()); + checker::Type *type_to_set = nullptr; + switch (resolve_res.size()) { + case 1: { + if (resolve_res[0]->Kind() == checker::ResolvedKind::PROPERTY) { + expr->SetPropVar(resolve_res[0]->Variable()->AsLocalVariable()); + checker->ValidatePropertyAccess(expr->PropVar(), expr->ObjType(), expr->Property()->Start()); + type_to_set = checker->GetTypeOfVariable(expr->PropVar()); + } else { + type_to_set = checker->GetTypeOfVariable(resolve_res[0]->Variable()); + } + break; + } + case 2: { + // ETSExtensionFuncHelperType(class_method_type, extension_method_type) + type_to_set = checker->CreateETSExtensionFuncHelperType( + checker->GetTypeOfVariable(resolve_res[1]->Variable())->AsETSFunctionType(), + checker->GetTypeOfVariable(resolve_res[0]->Variable())->AsETSFunctionType()); + break; + } + default: { + UNREACHABLE(); + } + } + expr->SetTsType(type_to_set); + if (expr->PropVar() != nullptr && expr->PropVar()->TsType() != nullptr && + expr->PropVar()->TsType()->IsETSFunctionType()) { + for (auto *sig : expr->PropVar()->TsType()->AsETSFunctionType()->CallSignatures()) { + if (sig->HasSignatureFlag(checker::SignatureFlags::NEED_RETURN_TYPE)) { + sig->OwnerVar()->Declaration()->Node()->Check(checker); + } + } + } + return expr->TsType(); } -checker::Type *ETSAnalyzer::Check(ir::NewExpression *expr) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::NewExpression *expr) const { - (void)expr; UNREACHABLE(); } @@ -363,9 +449,8 @@ checker::Type *ETSAnalyzer::Check(ir::ObjectExpression *expr) const UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::OmittedExpression *expr) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::OmittedExpression *expr) const { - (void)expr; UNREACHABLE(); } @@ -377,14 +462,26 @@ checker::Type *ETSAnalyzer::Check(ir::OpaqueTypeNode *expr) const checker::Type *ETSAnalyzer::Check(ir::SequenceExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + if (expr->TsType() != nullptr) { + return expr->TsType(); + } + + for (auto *it : expr->Sequence()) { + it->Check(checker); + } + return nullptr; } checker::Type *ETSAnalyzer::Check(ir::SuperExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + if (expr->TsType() != nullptr) { + return expr->TsType(); + } + + expr->SetTsType(checker->CheckThisOrSuperAccess(expr, checker->Context().ContainingClass()->SuperType(), "super")); + return expr->TsType(); } checker::Type *ETSAnalyzer::Check(ir::TaggedTemplateExpression *expr) const @@ -423,9 +520,8 @@ checker::Type *ETSAnalyzer::Check(ir::YieldExpression *expr) const UNREACHABLE(); } // compile methods for LITERAL EXPRESSIONS in alphabetical order -checker::Type *ETSAnalyzer::Check(ir::BigIntLiteral *expr) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::BigIntLiteral *expr) const { - (void)expr; UNREACHABLE(); } 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..482d6d5f6 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 { @@ -295,26 +290,121 @@ checker::Type *TSAnalyzer::Check(ir::FunctionExpression *expr) const checker::Type *TSAnalyzer::Check(ir::Identifier *expr) const { - (void)expr; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + if (expr->Variable() == nullptr) { + if (expr->Name().Is("undefined")) { + return checker->GlobalUndefinedType(); + } + + checker->ThrowTypeError({"Cannot find name ", expr->Name()}, expr->Start()); + } + + const binder::Decl *decl = expr->Variable()->Declaration(); + + if (decl->IsTypeAliasDecl() || decl->IsInterfaceDecl()) { + checker->ThrowTypeError({expr->Name(), " only refers to a type, but is being used as a value here."}, + expr->Start()); + } + + expr->SetTsType(checker->GetTypeOfVariable(expr->Variable())); + return expr->TsType(); } -checker::Type *TSAnalyzer::Check(ir::ImportExpression *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ImportExpression *expr) const { - (void)expr; UNREACHABLE(); } checker::Type *TSAnalyzer::Check(ir::MemberExpression *expr) const { - (void)expr; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + checker::Type *base_type = checker->CheckNonNullType(expr->Object()->Check(checker), expr->Object()->Start()); + + if (expr->IsComputed()) { + checker::Type *index_type = expr->Property()->Check(checker); + checker::Type *indexed_access_type = checker->GetPropertyTypeForIndexType(base_type, index_type); + + if (indexed_access_type != nullptr) { + return indexed_access_type; + } + + if (!index_type->HasTypeFlag(checker::TypeFlag::STRING_LIKE | checker::TypeFlag::NUMBER_LIKE)) { + checker->ThrowTypeError({"Type ", index_type, " cannot be used as index type"}, expr->Property()->Start()); + } + + if (index_type->IsNumberType()) { + checker->ThrowTypeError("No index signature with a parameter of type 'string' was found on type this type", + expr->Start()); + } + + if (index_type->IsStringType()) { + checker->ThrowTypeError("No index signature with a parameter of type 'number' was found on type this type", + expr->Start()); + } + + switch (expr->Property()->Type()) { + case ir::AstNodeType::IDENTIFIER: { + checker->ThrowTypeError( + {"Property ", expr->Property()->AsIdentifier()->Name(), " does not exist on this type."}, + expr->Property()->Start()); + } + case ir::AstNodeType::NUMBER_LITERAL: { + checker->ThrowTypeError( + {"Property ", expr->Property()->AsNumberLiteral()->Str(), " does not exist on this type."}, + expr->Property()->Start()); + } + case ir::AstNodeType::STRING_LITERAL: { + checker->ThrowTypeError( + {"Property ", expr->Property()->AsStringLiteral()->Str(), " does not exist on this type."}, + expr->Property()->Start()); + } + default: { + UNREACHABLE(); + } + } + } + + binder::Variable *prop = checker->GetPropertyOfType(base_type, expr->Property()->AsIdentifier()->Name()); + + if (prop != nullptr) { + checker::Type *prop_type = checker->GetTypeOfVariable(prop); + if (prop->HasFlag(binder::VariableFlags::READONLY)) { + prop_type->AddTypeFlag(checker::TypeFlag::READONLY); + } + + return prop_type; + } + + if (base_type->IsObjectType()) { + checker::ObjectType *obj_type = base_type->AsObjectType(); + + if (obj_type->StringIndexInfo() != nullptr) { + checker::Type *index_type = obj_type->StringIndexInfo()->GetType(); + if (obj_type->StringIndexInfo()->Readonly()) { + index_type->AddTypeFlag(checker::TypeFlag::READONLY); + } + + return index_type; + } + } + + checker->ThrowTypeError({"Property ", expr->Property()->AsIdentifier()->Name(), " does not exist on this type."}, + expr->Property()->Start()); + return nullptr; } checker::Type *TSAnalyzer::Check(ir::NewExpression *expr) const { - (void)expr; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + checker::Type *callee_type = expr->callee_->Check(checker); + + if (callee_type->IsObjectType()) { + checker::ObjectType *callee_obj = callee_type->AsObjectType(); + return checker->ResolveCallOrNewExpression(callee_obj->ConstructSignatures(), expr->Arguments(), expr->Start()); + } + + checker->ThrowTypeError("This expression is not callable.", expr->Start()); + return nullptr; } checker::Type *TSAnalyzer::Check(ir::ObjectExpression *expr) const @@ -323,10 +413,10 @@ checker::Type *TSAnalyzer::Check(ir::ObjectExpression *expr) const UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::OmittedExpression *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::OmittedExpression *expr) const { - (void)expr; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + return checker->GlobalUndefinedType(); } checker::Type *TSAnalyzer::Check(ir::OpaqueTypeNode *expr) const @@ -335,16 +425,18 @@ checker::Type *TSAnalyzer::Check(ir::OpaqueTypeNode *expr) const UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::SequenceExpression *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::SequenceExpression *expr) const { - (void)expr; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + // TODO(aszilagyi) + return checker->GlobalAnyType(); } -checker::Type *TSAnalyzer::Check(ir::SuperExpression *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::SuperExpression *expr) const { - (void)expr; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + // TODO(aszilagyi) + return checker->GlobalAnyType(); } checker::Type *TSAnalyzer::Check(ir::TaggedTemplateExpression *expr) const @@ -385,8 +477,15 @@ checker::Type *TSAnalyzer::Check(ir::YieldExpression *expr) const // compile methods for LITERAL EXPRESSIONS in alphabetical order checker::Type *TSAnalyzer::Check(ir::BigIntLiteral *expr) const { - (void)expr; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + auto search = checker->BigintLiteralMap().find(expr->Str()); + if (search != checker->BigintLiteralMap().end()) { + return search->second; + } + + auto *new_bigint_literal_type = checker->Allocator()->New(expr->Str(), false); + checker->BigintLiteralMap().insert({expr->Str(), new_bigint_literal_type}); + return new_bigint_literal_type; } checker::Type *TSAnalyzer::Check(ir::BooleanLiteral *expr) const diff --git a/compiler/core/ASTCompiler.h b/compiler/core/ASTCompiler.h index b5bd66617..03fdde033 100644 --- a/compiler/core/ASTCompiler.h +++ b/compiler/core/ASTCompiler.h @@ -17,6 +17,152 @@ #define ES2PANDA_COMPILER_CORE_ASTCOMPILER_H #include "compiler/core/dynamicContext.h" +#include "ir/opaqueTypeNode.h" +#include "ir/as/namedType.h" +#include "ir/as/prefixAssertionExpression.h" +#include "ir/base/catchClause.h" +#include "ir/base/classDefinition.h" +#include "ir/base/classProperty.h" +#include "ir/base/classStaticBlock.h" +#include "ir/base/decorator.h" +#include "ir/base/metaProperty.h" +#include "ir/base/methodDefinition.h" +#include "ir/base/property.h" +#include "ir/base/scriptFunction.h" +#include "ir/base/spreadElement.h" +#include "ir/base/templateElement.h" +#include "ir/base/tsIndexSignature.h" +#include "ir/base/tsMethodSignature.h" +#include "ir/base/tsPropertySignature.h" +#include "ir/base/tsSignatureDeclaration.h" +#include "ir/ets/etsClassLiteral.h" +#include "ir/ets/etsFunctionType.h" +#include "ir/ets/etsImportDeclaration.h" +#include "ir/ets/etsLaunchExpression.h" +#include "ir/ets/etsNewArrayInstanceExpression.h" +#include "ir/ets/etsNewClassInstanceExpression.h" +#include "ir/ets/etsNewMultiDimArrayInstanceExpression.h" +#include "ir/ets/etsPackageDeclaration.h" +#include "ir/ets/etsParameterExpression.h" +#include "ir/ets/etsPrimitiveType.h" +#include "ir/ets/etsScript.h" +#include "ir/ets/etsStructDeclaration.h" +#include "ir/ets/etsTypeReference.h" +#include "ir/ets/etsTypeReferencePart.h" +#include "ir/ets/etsWildcardType.h" +#include "ir/expressions/arrayExpression.h" +#include "ir/expressions/arrowFunctionExpression.h" +#include "ir/expressions/assignmentExpression.h" +#include "ir/expressions/awaitExpression.h" +#include "ir/expressions/binaryExpression.h" +#include "ir/expressions/callExpression.h" +#include "ir/expressions/chainExpression.h" +#include "ir/expressions/classExpression.h" +#include "ir/expressions/conditionalExpression.h" +#include "ir/expressions/directEvalExpression.h" +#include "ir/expressions/functionExpression.h" +#include "ir/expressions/identifier.h" +#include "ir/expressions/importExpression.h" +#include "ir/expressions/memberExpression.h" +#include "ir/expressions/newExpression.h" +#include "ir/expressions/objectExpression.h" +#include "ir/expressions/omittedExpression.h" +#include "ir/expressions/sequenceExpression.h" +#include "ir/expressions/superExpression.h" +#include "ir/expressions/taggedTemplateExpression.h" +#include "ir/expressions/templateLiteral.h" +#include "ir/expressions/thisExpression.h" +#include "ir/expressions/unaryExpression.h" +#include "ir/expressions/updateExpression.h" +#include "ir/expressions/yieldExpression.h" +#include "ir/expressions/literals/bigIntLiteral.h" +#include "ir/expressions/literals/booleanLiteral.h" +#include "ir/expressions/literals/charLiteral.h" +#include "ir/expressions/literals/nullLiteral.h" +#include "ir/expressions/literals/numberLiteral.h" +#include "ir/expressions/literals/regExpLiteral.h" +#include "ir/expressions/literals/stringLiteral.h" +#include "ir/module/exportAllDeclaration.h" +#include "ir/module/exportDefaultDeclaration.h" +#include "ir/module/exportNamedDeclaration.h" +#include "ir/module/exportSpecifier.h" +#include "ir/module/importDeclaration.h" +#include "ir/module/importDefaultSpecifier.h" +#include "ir/module/importNamespaceSpecifier.h" +#include "ir/module/importSpecifier.h" +#include "ir/statements/assertStatement.h" +#include "ir/statements/blockStatement.h" +#include "ir/statements/breakStatement.h" +#include "ir/statements/classDeclaration.h" +#include "ir/statements/continueStatement.h" +#include "ir/statements/debuggerStatement.h" +#include "ir/statements/doWhileStatement.h" +#include "ir/statements/emptyStatement.h" +#include "ir/statements/expressionStatement.h" +#include "ir/statements/forInStatement.h" +#include "ir/statements/forOfStatement.h" +#include "ir/statements/forUpdateStatement.h" +#include "ir/statements/functionDeclaration.h" +#include "ir/statements/ifStatement.h" +#include "ir/statements/labelledStatement.h" +#include "ir/statements/returnStatement.h" +#include "ir/statements/switchCaseStatement.h" +#include "ir/statements/switchStatement.h" +#include "ir/statements/throwStatement.h" +#include "ir/statements/tryStatement.h" +#include "ir/statements/variableDeclaration.h" +#include "ir/statements/variableDeclarator.h" +#include "ir/statements/whileStatement.h" +#include "ir/ts/tsAnyKeyword.h" +#include "ir/ts/tsArrayType.h" +#include "ir/ts/tsAsExpression.h" +#include "ir/ts/tsBigintKeyword.h" +#include "ir/ts/tsBooleanKeyword.h" +#include "ir/ts/tsClassImplements.h" +#include "ir/ts/tsConditionalType.h" +#include "ir/ts/tsConstructorType.h" +#include "ir/ts/tsEnumDeclaration.h" +#include "ir/ts/tsEnumMember.h" +#include "ir/ts/tsExternalModuleReference.h" +#include "ir/ts/tsFunctionType.h" +#include "ir/ts/tsImportEqualsDeclaration.h" +#include "ir/ts/tsImportType.h" +#include "ir/ts/tsIndexedAccessType.h" +#include "ir/ts/tsInferType.h" +#include "ir/ts/tsInterfaceBody.h" +#include "ir/ts/tsInterfaceDeclaration.h" +#include "ir/ts/tsInterfaceHeritage.h" +#include "ir/ts/tsIntersectionType.h" +#include "ir/ts/tsLiteralType.h" +#include "ir/ts/tsMappedType.h" +#include "ir/ts/tsModuleBlock.h" +#include "ir/ts/tsModuleDeclaration.h" +#include "ir/ts/tsNamedTupleMember.h" +#include "ir/ts/tsNeverKeyword.h" +#include "ir/ts/tsNonNullExpression.h" +#include "ir/ts/tsNullKeyword.h" +#include "ir/ts/tsNumberKeyword.h" +#include "ir/ts/tsObjectKeyword.h" +#include "ir/ts/tsParameterProperty.h" +#include "ir/ts/tsParenthesizedType.h" +#include "ir/ts/tsQualifiedName.h" +#include "ir/ts/tsStringKeyword.h" +#include "ir/ts/tsThisType.h" +#include "ir/ts/tsTupleType.h" +#include "ir/ts/tsTypeAliasDeclaration.h" +#include "ir/ts/tsTypeAssertion.h" +#include "ir/ts/tsTypeLiteral.h" +#include "ir/ts/tsTypeOperator.h" +#include "ir/ts/tsTypeParameterDeclaration.h" +#include "ir/ts/tsTypeParameter.h" +#include "ir/ts/tsTypeParameterInstantiation.h" +#include "ir/ts/tsTypePredicate.h" +#include "ir/ts/tsTypeQuery.h" +#include "ir/ts/tsTypeReference.h" +#include "ir/ts/tsUndefinedKeyword.h" +#include "ir/ts/tsUnionType.h" +#include "ir/ts/tsUnknownKeyword.h" +#include "ir/ts/tsVoidKeyword.h" namespace panda::es2panda::compiler { class CodeGen; diff --git a/compiler/core/ETSCompiler.cpp b/compiler/core/ETSCompiler.cpp index c7f91c0d7..992cbf008 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 { @@ -300,25 +298,184 @@ void ETSCompiler::Compile(const ir::FunctionExpression *expr) const void ETSCompiler::Compile(const ir::Identifier *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + auto lambda = etsg->Binder()->LambdaObjects().find(expr); + if (lambda != etsg->Binder()->LambdaObjects().end()) { + etsg->CreateLambdaObjectFromIdentReference(expr, lambda->second.first); + return; + } + + auto ttctx = compiler::TargetTypeContext(etsg, expr->TsType()); + + ASSERT(expr->Variable() != nullptr); + if (!expr->Variable()->HasFlag(binder::VariableFlags::TYPE_ALIAS)) { + etsg->LoadVar(expr, expr->Variable()); + } else { + etsg->LoadVar(expr, expr->TsType()->Variable()); + } } -void ETSCompiler::Compile(const ir::ImportExpression *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::ImportExpression *expr) const { - (void)expr; UNREACHABLE(); } void ETSCompiler::Compile(const ir::MemberExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + auto lambda = etsg->Binder()->LambdaObjects().find(expr); + if (lambda != etsg->Binder()->LambdaObjects().end()) { + etsg->CreateLambdaObjectFromMemberReference(expr, expr->object_, lambda->second.first); + return; + } + + compiler::RegScope rs(etsg); + + if (expr->IsComputed()) { + auto ottctx = compiler::TargetTypeContext(etsg, expr->Object()->TsType()); + expr->Object()->Compile(etsg); + + if (etsg->GetAccumulatorType()->IsETSNullType()) { + if (expr->IsOptional()) { + return; + } + + etsg->EmitNullPointerException(expr); + return; + } + + // Helper function to avoid branching in non optional cases + auto compile_and_load_elements = [expr, etsg]() { + compiler::VReg obj_reg = etsg->AllocReg(); + etsg->StoreAccumulator(expr, obj_reg); + auto pttctx = compiler::TargetTypeContext(etsg, expr->Property()->TsType()); + expr->Property()->Compile(etsg); + etsg->ApplyConversion(expr->Property()); + + auto ttctx = compiler::TargetTypeContext(etsg, expr->TsType()); + + if (expr->TsType()->IsETSDynamicType()) { + auto lang = expr->TsType()->AsETSDynamicType()->Language(); + etsg->LoadElementDynamic(expr, obj_reg, lang); + } else { + etsg->LoadArrayElement(expr, obj_reg); + } + + etsg->ApplyConversion(expr); + }; + + if (expr->IsOptional()) { + compiler::Label *end_label = etsg->AllocLabel(); + etsg->BranchIfNull(expr, end_label); + compile_and_load_elements(); + etsg->SetLabel(expr, end_label); + } else { + compile_and_load_elements(); + } + + return; + } + + auto &prop_name = expr->Property()->AsIdentifier()->Name(); + auto const *const object_type = expr->Object()->TsType(); + + if (object_type->IsETSArrayType() && prop_name.Is("length")) { + auto ottctx = compiler::TargetTypeContext(etsg, object_type); + expr->Object()->Compile(etsg); + compiler::VReg obj_reg = etsg->AllocReg(); + etsg->StoreAccumulator(expr, obj_reg); + + auto ttctx = compiler::TargetTypeContext(etsg, expr->TsType()); + etsg->LoadArrayLength(expr, obj_reg); + etsg->ApplyConversion(expr); + return; + } + + if (object_type->IsETSEnumType() || object_type->IsETSStringEnumType()) { + auto const *const enum_interface = [object_type, expr]() -> checker::ETSEnumInterface const * { + if (object_type->IsETSEnumType()) { + return expr->TsType()->AsETSEnumType(); + } + return expr->TsType()->AsETSStringEnumType(); + }(); + + auto ottctx = compiler::TargetTypeContext(etsg, object_type); + auto ttctx = compiler::TargetTypeContext(etsg, expr->TsType()); + etsg->LoadAccumulatorInt(expr, enum_interface->GetOrdinal()); + return; + } + + if (etsg->Checker()->IsVariableStatic(expr->PropVar())) { + auto ttctx = compiler::TargetTypeContext(etsg, expr->TsType()); + + if (expr->PropVar()->TsType()->HasTypeFlag(checker::TypeFlag::GETTER_SETTER)) { + checker::Signature *sig = expr->PropVar()->TsType()->AsETSFunctionType()->FindGetter(); + etsg->CallStatic0(expr, sig->InternalName()); + etsg->SetAccumulatorType(sig->ReturnType()); + return; + } + + util::StringView full_name = + etsg->FormClassPropReference(expr->Object()->TsType()->AsETSObjectType(), prop_name); + etsg->LoadStaticProperty(expr, expr->TsType(), full_name); + etsg->ApplyConversion(expr); + return; + } + + auto ottctx = compiler::TargetTypeContext(etsg, expr->Object()->TsType()); + expr->Object()->Compile(etsg); + + // TODO(rsipka): it should be CTE if object type is non nullable type + + if (etsg->GetAccumulatorType()->IsETSNullType()) { + if (expr->IsOptional()) { + etsg->LoadAccumulatorNull(expr, etsg->Checker()->GlobalETSNullType()); + return; + } + + etsg->EmitNullPointerException(expr); + etsg->LoadAccumulatorNull(expr, etsg->Checker()->GlobalETSNullType()); + return; + } + + etsg->ApplyConversion(expr->Object()); + compiler::VReg obj_reg = etsg->AllocReg(); + etsg->StoreAccumulator(expr, obj_reg); + + auto ttctx = compiler::TargetTypeContext(etsg, expr->TsType()); + + auto load_property = [expr, etsg, obj_reg, prop_name]() { + if (expr->PropVar()->TsType()->HasTypeFlag(checker::TypeFlag::GETTER_SETTER)) { + checker::Signature *sig = expr->PropVar()->TsType()->AsETSFunctionType()->FindGetter(); + etsg->CallThisVirtual0(expr, obj_reg, sig->InternalName()); + etsg->SetAccumulatorType(sig->ReturnType()); + } else if (expr->Object()->TsType()->IsETSDynamicType()) { + auto lang = expr->Object()->TsType()->AsETSDynamicType()->Language(); + etsg->LoadPropertyDynamic(expr, expr->TsType(), obj_reg, prop_name, lang); + } else { + const auto full_name = etsg->FormClassPropReference(expr->Object()->TsType()->AsETSObjectType(), prop_name); + etsg->LoadProperty(expr, expr->TsType(), obj_reg, full_name); + } + etsg->ApplyConversion(expr); + }; + + if (expr->IsOptional()) { + compiler::Label *if_not_null = etsg->AllocLabel(); + compiler::Label *end_label = etsg->AllocLabel(); + + etsg->BranchIfNotNull(expr, if_not_null); + etsg->LoadAccumulatorNull(expr, expr->TsType()); + etsg->Branch(expr, end_label); + etsg->SetLabel(expr, if_not_null); + load_property(); + etsg->SetLabel(expr, end_label); + } else { + load_property(); + } } -void ETSCompiler::Compile(const ir::NewExpression *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::NewExpression *expr) const { - (void)expr; UNREACHABLE(); } @@ -328,9 +485,8 @@ void ETSCompiler::Compile(const ir::ObjectExpression *expr) const UNREACHABLE(); } -void ETSCompiler::Compile(const ir::OmittedExpression *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::OmittedExpression *expr) const { - (void)expr; UNREACHABLE(); } @@ -342,14 +498,16 @@ void ETSCompiler::Compile(const ir::OpaqueTypeNode *node) const void ETSCompiler::Compile(const ir::SequenceExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + for (const auto *it : expr->Sequence()) { + it->Compile(etsg); + } } void ETSCompiler::Compile(const ir::SuperExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + etsg->LoadThis(expr); } void ETSCompiler::Compile(const ir::TaggedTemplateExpression *expr) const @@ -388,9 +546,8 @@ void ETSCompiler::Compile(const ir::YieldExpression *expr) const UNREACHABLE(); } // compile methods for LITERAL EXPRESSIONS in alphabetical order -void ETSCompiler::Compile(const ir::BigIntLiteral *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::BigIntLiteral *expr) const { - (void)expr; UNREACHABLE(); } diff --git a/compiler/core/JSCompiler.cpp b/compiler/core/JSCompiler.cpp index a0b481589..42b04ec72 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 { @@ -628,26 +620,83 @@ void JSCompiler::Compile(const ir::FunctionExpression *expr) const void JSCompiler::Compile(const ir::Identifier *expr) const { - (void)expr; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + auto res = pg->Scope()->Find(expr->Name()); + if (res.variable != nullptr) { + pg->LoadVar(expr, res); + return; + } + + if (pg->IsDirectEval()) { + pg->LoadEvalVariable(expr, expr->Name()); + return; + } + + if (expr->Name().Is("NaN")) { + pg->LoadConst(expr, compiler::Constant::JS_NAN); + return; + } + + if (expr->Name().Is("Infinity")) { + pg->LoadConst(expr, compiler::Constant::JS_INFINITY); + return; + } + + if (expr->Name().Is("globalThis")) { + pg->LoadConst(expr, compiler::Constant::JS_GLOBAL); + return; + } + + if (expr->Name().Is("undefined")) { + pg->LoadConst(expr, compiler::Constant::JS_UNDEFINED); + return; + } + + pg->TryLoadGlobalByName(expr, expr->Name()); } -void JSCompiler::Compile(const ir::ImportExpression *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::ImportExpression *expr) const { - (void)expr; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + pg->Unimplemented(); } void JSCompiler::Compile(const ir::MemberExpression *expr) const { - (void)expr; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + expr->Object()->Compile(pg); + pg->OptionalChainCheck(expr->IsOptional(), compiler::VReg::Invalid()); + expr->LoadRhs(pg); } void JSCompiler::Compile(const ir::NewExpression *expr) const { - (void)expr; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + compiler::RegScope rs(pg); + compiler::VReg ctor = pg->AllocReg(); + compiler::VReg new_target = pg->AllocReg(); + + expr->Callee()->Compile(pg); + pg->StoreAccumulator(expr, ctor); + + // new.Target will be the same as ctor + pg->StoreAccumulator(expr, new_target); + + if (!util::Helpers::ContainSpreadElement(expr->Arguments()) && + expr->Arguments().size() < compiler::PandaGen::MAX_RANGE_CALL_ARG) { + for (const auto *it : expr->Arguments()) { + compiler::VReg arg = pg->AllocReg(); + it->Compile(pg); + pg->StoreAccumulator(expr, arg); + } + + pg->NewObject(expr, ctor, expr->Arguments().size() + 2); + } else { + compiler::VReg args_obj = pg->AllocReg(); + + pg->CreateArray(expr, expr->Arguments(), args_obj); + pg->NewObjSpread(expr, ctor, new_target); + } } void JSCompiler::Compile(const ir::ObjectExpression *expr) const @@ -662,22 +711,29 @@ void JSCompiler::Compile(const ir::OpaqueTypeNode *node) const UNREACHABLE(); } -void JSCompiler::Compile(const ir::OmittedExpression *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::OmittedExpression *expr) const { - (void)expr; UNREACHABLE(); } void JSCompiler::Compile(const ir::SequenceExpression *expr) const { - (void)expr; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + for (const auto *it : expr->Sequence()) { + it->Compile(pg); + } } void JSCompiler::Compile(const ir::SuperExpression *expr) const { - (void)expr; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + pg->GetThis(expr); + + const ir::ScriptFunction *func = util::Helpers::GetContainingConstructor(expr); + + if (func != nullptr) { + pg->ThrowIfSuperNotCorrectCall(expr, 0); + } } void JSCompiler::Compile(const ir::TaggedTemplateExpression *expr) const @@ -718,8 +774,8 @@ void JSCompiler::Compile(const ir::YieldExpression *expr) const // Compile methods for LITERAL EXPRESSIONS in alphabetical order void JSCompiler::Compile(const ir::BigIntLiteral *expr) const { - (void)expr; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + pg->LoadAccumulatorBigInt(expr, expr->Str()); } void JSCompiler::Compile(const ir::BooleanLiteral *expr) const diff --git a/ir/expressions/identifier.cpp b/ir/expressions/identifier.cpp index 117ff9e3d..8ae79fa06 100644 --- a/ir/expressions/identifier.cpp +++ b/ir/expressions/identifier.cpp @@ -15,15 +15,11 @@ #include "identifier.h" -#include "binder/scope.h" +#include "checker/ETSchecker.h" +#include "checker/TSchecker.h" #include "compiler/core/pandagen.h" #include "compiler/core/ETSGen.h" -#include "checker/TSchecker.h" -#include "checker/ETSchecker.h" #include "ir/astDump.h" -#include "ir/typeNode.h" -#include "ir/base/decorator.h" -#include "ir/expression.h" namespace panda::es2panda::ir { Identifier::Identifier([[maybe_unused]] Tag const tag, Identifier const &other, ArenaAllocator *const allocator) @@ -98,92 +94,21 @@ void Identifier::Dump(ir::AstDumper *dumper) const void Identifier::Compile(compiler::PandaGen *pg) const { - auto res = pg->Scope()->Find(name_); - if (res.variable != nullptr) { - pg->LoadVar(this, res); - return; - } - - if (pg->IsDirectEval()) { - pg->LoadEvalVariable(this, name_); - return; - } - - if (name_.Is("NaN")) { - pg->LoadConst(this, compiler::Constant::JS_NAN); - return; - } - - if (name_.Is("Infinity")) { - pg->LoadConst(this, compiler::Constant::JS_INFINITY); - return; - } - - if (name_.Is("globalThis")) { - pg->LoadConst(this, compiler::Constant::JS_GLOBAL); - return; - } - - if (name_.Is("undefined")) { - pg->LoadConst(this, compiler::Constant::JS_UNDEFINED); - return; - } - - pg->TryLoadGlobalByName(this, name_); + pg->GetAstCompiler()->Compile(this); } void Identifier::Compile(compiler::ETSGen *etsg) const { - auto lambda = etsg->Binder()->LambdaObjects().find(this); - if (lambda != etsg->Binder()->LambdaObjects().end()) { - etsg->CreateLambdaObjectFromIdentReference(this, lambda->second.first); - return; - } - - auto ttctx = compiler::TargetTypeContext(etsg, TsType()); - - ASSERT(variable_ != nullptr); - if (!variable_->HasFlag(binder::VariableFlags::TYPE_ALIAS)) { - etsg->LoadVar(this, variable_); - } else { - etsg->LoadVar(this, TsType()->Variable()); - } + etsg->GetAstCompiler()->Compile(this); } checker::Type *Identifier::Check(checker::TSChecker *checker) { - if (Variable() == nullptr) { - if (name_.Is("undefined")) { - return checker->GlobalUndefinedType(); - } - - checker->ThrowTypeError({"Cannot find name ", name_}, Start()); - } - - const binder::Decl *decl = Variable()->Declaration(); - - if (decl->IsTypeAliasDecl() || decl->IsInterfaceDecl()) { - checker->ThrowTypeError({name_, " only refers to a type, but is being used as a value here."}, Start()); - } - - SetTsType(checker->GetTypeOfVariable(Variable())); - return TsType(); + return checker->GetAnalyzer()->Check(this); } checker::Type *Identifier::Check(checker::ETSChecker *checker) { - if (TsType() != nullptr) { - return TsType(); - } - - SetTsType(checker->ResolveIdentifier(this)); - if (TsType()->IsETSFunctionType()) { - for (auto *sig : TsType()->AsETSFunctionType()->CallSignatures()) { - if (sig->HasSignatureFlag(checker::SignatureFlags::NEED_RETURN_TYPE)) { - sig->OwnerVar()->Declaration()->Node()->Check(checker); - } - } - } - return TsType(); + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ir/expressions/identifier.h b/ir/expressions/identifier.h index e4b7f7122..aad6fb5dd 100644 --- a/ir/expressions/identifier.h +++ b/ir/expressions/identifier.h @@ -193,10 +193,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: util::StringView name_; diff --git a/ir/expressions/importExpression.cpp b/ir/expressions/importExpression.cpp index e812123c1..1f7c36207 100644 --- a/ir/expressions/importExpression.cpp +++ b/ir/expressions/importExpression.cpp @@ -15,8 +15,9 @@ #include "importExpression.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" #include "compiler/core/pandagen.h" -#include "ir/astDump.h" namespace panda::es2panda::ir { void ImportExpression::TransformChildren(const NodeTransformer &cb) @@ -34,19 +35,23 @@ void ImportExpression::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "ImportExpression"}, {"source", source_}}); } -void ImportExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const +void ImportExpression::Compile(compiler::PandaGen *pg) const { - pg->Unimplemented(); + pg->GetAstCompiler()->Compile(this); } -checker::Type *ImportExpression::Check([[maybe_unused]] checker::TSChecker *checker) +void ImportExpression::Compile(compiler::ETSGen *etsg) const { - return nullptr; + etsg->GetAstCompiler()->Compile(this); +} +checker::Type *ImportExpression::Check(checker::TSChecker *checker) +{ + return checker->GetAnalyzer()->Check(this); } -checker::Type *ImportExpression::Check([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *ImportExpression::Check(checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } // NOLINTNEXTLINE(google-default-arguments) diff --git a/ir/expressions/importExpression.h b/ir/expressions/importExpression.h index d275dd9a9..5d33ba366 100644 --- a/ir/expressions/importExpression.h +++ b/ir/expressions/importExpression.h @@ -35,9 +35,10 @@ public: void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; - void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + void Compile(compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; + checker::Type *Check(checker::TSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; private: Expression *source_; diff --git a/ir/expressions/literals/bigIntLiteral.cpp b/ir/expressions/literals/bigIntLiteral.cpp index b59d2f83c..47e43c721 100644 --- a/ir/expressions/literals/bigIntLiteral.cpp +++ b/ir/expressions/literals/bigIntLiteral.cpp @@ -15,8 +15,9 @@ #include "bigIntLiteral.h" -#include "compiler/core/pandagen.h" #include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" namespace panda::es2panda::ir { @@ -30,24 +31,22 @@ void BigIntLiteral::Dump(ir::AstDumper *dumper) const void BigIntLiteral::Compile(compiler::PandaGen *pg) const { - pg->LoadAccumulatorBigInt(this, src_); + pg->GetAstCompiler()->Compile(this); } -checker::Type *BigIntLiteral::Check(checker::TSChecker *checker) +void BigIntLiteral::Compile(compiler::ETSGen *etsg) const { - auto search = checker->BigintLiteralMap().find(src_); - if (search != checker->BigintLiteralMap().end()) { - return search->second; - } + etsg->GetAstCompiler()->Compile(this); +} - auto *new_bigint_literal_type = checker->Allocator()->New(src_, false); - checker->BigintLiteralMap().insert({src_, new_bigint_literal_type}); - return new_bigint_literal_type; +checker::Type *BigIntLiteral::Check(checker::TSChecker *checker) +{ + return checker->GetAnalyzer()->Check(this); } checker::Type *BigIntLiteral::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } // NOLINTNEXTLINE(google-default-arguments) diff --git a/ir/expressions/literals/bigIntLiteral.h b/ir/expressions/literals/bigIntLiteral.h index a017c4912..a0b72c484 100644 --- a/ir/expressions/literals/bigIntLiteral.h +++ b/ir/expressions/literals/bigIntLiteral.h @@ -41,9 +41,10 @@ public: void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; - void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + void Compile(compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; + checker::Type *Check(checker::TSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; private: util::StringView const src_; diff --git a/ir/expressions/memberExpression.cpp b/ir/expressions/memberExpression.cpp index 6789de0bf..cef630597 100644 --- a/ir/expressions/memberExpression.cpp +++ b/ir/expressions/memberExpression.cpp @@ -75,6 +75,7 @@ void MemberExpression::Dump(ir::AstDumper *dumper) const {"optional", optional_}}); } +// TODO(csabahurton): LoadRhs() can be moved to JSCompiler.cpp once ChainExpression logic is there, too void MemberExpression::LoadRhs(compiler::PandaGen *pg) const { compiler::RegScope rs(pg); @@ -95,6 +96,7 @@ void MemberExpression::LoadRhs(compiler::PandaGen *pg) const } } +// TODO(csabahurton): CompileToRegs() can be moved to JSCompiler.cpp once unaryExpression logic is there, too void MemberExpression::CompileToRegs(compiler::PandaGen *pg, compiler::VReg object, compiler::VReg property) const { object_->Compile(pg); @@ -113,11 +115,11 @@ void MemberExpression::CompileToRegs(compiler::PandaGen *pg, compiler::VReg obje void MemberExpression::Compile(compiler::PandaGen *pg) const { - object_->Compile(pg); - pg->OptionalChainCheck(optional_, compiler::VReg::Invalid()); - LoadRhs(pg); + pg->GetAstCompiler()->Compile(this); } +// TODO(csabahurton): CompileToReg() can be moved to JSCompiler.cpp once ChainExpression and CallExpression logic are +// there, too void MemberExpression::CompileToReg(compiler::PandaGen *pg, compiler::VReg obj_reg) const { object_->Compile(pg); @@ -128,311 +130,17 @@ void MemberExpression::CompileToReg(compiler::PandaGen *pg, compiler::VReg obj_r void MemberExpression::Compile(compiler::ETSGen *etsg) const { - auto lambda = etsg->Binder()->LambdaObjects().find(this); - if (lambda != etsg->Binder()->LambdaObjects().end()) { - etsg->CreateLambdaObjectFromMemberReference(this, object_, lambda->second.first); - return; - } - - compiler::RegScope rs(etsg); - - if (computed_) { - auto ottctx = compiler::TargetTypeContext(etsg, object_->TsType()); - object_->Compile(etsg); - - if (etsg->GetAccumulatorType()->IsETSNullType()) { - if (optional_) { - return; - } - - etsg->EmitNullPointerException(this); - return; - } - - // Helper function to avoid branching in non optional cases - auto compile_and_load_elements = [this, etsg]() { - compiler::VReg obj_reg = etsg->AllocReg(); - etsg->StoreAccumulator(this, obj_reg); - auto pttctx = compiler::TargetTypeContext(etsg, property_->TsType()); - property_->Compile(etsg); - etsg->ApplyConversion(property_); - - auto ttctx = compiler::TargetTypeContext(etsg, TsType()); - - if (TsType()->IsETSDynamicType()) { - auto lang = TsType()->AsETSDynamicType()->Language(); - etsg->LoadElementDynamic(this, obj_reg, lang); - } else { - etsg->LoadArrayElement(this, obj_reg); - } - - etsg->ApplyConversion(this); - }; - - if (optional_) { - compiler::Label *end_label = etsg->AllocLabel(); - etsg->BranchIfNull(this, end_label); - compile_and_load_elements(); - etsg->SetLabel(this, end_label); - } else { - compile_and_load_elements(); - } - - return; - } - - auto &prop_name = property_->AsIdentifier()->Name(); - auto const *const object_type = object_->TsType(); - - if (object_type->IsETSArrayType() && prop_name.Is("length")) { - auto ottctx = compiler::TargetTypeContext(etsg, object_type); - object_->Compile(etsg); - compiler::VReg obj_reg = etsg->AllocReg(); - etsg->StoreAccumulator(this, obj_reg); - - auto ttctx = compiler::TargetTypeContext(etsg, TsType()); - etsg->LoadArrayLength(this, obj_reg); - etsg->ApplyConversion(this); - return; - } - - if (object_type->IsETSEnumType() || object_type->IsETSStringEnumType()) { - auto const *const enum_interface = [object_type, this]() -> checker::ETSEnumInterface const * { - if (object_type->IsETSEnumType()) { - return TsType()->AsETSEnumType(); - } - return TsType()->AsETSStringEnumType(); - }(); - - auto ottctx = compiler::TargetTypeContext(etsg, object_type); - auto ttctx = compiler::TargetTypeContext(etsg, TsType()); - etsg->LoadAccumulatorInt(this, enum_interface->GetOrdinal()); - return; - } - - if (etsg->Checker()->IsVariableStatic(prop_var_)) { - auto ttctx = compiler::TargetTypeContext(etsg, TsType()); - - if (prop_var_->TsType()->HasTypeFlag(checker::TypeFlag::GETTER_SETTER)) { - checker::Signature *sig = prop_var_->TsType()->AsETSFunctionType()->FindGetter(); - etsg->CallStatic0(this, sig->InternalName()); - etsg->SetAccumulatorType(sig->ReturnType()); - return; - } - - util::StringView full_name = etsg->FormClassPropReference(object_->TsType()->AsETSObjectType(), prop_name); - etsg->LoadStaticProperty(this, TsType(), full_name); - etsg->ApplyConversion(this); - return; - } - - auto ottctx = compiler::TargetTypeContext(etsg, object_->TsType()); - object_->Compile(etsg); - - // TODO(rsipka): it should be CTE if object type is non nullable type - - if (etsg->GetAccumulatorType()->IsETSNullType()) { - if (optional_) { - etsg->LoadAccumulatorNull(this, etsg->Checker()->GlobalETSNullType()); - return; - } - - etsg->EmitNullPointerException(this); - etsg->LoadAccumulatorNull(this, etsg->Checker()->GlobalETSNullType()); - return; - } - - etsg->ApplyConversion(object_); - compiler::VReg obj_reg = etsg->AllocReg(); - etsg->StoreAccumulator(this, obj_reg); - - auto ttctx = compiler::TargetTypeContext(etsg, TsType()); - - auto load_property = [this, etsg, obj_reg, prop_name]() { - if (prop_var_->TsType()->HasTypeFlag(checker::TypeFlag::GETTER_SETTER)) { - checker::Signature *sig = prop_var_->TsType()->AsETSFunctionType()->FindGetter(); - etsg->CallThisVirtual0(this, obj_reg, sig->InternalName()); - etsg->SetAccumulatorType(sig->ReturnType()); - } else if (object_->TsType()->IsETSDynamicType()) { - auto lang = object_->TsType()->AsETSDynamicType()->Language(); - etsg->LoadPropertyDynamic(this, TsType(), obj_reg, prop_name, lang); - } else { - const auto full_name = etsg->FormClassPropReference(object_->TsType()->AsETSObjectType(), prop_name); - etsg->LoadProperty(this, TsType(), obj_reg, full_name); - } - etsg->ApplyConversion(this); - }; - - if (optional_) { - compiler::Label *if_not_null = etsg->AllocLabel(); - compiler::Label *end_label = etsg->AllocLabel(); - - etsg->BranchIfNotNull(this, if_not_null); - etsg->LoadAccumulatorNull(this, TsType()); - etsg->Branch(this, end_label); - etsg->SetLabel(this, if_not_null); - load_property(); - etsg->SetLabel(this, end_label); - } else { - load_property(); - } + etsg->GetAstCompiler()->Compile(this); } checker::Type *MemberExpression::Check(checker::TSChecker *checker) { - checker::Type *base_type = checker->CheckNonNullType(object_->Check(checker), object_->Start()); - - if (computed_) { - checker::Type *index_type = property_->Check(checker); - checker::Type *indexed_access_type = checker->GetPropertyTypeForIndexType(base_type, index_type); - - if (indexed_access_type != nullptr) { - return indexed_access_type; - } - - if (!index_type->HasTypeFlag(checker::TypeFlag::STRING_LIKE | checker::TypeFlag::NUMBER_LIKE)) { - checker->ThrowTypeError({"Type ", index_type, " cannot be used as index type"}, property_->Start()); - } - - if (index_type->IsNumberType()) { - checker->ThrowTypeError("No index signature with a parameter of type 'string' was found on type this type", - Start()); - } - - if (index_type->IsStringType()) { - checker->ThrowTypeError("No index signature with a parameter of type 'number' was found on type this type", - Start()); - } - - switch (property_->Type()) { - case ir::AstNodeType::IDENTIFIER: { - checker->ThrowTypeError( - {"Property ", property_->AsIdentifier()->Name(), " does not exist on this type."}, - property_->Start()); - } - case ir::AstNodeType::NUMBER_LITERAL: { - checker->ThrowTypeError( - {"Property ", property_->AsNumberLiteral()->Str(), " does not exist on this type."}, - property_->Start()); - } - case ir::AstNodeType::STRING_LITERAL: { - checker->ThrowTypeError( - {"Property ", property_->AsStringLiteral()->Str(), " does not exist on this type."}, - property_->Start()); - } - default: { - UNREACHABLE(); - } - } - } - - binder::Variable *prop = checker->GetPropertyOfType(base_type, property_->AsIdentifier()->Name()); - - if (prop != nullptr) { - checker::Type *prop_type = checker->GetTypeOfVariable(prop); - if (prop->HasFlag(binder::VariableFlags::READONLY)) { - prop_type->AddTypeFlag(checker::TypeFlag::READONLY); - } - - return prop_type; - } - - if (base_type->IsObjectType()) { - checker::ObjectType *obj_type = base_type->AsObjectType(); - - if (obj_type->StringIndexInfo() != nullptr) { - checker::Type *index_type = obj_type->StringIndexInfo()->GetType(); - if (obj_type->StringIndexInfo()->Readonly()) { - index_type->AddTypeFlag(checker::TypeFlag::READONLY); - } - - return index_type; - } - } - - checker->ThrowTypeError({"Property ", property_->AsIdentifier()->Name(), " does not exist on this type."}, - property_->Start()); - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *MemberExpression::Check(checker::ETSChecker *checker) { - if (TsType() != nullptr) { - return TsType(); - } - - if (computed_) { - SetTsType(checker->CheckArrayElementAccess(this)); - return TsType(); - } - - checker::Type *const base_type = object_->Check(checker); - - if (!base_type->IsETSObjectType()) { - if (base_type->IsETSArrayType() && property_->AsIdentifier()->Name().Is("length")) { - SetTsType(checker->GlobalIntType()); - return TsType(); - } - - if (base_type->IsETSEnumType() || base_type->IsETSStringEnumType()) { - auto const *const enum_interface = [base_type]() -> checker::ETSEnumInterface const * { - if (base_type->IsETSEnumType()) { - return base_type->AsETSEnumType(); - } - return base_type->AsETSStringEnumType(); - }(); - - if (parent_->Type() == ir::AstNodeType::CALL_EXPRESSION && parent_->AsCallExpression()->Callee() == this) { - auto *const enum_method_type = - enum_interface->LookupMethod(checker, object_, property_->AsIdentifier()); - SetTsType(enum_method_type); - return TsType(); - } - - auto *const enum_literal_type = enum_interface->LookupConstant(checker, object_, property_->AsIdentifier()); - SetTsType(enum_literal_type); - SetPropVar(enum_literal_type->GetMemberVar()); - return TsType(); - } - - checker->ThrowTypeError({"Cannot access property of non-object or non-enum type"}, object_->Start()); - } - - obj_type_ = base_type->AsETSObjectType(); - auto resolve_res = checker->ResolveMemberReference(this, obj_type_); - ASSERT(!resolve_res.empty()); - checker::Type *type_to_set = nullptr; - switch (resolve_res.size()) { - case 1: { - if (resolve_res[0]->Kind() == checker::ResolvedKind::PROPERTY) { - prop_var_ = resolve_res[0]->Variable()->AsLocalVariable(); - checker->ValidatePropertyAccess(prop_var_, obj_type_, property_->Start()); - type_to_set = checker->GetTypeOfVariable(prop_var_); - } else { - type_to_set = checker->GetTypeOfVariable(resolve_res[0]->Variable()); - } - break; - } - case 2: { - // ETSExtensionFuncHelperType(class_method_type, extension_method_type) - type_to_set = checker->CreateETSExtensionFuncHelperType( - checker->GetTypeOfVariable(resolve_res[1]->Variable())->AsETSFunctionType(), - checker->GetTypeOfVariable(resolve_res[0]->Variable())->AsETSFunctionType()); - break; - } - default: { - UNREACHABLE(); - } - } - SetTsType(type_to_set); - if (prop_var_ != nullptr && prop_var_->TsType() != nullptr && prop_var_->TsType()->IsETSFunctionType()) { - for (auto *sig : prop_var_->TsType()->AsETSFunctionType()->CallSignatures()) { - if (sig->HasSignatureFlag(checker::SignatureFlags::NEED_RETURN_TYPE)) { - sig->OwnerVar()->Declaration()->Node()->Check(checker); - } - } - } - return TsType(); + return checker->GetAnalyzer()->Check(this); } // NOLINTNEXTLINE(google-default-arguments) diff --git a/ir/expressions/memberExpression.h b/ir/expressions/memberExpression.h index 4c786300a..738ad4265 100644 --- a/ir/expressions/memberExpression.h +++ b/ir/expressions/memberExpression.h @@ -20,6 +20,11 @@ #include "ir/expression.h" #include "ir/irnode.h" +namespace panda::es2panda::compiler { +class JSCompiler; +class ETSCompiler; +} // namespace panda::es2panda::compiler + namespace panda::es2panda::checker { class ETSObjectType; } // namespace panda::es2panda::checker @@ -59,6 +64,10 @@ public: explicit MemberExpression(Tag tag, Expression *object, Expression *property); + // TODO (csabahurton): these friend relationships can be removed once there are getters for private fields + friend class compiler::JSCompiler; + friend class compiler::ETSCompiler; + [[nodiscard]] Expression *Object() noexcept { return object_; @@ -157,7 +166,7 @@ public: void CompileToReg(compiler::PandaGen *pg, compiler::VReg obj_reg) const; void CompileToRegs(compiler::PandaGen *pg, compiler::VReg object, compiler::VReg property) const; checker::Type *Check(checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; protected: MemberExpression(MemberExpression const &other) : Expression(static_cast(other)) diff --git a/ir/expressions/newExpression.cpp b/ir/expressions/newExpression.cpp index d8783c717..afd01242f 100644 --- a/ir/expressions/newExpression.cpp +++ b/ir/expressions/newExpression.cpp @@ -15,12 +15,10 @@ #include "newExpression.h" -#include "util/helpers.h" -#include "compiler/core/pandagen.h" -#include "compiler/core/ETSGen.h" -#include "compiler/core/regScope.h" #include "checker/TSchecker.h" -#include "ir/astDump.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" +#include "util/helpers.h" namespace panda::es2panda::ir { NewExpression::NewExpression([[maybe_unused]] Tag const tag, NewExpression const &other, @@ -73,53 +71,21 @@ void NewExpression::Dump(ir::AstDumper *dumper) const void NewExpression::Compile(compiler::PandaGen *pg) const { - compiler::RegScope rs(pg); - compiler::VReg ctor = pg->AllocReg(); - compiler::VReg new_target = pg->AllocReg(); - - callee_->Compile(pg); - pg->StoreAccumulator(this, ctor); - - // new.Target will be the same as ctor - pg->StoreAccumulator(this, new_target); - - if (!util::Helpers::ContainSpreadElement(arguments_) && - arguments_.size() < compiler::PandaGen::MAX_RANGE_CALL_ARG) { - for (const auto *it : arguments_) { - compiler::VReg arg = pg->AllocReg(); - it->Compile(pg); - pg->StoreAccumulator(this, arg); - } - - pg->NewObject(this, ctor, arguments_.size() + 2); - } else { - compiler::VReg args_obj = pg->AllocReg(); - - pg->CreateArray(this, arguments_, args_obj); - pg->NewObjSpread(this, ctor, new_target); - } + pg->GetAstCompiler()->Compile(this); } -void NewExpression::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +void NewExpression::Compile(compiler::ETSGen *etsg) const { - UNREACHABLE(); + etsg->GetAstCompiler()->Compile(this); } -checker::Type *NewExpression::Check([[maybe_unused]] checker::TSChecker *checker) +checker::Type *NewExpression::Check(checker::TSChecker *checker) { - checker::Type *callee_type = callee_->Check(checker); - - if (callee_type->IsObjectType()) { - checker::ObjectType *callee_obj = callee_type->AsObjectType(); - return checker->ResolveCallOrNewExpression(callee_obj->ConstructSignatures(), arguments_, Start()); - } - - checker->ThrowTypeError("This expression is not callable.", Start()); - return nullptr; + return checker->GetAnalyzer()->Check(this); } -checker::Type *NewExpression::Check([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *NewExpression::Check(checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ir/expressions/newExpression.h b/ir/expressions/newExpression.h index 2cefd3ce6..2183cb957 100644 --- a/ir/expressions/newExpression.h +++ b/ir/expressions/newExpression.h @@ -18,6 +18,10 @@ #include "ir/expression.h" +namespace panda::es2panda::checker { +class TSAnalyzer; +} // namespace panda::es2panda::checker + namespace panda::es2panda::ir { class NewExpression : public Expression { private: @@ -34,9 +38,11 @@ public: : Expression(AstNodeType::NEW_EXPRESSION), callee_(callee), arguments_(std::move(arguments)) { } - explicit NewExpression(Tag tag, NewExpression const &other, ArenaAllocator *allocator); + // TODO (csabahurton): friend relationship can be removed once there are getters for private fields + friend class checker::TSAnalyzer; + [[nodiscard]] const Expression *Callee() const noexcept { return callee_; @@ -56,7 +62,7 @@ public: void Compile(compiler::PandaGen *pg) const override; void Compile(compiler::ETSGen *etsg) const override; checker::Type *Check(checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; private: Expression *callee_ = nullptr; diff --git a/ir/expressions/omittedExpression.cpp b/ir/expressions/omittedExpression.cpp index b24ea45be..6b08d81d0 100644 --- a/ir/expressions/omittedExpression.cpp +++ b/ir/expressions/omittedExpression.cpp @@ -15,8 +15,10 @@ #include "omittedExpression.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 OmittedExpression::TransformChildren([[maybe_unused]] const NodeTransformer &cb) {} @@ -27,16 +29,24 @@ void OmittedExpression::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "OmittedExpression"}}); } -void OmittedExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void OmittedExpression::Compile(compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} + +void OmittedExpression::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} -checker::Type *OmittedExpression::Check([[maybe_unused]] checker::TSChecker *checker) +checker::Type *OmittedExpression::Check(checker::TSChecker *checker) { - return checker->GlobalUndefinedType(); + return checker->GetAnalyzer()->Check(this); } -checker::Type *OmittedExpression::Check([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *OmittedExpression::Check(checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } // NOLINTNEXTLINE(google-default-arguments) diff --git a/ir/expressions/omittedExpression.h b/ir/expressions/omittedExpression.h index ee722bf0c..5ff6b4fe9 100644 --- a/ir/expressions/omittedExpression.h +++ b/ir/expressions/omittedExpression.h @@ -35,9 +35,10 @@ public: void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; - void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; - 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; }; } // namespace panda::es2panda::ir diff --git a/ir/expressions/sequenceExpression.cpp b/ir/expressions/sequenceExpression.cpp index 637dc990c..edf20e42d 100644 --- a/ir/expressions/sequenceExpression.cpp +++ b/ir/expressions/sequenceExpression.cpp @@ -15,8 +15,10 @@ #include "sequenceExpression.h" +#include "checker/ETSchecker.h" #include "checker/TSchecker.h" -#include "ir/astDump.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" namespace panda::es2panda::ir { SequenceExpression::SequenceExpression([[maybe_unused]] Tag const tag, SequenceExpression const &other, @@ -59,35 +61,23 @@ void SequenceExpression::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "SequenceExpression"}, {"expressions", sequence_}}); } -void SequenceExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const +void SequenceExpression::Compile(compiler::PandaGen *pg) const { - for (const auto *it : sequence_) { - it->Compile(pg); - } + pg->GetAstCompiler()->Compile(this); } void SequenceExpression::Compile(compiler::ETSGen *etsg) const { - for (const auto *it : sequence_) { - it->Compile(etsg); - } + etsg->GetAstCompiler()->Compile(this); } -checker::Type *SequenceExpression::Check([[maybe_unused]] checker::TSChecker *checker) +checker::Type *SequenceExpression::Check(checker::TSChecker *checker) { - // TODO(aszilagyi) - return checker->GlobalAnyType(); + return checker->GetAnalyzer()->Check(this); } checker::Type *SequenceExpression::Check(checker::ETSChecker *checker) { - if (TsType() != nullptr) { - return TsType(); - } - - for (auto *it : sequence_) { - it->Check(checker); - } - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ir/expressions/sequenceExpression.h b/ir/expressions/sequenceExpression.h index 29a1fd2ae..50cf4e4a3 100644 --- a/ir/expressions/sequenceExpression.h +++ b/ir/expressions/sequenceExpression.h @@ -53,9 +53,9 @@ public: void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; - void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + void Compile(compiler::PandaGen *pg) const override; void Compile(compiler::ETSGen *etsg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; + checker::Type *Check(checker::TSChecker *checker) override; checker::Type *Check(checker::ETSChecker *checker) override; private: diff --git a/ir/expressions/superExpression.cpp b/ir/expressions/superExpression.cpp index 67e4625b5..234cedbfc 100644 --- a/ir/expressions/superExpression.cpp +++ b/ir/expressions/superExpression.cpp @@ -15,12 +15,11 @@ #include "superExpression.h" -#include "util/helpers.h" -#include "compiler/core/pandagen.h" -#include "compiler/core/ETSGen.h" -#include "checker/TSchecker.h" #include "checker/ETSchecker.h" -#include "ir/astDump.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" +#include "util/helpers.h" namespace panda::es2panda::ir { void SuperExpression::TransformChildren([[maybe_unused]] const NodeTransformer &cb) {} @@ -33,34 +32,22 @@ void SuperExpression::Dump(ir::AstDumper *dumper) const void SuperExpression::Compile(compiler::PandaGen *pg) const { - pg->GetThis(this); - - const ir::ScriptFunction *func = util::Helpers::GetContainingConstructor(this); - - if (func != nullptr) { - pg->ThrowIfSuperNotCorrectCall(this, 0); - } + pg->GetAstCompiler()->Compile(this); } void SuperExpression::Compile(compiler::ETSGen *etsg) const { - etsg->LoadThis(this); + etsg->GetAstCompiler()->Compile(this); } checker::Type *SuperExpression::Check(checker::TSChecker *checker) { - // TODO(aszilagyi) - return checker->GlobalAnyType(); + return checker->GetAnalyzer()->Check(this); } checker::Type *SuperExpression::Check([[maybe_unused]] checker::ETSChecker *checker) { - if (TsType() != nullptr) { - return TsType(); - } - - SetTsType(checker->CheckThisOrSuperAccess(this, checker->Context().ContainingClass()->SuperType(), "super")); - return TsType(); + return checker->GetAnalyzer()->Check(this); } // NOLINTNEXTLINE(google-default-arguments) diff --git a/ir/expressions/superExpression.h b/ir/expressions/superExpression.h index 31b283597..fdbfd9146 100644 --- a/ir/expressions/superExpression.h +++ b/ir/expressions/superExpression.h @@ -37,7 +37,7 @@ public: void Compile(compiler::PandaGen *pg) const override; void Compile(compiler::ETSGen *etsg) const override; checker::Type *Check(checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; private: }; 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