diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index f91ee6ca74baf1c27f552ac3a85e504a908deba4..402dbe8ddce713a46b76e96af3d0a0d093da5f13 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -20,14 +20,6 @@ #include "checker/ETSchecker.h" #include "checker/ets/castingContext.h" #include "checker/ets/typeRelationContext.h" -#include "ir/base/catchClause.h" -#include "ir/base/classProperty.h" -#include "ir/base/classStaticBlock.h" -#include "ir/expressions/identifier.h" -#include "ir/expressions/objectExpression.h" -#include "ir/expressions/arrayExpression.h" -#include "ir/statements/blockStatement.h" -#include "ir/statements/returnStatement.h" #include "util/helpers.h" namespace panda::es2panda::checker { @@ -472,9 +464,8 @@ checker::Type *ETSAnalyzer::Check(ir::SuperExpression *expr) const UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TaggedTemplateExpression *expr) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TaggedTemplateExpression *expr) const { - (void)expr; UNREACHABLE(); } @@ -498,8 +489,36 @@ checker::Type *ETSAnalyzer::Check(ir::UnaryExpression *expr) const checker::Type *ETSAnalyzer::Check(ir::UpdateExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + if (expr->TsType() != nullptr) { + return expr->TsType(); + } + + checker::Type *operand_type = expr->argument_->Check(checker); + if (expr->Argument()->IsIdentifier()) { + checker->ValidateUnaryOperatorOperand(expr->Argument()->AsIdentifier()->Variable()); + } else { + ASSERT(expr->Argument()->IsMemberExpression()); + varbinder::LocalVariable *prop_var = expr->argument_->AsMemberExpression()->PropVar(); + if (prop_var != nullptr) { + checker->ValidateUnaryOperatorOperand(prop_var); + } + } + + auto unboxed_type = checker->ETSBuiltinTypeAsPrimitiveType(operand_type); + + if (unboxed_type == nullptr || !unboxed_type->HasTypeFlag(checker::TypeFlag::ETS_NUMERIC)) { + checker->ThrowTypeError("Bad operand type, the type of the operand must be numeric type.", + expr->Argument()->Start()); + } + + if (operand_type->IsETSObjectType()) { + expr->Argument()->AddBoxingUnboxingFlag(checker->GetUnboxingFlag(unboxed_type) | + checker->GetBoxingFlag(unboxed_type)); + } + + expr->SetTsType(operand_type); + return expr->TsType(); } checker::Type *ETSAnalyzer::Check(ir::YieldExpression *expr) const @@ -938,8 +957,12 @@ checker::Type *ETSAnalyzer::Check(ir::VariableDeclarator *st) const checker::Type *ETSAnalyzer::Check(ir::VariableDeclaration *st) const { - (void)st; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + for (auto *it : st->Declarators()) { + it->Check(checker); + } + + return nullptr; } checker::Type *ETSAnalyzer::Check(ir::WhileStatement *st) const @@ -962,8 +985,37 @@ checker::Type *ETSAnalyzer::Check(ir::TSArrayType *node) const checker::Type *ETSAnalyzer::Check(ir::TSAsExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + + auto *const target_type = expr->TypeAnnotation()->AsTypeNode()->GetType(checker); + // Object expression requires that its type be set by the context before checking. in this case, the target type + // provides that context. + if (expr->Expr()->IsObjectExpression()) { + expr->Expr()->AsObjectExpression()->SetPreferredType(target_type); + } + auto *const source_type = expr->Expr()->Check(checker); + + const checker::CastingContext ctx(checker->Relation(), expr->Expr(), source_type, target_type, + expr->Expr()->Start(), + {"Cannot cast type '", source_type, "' to '", target_type, "'"}); + + if (source_type->IsETSDynamicType() && target_type->IsLambdaObject()) { + // NOTE: itrubachev. change target_type to created lambdaobject type. + // Now target_type is not changed, only construct signature is added to it + checker->BuildLambdaObjectClass(target_type->AsETSObjectType(), + expr->TypeAnnotation()->AsETSFunctionType()->ReturnType()); + } + expr->is_unchecked_cast_ = ctx.UncheckedCast(); + + // Make sure the array type symbol gets created for the assembler to be able to emit checkcast. + // Because it might not exist, if this particular array type was never created explicitly. + if (!expr->is_unchecked_cast_ && target_type->IsETSArrayType()) { + auto *const target_array_type = target_type->AsETSArrayType(); + checker->CreateBuiltinArraySignature(target_array_type, target_array_type->Rank()); + } + + expr->SetTsType(target_type); + return expr->TsType(); } checker::Type *ETSAnalyzer::Check(ir::TSBigintKeyword *node) const @@ -978,9 +1030,8 @@ checker::Type *ETSAnalyzer::Check(ir::TSBooleanKeyword *node) const UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSClassImplements *expr) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSClassImplements *expr) const { - (void)expr; UNREACHABLE(); } @@ -1044,9 +1095,8 @@ checker::Type *ETSAnalyzer::Check(ir::TSInferType *node) const UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSInterfaceBody *expr) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSInterfaceBody *expr) const { - (void)expr; UNREACHABLE(); } @@ -1056,9 +1106,8 @@ checker::Type *ETSAnalyzer::Check(ir::TSInterfaceDeclaration *st) const UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSInterfaceHeritage *expr) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSInterfaceHeritage *expr) const { - (void)expr; UNREACHABLE(); } @@ -1092,9 +1141,8 @@ checker::Type *ETSAnalyzer::Check(ir::TSModuleDeclaration *st) const UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSNamedTupleMember *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSNamedTupleMember *node) const { - (void)node; UNREACHABLE(); } @@ -1158,9 +1206,8 @@ checker::Type *ETSAnalyzer::Check(ir::TSThisType *node) const UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSTupleType *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSTupleType *node) const { - (void)node; UNREACHABLE(); } @@ -1170,9 +1217,8 @@ checker::Type *ETSAnalyzer::Check(ir::TSTypeAliasDeclaration *st) const UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSTypeAssertion *expr) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSTypeAssertion *expr) const { - (void)expr; UNREACHABLE(); } @@ -1212,9 +1258,8 @@ checker::Type *ETSAnalyzer::Check(ir::TSTypePredicate *node) const UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSTypeQuery *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSTypeQuery *node) const { - (void)node; UNREACHABLE(); } diff --git a/ets2panda/checker/TSAnalyzer.cpp b/ets2panda/checker/TSAnalyzer.cpp index d3e96e821ffd6bb149a2337acaa909ed200d7dca..e0bb87a81af11b0a3f3097780882a9ff9d07a73f 100644 --- a/ets2panda/checker/TSAnalyzer.cpp +++ b/ets2panda/checker/TSAnalyzer.cpp @@ -369,10 +369,11 @@ checker::Type *TSAnalyzer::Check(ir::SuperExpression *expr) const UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::TaggedTemplateExpression *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TaggedTemplateExpression *expr) const { - (void)expr; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + // NOTE: aszilagyi. + return checker->GlobalAnyType(); } checker::Type *TSAnalyzer::Check(ir::TemplateLiteral *expr) const @@ -395,8 +396,20 @@ checker::Type *TSAnalyzer::Check(ir::UnaryExpression *expr) const checker::Type *TSAnalyzer::Check(ir::UpdateExpression *expr) const { - (void)expr; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + checker::Type *operand_type = expr->argument_->Check(checker); + checker->CheckNonNullType(operand_type, expr->Start()); + + if (!operand_type->HasTypeFlag(checker::TypeFlag::VALID_ARITHMETIC_TYPE)) { + checker->ThrowTypeError("An arithmetic operand must be of type 'any', 'number', 'bigint' or an enum type.", + expr->Start()); + } + + checker->CheckReferenceExpression( + expr->argument_, "The operand of an increment or decrement operator must be a variable or a property access", + "The operand of an increment or decrement operator may not be an optional property access"); + + return checker->GetUnaryResultType(operand_type); } checker::Type *TSAnalyzer::Check(ir::YieldExpression *expr) const @@ -655,8 +668,12 @@ checker::Type *TSAnalyzer::Check(ir::VariableDeclarator *st) const checker::Type *TSAnalyzer::Check(ir::VariableDeclaration *st) const { - (void)st; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + for (auto *it : st->Declarators()) { + it->Check(checker); + } + + return nullptr; } checker::Type *TSAnalyzer::Check(ir::WhileStatement *st) const @@ -677,10 +694,76 @@ checker::Type *TSAnalyzer::Check(ir::TSArrayType *node) const UNREACHABLE(); } +static bool IsValidConstAssertionArgument(checker::Checker *checker, const ir::AstNode *arg) +{ + switch (arg->Type()) { + case ir::AstNodeType::NUMBER_LITERAL: + case ir::AstNodeType::STRING_LITERAL: + case ir::AstNodeType::BIGINT_LITERAL: + case ir::AstNodeType::BOOLEAN_LITERAL: + case ir::AstNodeType::ARRAY_EXPRESSION: + case ir::AstNodeType::OBJECT_EXPRESSION: + case ir::AstNodeType::TEMPLATE_LITERAL: { + return true; + } + case ir::AstNodeType::UNARY_EXPRESSION: { + const ir::UnaryExpression *unary_expr = arg->AsUnaryExpression(); + lexer::TokenType op = unary_expr->OperatorType(); + const ir::Expression *unary_arg = unary_expr->Argument(); + return (op == lexer::TokenType::PUNCTUATOR_MINUS && unary_arg->IsLiteral() && + (unary_arg->AsLiteral()->IsNumberLiteral() || unary_arg->AsLiteral()->IsBigIntLiteral())) || + (op == lexer::TokenType::PUNCTUATOR_PLUS && unary_arg->IsLiteral() && + unary_arg->AsLiteral()->IsNumberLiteral()); + } + case ir::AstNodeType::MEMBER_EXPRESSION: { + const ir::MemberExpression *member_expr = arg->AsMemberExpression(); + if (member_expr->Object()->IsIdentifier()) { + auto result = checker->Scope()->Find(member_expr->Object()->AsIdentifier()->Name()); + constexpr auto ENUM_LITERAL_TYPE = checker::EnumLiteralType::EnumLiteralTypeKind::LITERAL; + if (result.variable != nullptr && + result.variable->TsType()->HasTypeFlag(checker::TypeFlag::ENUM_LITERAL) && + result.variable->TsType()->AsEnumLiteralType()->Kind() == ENUM_LITERAL_TYPE) { + return true; + } + } + return false; + } + default: + return false; + } +} + checker::Type *TSAnalyzer::Check(ir::TSAsExpression *expr) const { - (void)expr; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + if (expr->IsConst()) { + auto context = checker::SavedCheckerContext(checker, checker::CheckerStatus::IN_CONST_CONTEXT); + checker::Type *expr_type = expr->Expr()->Check(checker); + + if (!IsValidConstAssertionArgument(checker, expr->Expr())) { + checker->ThrowTypeError( + "A 'const' assertions can only be applied to references to enum members, or string, number, " + "boolean, array, or object literals.", + expr->Expr()->Start()); + } + + return expr_type; + } + + auto context = checker::SavedCheckerContext(checker, checker::CheckerStatus::NO_OPTS); + + expr->TypeAnnotation()->Check(checker); + checker::Type *expr_type = checker->GetBaseTypeOfLiteralType(expr->Expr()->Check(checker)); + checker::Type *target_type = expr->TypeAnnotation()->GetType(checker); + + checker->IsTypeComparableTo( + target_type, expr_type, + {"Conversion of type '", expr_type, "' to type '", target_type, + "' may be a mistake because neither type sufficiently overlaps with the other. If this was ", + "intentional, convert the expression to 'unknown' first."}, + expr->Start()); + + return target_type; } checker::Type *TSAnalyzer::Check(ir::TSBigintKeyword *node) const @@ -695,9 +778,8 @@ checker::Type *TSAnalyzer::Check(ir::TSBooleanKeyword *node) const UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::TSClassImplements *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSClassImplements *expr) const { - (void)expr; UNREACHABLE(); } @@ -763,8 +845,12 @@ checker::Type *TSAnalyzer::Check(ir::TSInferType *node) const checker::Type *TSAnalyzer::Check(ir::TSInterfaceBody *expr) const { - (void)expr; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + for (auto *it : expr->Body()) { + it->Check(checker); + } + + return nullptr; } checker::Type *TSAnalyzer::Check(ir::TSInterfaceDeclaration *st) const @@ -773,9 +859,8 @@ checker::Type *TSAnalyzer::Check(ir::TSInterfaceDeclaration *st) const UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::TSInterfaceHeritage *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSInterfaceHeritage *expr) const { - (void)expr; UNREACHABLE(); } @@ -811,8 +896,9 @@ checker::Type *TSAnalyzer::Check(ir::TSModuleDeclaration *st) const checker::Type *TSAnalyzer::Check(ir::TSNamedTupleMember *node) const { - (void)node; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + node->ElementType()->Check(checker); + return nullptr; } checker::Type *TSAnalyzer::Check(ir::TSNeverKeyword *node) const @@ -877,8 +963,13 @@ checker::Type *TSAnalyzer::Check(ir::TSThisType *node) const checker::Type *TSAnalyzer::Check(ir::TSTupleType *node) const { - (void)node; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + for (auto *it : node->ElementType()) { + it->Check(checker); + } + + node->GetType(checker); + return nullptr; } checker::Type *TSAnalyzer::Check(ir::TSTypeAliasDeclaration *st) const @@ -887,9 +978,8 @@ checker::Type *TSAnalyzer::Check(ir::TSTypeAliasDeclaration *st) const UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::TSTypeAssertion *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSTypeAssertion *expr) const { - (void)expr; UNREACHABLE(); } @@ -931,8 +1021,13 @@ checker::Type *TSAnalyzer::Check(ir::TSTypePredicate *node) const checker::Type *TSAnalyzer::Check(ir::TSTypeQuery *node) const { - (void)node; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + if (node->TsType() != nullptr) { + return node->TsType(); + } + + node->SetTsType(node->expr_name_->Check(checker)); + return node->TsType(); } checker::Type *TSAnalyzer::Check(ir::TSTypeReference *node) const diff --git a/ets2panda/compiler/core/ETSCompiler.cpp b/ets2panda/compiler/core/ETSCompiler.cpp index 46dd096ae82d9c812db8af28704dee330951bdcd..507b291ea30fb3ce9d139df634fbe56db6951af8 100644 --- a/ets2panda/compiler/core/ETSCompiler.cpp +++ b/ets2panda/compiler/core/ETSCompiler.cpp @@ -16,11 +16,11 @@ #include "ETSCompiler.h" #include "checker/types/ets/etsDynamicFunctionType.h" +#include "checker/types/ts/enumLiteralType.h" #include "compiler/base/condition.h" #include "compiler/base/lreference.h" #include "compiler/core/ETSGen.h" #include "compiler/function/functionBuilder.h" - namespace panda::es2panda::compiler { ETSGen *ETSCompiler::GetETSGen() const @@ -370,9 +370,8 @@ void ETSCompiler::Compile(const ir::SuperExpression *expr) const UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TaggedTemplateExpression *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TaggedTemplateExpression *expr) const { - (void)expr; UNREACHABLE(); } @@ -396,8 +395,43 @@ void ETSCompiler::Compile(const ir::UnaryExpression *expr) const void ETSCompiler::Compile(const ir::UpdateExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + + auto lref = compiler::ETSLReference::Create(etsg, expr->Argument(), false); + + const auto argument_boxing_flags = static_cast(expr->Argument()->GetBoxingUnboxingFlags() & + ir::BoxingUnboxingFlags::BOXING_FLAG); + const auto argument_unboxing_flags = static_cast( + expr->Argument()->GetBoxingUnboxingFlags() & ir::BoxingUnboxingFlags::UNBOXING_FLAG); + + if (expr->IsPrefix()) { + lref.GetValue(); + expr->Argument()->SetBoxingUnboxingFlags(argument_unboxing_flags); + etsg->ApplyConversion(expr->Argument(), nullptr); + etsg->Update(expr, expr->OperatorType()); + expr->Argument()->SetBoxingUnboxingFlags(argument_boxing_flags); + etsg->ApplyConversion(expr->Argument(), expr->Argument()->TsType()); + lref.SetValue(); + return; + } + + // workaround so argument_ does not get auto unboxed by lref.GetValue() + expr->Argument()->SetBoxingUnboxingFlags(ir::BoxingUnboxingFlags::NONE); + lref.GetValue(); + + compiler::RegScope rs(etsg); + compiler::VReg original_value_reg = etsg->AllocReg(); + etsg->StoreAccumulator(expr->Argument(), original_value_reg); + + expr->Argument()->SetBoxingUnboxingFlags(argument_unboxing_flags); + etsg->ApplyConversion(expr->Argument(), nullptr); + etsg->Update(expr, expr->OperatorType()); + + expr->Argument()->SetBoxingUnboxingFlags(argument_boxing_flags); + etsg->ApplyConversion(expr->Argument(), expr->Argument()->TsType()); + lref.SetValue(); + + etsg->LoadAccumulator(expr->Argument(), original_value_reg); } void ETSCompiler::Compile(const ir::YieldExpression *expr) const @@ -668,8 +702,10 @@ void ETSCompiler::Compile(const ir::VariableDeclarator *st) const void ETSCompiler::Compile(const ir::VariableDeclaration *st) const { - (void)st; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + for (const auto *it : st->Declarators()) { + it->Compile(etsg); + } } void ETSCompiler::Compile(const ir::WhileStatement *st) const @@ -692,8 +728,75 @@ void ETSCompiler::Compile(const ir::TSArrayType *node) const void ETSCompiler::Compile(const ir::TSAsExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + + auto ttctx = compiler::TargetTypeContext(etsg, nullptr); + if (!etsg->TryLoadConstantExpression(expr->Expr())) { + expr->Expr()->Compile(etsg); + } + + etsg->ApplyConversion(expr->Expr(), nullptr); + + auto *target_type = expr->TsType(); + if (target_type->IsETSUnionType()) { + target_type = target_type->AsETSUnionType()->FindTypeIsCastableToThis( + expr->expression_, etsg->Checker()->Relation(), expr->expression_->TsType()); + } + switch (checker::ETSChecker::TypeKind(target_type)) { + case checker::TypeFlag::ETS_BOOLEAN: { + etsg->CastToBoolean(expr); + break; + } + case checker::TypeFlag::CHAR: { + etsg->CastToChar(expr); + break; + } + case checker::TypeFlag::BYTE: { + etsg->CastToByte(expr); + break; + } + case checker::TypeFlag::SHORT: { + etsg->CastToShort(expr); + break; + } + case checker::TypeFlag::INT: { + etsg->CastToInt(expr); + break; + } + case checker::TypeFlag::LONG: { + etsg->CastToLong(expr); + break; + } + case checker::TypeFlag::FLOAT: { + etsg->CastToFloat(expr); + break; + } + case checker::TypeFlag::DOUBLE: { + etsg->CastToDouble(expr); + break; + } + case checker::TypeFlag::ETS_ARRAY: + case checker::TypeFlag::ETS_OBJECT: + case checker::TypeFlag::ETS_DYNAMIC_TYPE: { + etsg->CastToArrayOrObject(expr, target_type, expr->is_unchecked_cast_); + break; + } + case checker::TypeFlag::ETS_STRING_ENUM: + [[fallthrough]]; + case checker::TypeFlag::ETS_ENUM: { + auto *const signature = expr->TsType()->IsETSEnumType() + ? expr->TsType()->AsETSEnumType()->FromIntMethod().global_signature + : expr->TsType()->AsETSStringEnumType()->FromIntMethod().global_signature; + ArenaVector arguments(etsg->Allocator()->Adapter()); + arguments.push_back(expr->expression_); + etsg->CallStatic(expr, signature, arguments); + etsg->SetAccumulatorType(signature->ReturnType()); + break; + } + default: { + UNREACHABLE(); + } + } } void ETSCompiler::Compile(const ir::TSBigintKeyword *node) const @@ -708,9 +811,8 @@ void ETSCompiler::Compile(const ir::TSBooleanKeyword *node) const UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSClassImplements *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSClassImplements *expr) const { - (void)expr; UNREACHABLE(); } @@ -774,9 +876,8 @@ void ETSCompiler::Compile(const ir::TSInferType *node) const UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSInterfaceBody *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSInterfaceBody *expr) const { - (void)expr; UNREACHABLE(); } @@ -786,9 +887,8 @@ void ETSCompiler::Compile(const ir::TSInterfaceDeclaration *st) const UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSInterfaceHeritage *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSInterfaceHeritage *expr) const { - (void)expr; UNREACHABLE(); } @@ -822,9 +922,8 @@ void ETSCompiler::Compile(const ir::TSModuleDeclaration *st) const UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSNamedTupleMember *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSNamedTupleMember *node) const { - (void)node; UNREACHABLE(); } @@ -888,9 +987,8 @@ void ETSCompiler::Compile(const ir::TSThisType *node) const UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSTupleType *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSTupleType *node) const { - (void)node; UNREACHABLE(); } @@ -900,9 +998,8 @@ void ETSCompiler::Compile(const ir::TSTypeAliasDeclaration *st) const UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSTypeAssertion *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSTypeAssertion *expr) const { - (void)expr; UNREACHABLE(); } @@ -942,9 +1039,8 @@ void ETSCompiler::Compile(const ir::TSTypePredicate *node) const UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSTypeQuery *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSTypeQuery *node) const { - (void)node; UNREACHABLE(); } diff --git a/ets2panda/compiler/core/JSCompiler.cpp b/ets2panda/compiler/core/JSCompiler.cpp index 10a894d364243fe8b74d0bd55d96c5d90df2551c..45b9f8f01844b923be2a0bcb5fde9d344b88fd2f 100644 --- a/ets2panda/compiler/core/JSCompiler.cpp +++ b/ets2panda/compiler/core/JSCompiler.cpp @@ -20,7 +20,6 @@ #include "compiler/core/pandagen.h" #include "compiler/function/functionBuilder.h" #include "util/helpers.h" - namespace panda::es2panda::compiler { PandaGen *JSCompiler::GetPandaGen() const @@ -674,8 +673,20 @@ void JSCompiler::Compile(const ir::SuperExpression *expr) const void JSCompiler::Compile(const ir::TaggedTemplateExpression *expr) const { - (void)expr; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + compiler::RegScope rs(pg); + compiler::VReg callee = pg->AllocReg(); + compiler::VReg this_reg = compiler::VReg::Invalid(); + + if (expr->Tag()->IsMemberExpression()) { + this_reg = pg->AllocReg(); + compiler::RegScope mrs(pg); + expr->Tag()->AsMemberExpression()->CompileToReg(pg, this_reg); + } else { + expr->Tag()->Compile(pg); + } + + pg->CallTagged(expr, callee, this_reg, expr->Quasi()->Expressions()); } void JSCompiler::Compile(const ir::TemplateLiteral *expr) const @@ -698,8 +709,21 @@ void JSCompiler::Compile(const ir::UnaryExpression *expr) const void JSCompiler::Compile(const ir::UpdateExpression *expr) const { - (void)expr; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + compiler::RegScope rs(pg); + compiler::VReg operand_reg = pg->AllocReg(); + + auto lref = compiler::JSLReference::Create(pg, expr->Argument(), false); + lref.GetValue(); + + pg->StoreAccumulator(expr, operand_reg); + pg->Unary(expr, expr->OperatorType(), operand_reg); + + lref.SetValue(); + + if (!expr->IsPrefix()) { + pg->ToNumber(expr, operand_reg); + } } void JSCompiler::Compile(const ir::YieldExpression *expr) const @@ -953,8 +977,10 @@ void JSCompiler::Compile(const ir::VariableDeclarator *st) const void JSCompiler::Compile(const ir::VariableDeclaration *st) const { - (void)st; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + for (const auto *it : st->Declarators()) { + it->Compile(pg); + } } void JSCompiler::Compile(const ir::WhileStatement *st) const @@ -975,9 +1001,8 @@ void JSCompiler::Compile(const ir::TSArrayType *node) const UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSAsExpression *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSAsExpression *expr) const { - (void)expr; UNREACHABLE(); } @@ -993,9 +1018,8 @@ void JSCompiler::Compile(const ir::TSBooleanKeyword *node) const UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSClassImplements *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSClassImplements *expr) const { - (void)expr; UNREACHABLE(); } @@ -1059,9 +1083,8 @@ void JSCompiler::Compile(const ir::TSInferType *node) const UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSInterfaceBody *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSInterfaceBody *expr) const { - (void)expr; UNREACHABLE(); } @@ -1071,9 +1094,8 @@ void JSCompiler::Compile(const ir::TSInterfaceDeclaration *st) const UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSInterfaceHeritage *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSInterfaceHeritage *expr) const { - (void)expr; UNREACHABLE(); } @@ -1107,9 +1129,8 @@ void JSCompiler::Compile(const ir::TSModuleDeclaration *st) const UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSNamedTupleMember *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSNamedTupleMember *node) const { - (void)node; UNREACHABLE(); } @@ -1173,9 +1194,8 @@ void JSCompiler::Compile(const ir::TSThisType *node) const UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSTupleType *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSTupleType *node) const { - (void)node; UNREACHABLE(); } @@ -1185,9 +1205,8 @@ void JSCompiler::Compile(const ir::TSTypeAliasDeclaration *st) const UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSTypeAssertion *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSTypeAssertion *expr) const { - (void)expr; UNREACHABLE(); } @@ -1221,15 +1240,13 @@ void JSCompiler::Compile(const ir::TSTypeParameterInstantiation *expr) const UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSTypePredicate *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSTypePredicate *node) const { - (void)node; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSTypeQuery *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSTypeQuery *node) const { - (void)node; UNREACHABLE(); } diff --git a/ets2panda/ir/expressions/taggedTemplateExpression.cpp b/ets2panda/ir/expressions/taggedTemplateExpression.cpp index 3960c0d1c3ee7c915b032ecb59f765e754cdf4d2..2e36f30718f7417d73021f6c0b07ef031326beb0 100644 --- a/ets2panda/ir/expressions/taggedTemplateExpression.cpp +++ b/ets2panda/ir/expressions/taggedTemplateExpression.cpp @@ -17,6 +17,7 @@ #include "varbinder/variable.h" #include "compiler/base/literals.h" +#include "compiler/core/ETSGen.h" #include "compiler/core/pandagen.h" #include "compiler/core/regScope.h" #include "checker/TSchecker.h" @@ -56,30 +57,22 @@ void TaggedTemplateExpression::Dump(ir::AstDumper *dumper) const void TaggedTemplateExpression::Compile(compiler::PandaGen *pg) const { - compiler::RegScope rs(pg); - compiler::VReg callee = pg->AllocReg(); - compiler::VReg this_reg = compiler::VReg::Invalid(); - - if (tag_->IsMemberExpression()) { - this_reg = pg->AllocReg(); - compiler::RegScope mrs(pg); - tag_->AsMemberExpression()->CompileToReg(pg, this_reg); - } else { - tag_->Compile(pg); - } + pg->GetAstCompiler()->Compile(this); +} - pg->CallTagged(this, callee, this_reg, quasi_->Expressions()); +void TaggedTemplateExpression::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); } checker::Type *TaggedTemplateExpression::Check(checker::TSChecker *checker) { - // NOTE: aszilagyi. - return checker->GlobalAnyType(); + return checker->GetAnalyzer()->Check(this); } checker::Type *TaggedTemplateExpression::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } // NOLINTNEXTLINE(google-default-arguments) diff --git a/ets2panda/ir/expressions/taggedTemplateExpression.h b/ets2panda/ir/expressions/taggedTemplateExpression.h index 194571cf79c12eda61595a57a64efd753b6d948c..5cbfe869c4b4d57e6ecfb162dfb0bfedd46763d9 100644 --- a/ets2panda/ir/expressions/taggedTemplateExpression.h +++ b/ets2panda/ir/expressions/taggedTemplateExpression.h @@ -58,6 +58,7 @@ public: void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; diff --git a/ets2panda/ir/expressions/updateExpression.cpp b/ets2panda/ir/expressions/updateExpression.cpp index e72ca193e8daeafe42af10f01d419cdbdc17b9f4..0266964d17c1ba87932912402bc261ee8643390f 100644 --- a/ets2panda/ir/expressions/updateExpression.cpp +++ b/ets2panda/ir/expressions/updateExpression.cpp @@ -45,107 +45,22 @@ void UpdateExpression::Dump(ir::AstDumper *dumper) const void UpdateExpression::Compile(compiler::PandaGen *pg) const { - compiler::RegScope rs(pg); - compiler::VReg operand_reg = pg->AllocReg(); - - auto lref = compiler::JSLReference::Create(pg, argument_, false); - lref.GetValue(); - - pg->StoreAccumulator(this, operand_reg); - pg->Unary(this, operator_, operand_reg); - - lref.SetValue(); - - if (!IsPrefix()) { - pg->ToNumber(this, operand_reg); - } + pg->GetAstCompiler()->Compile(this); } void UpdateExpression::Compile(compiler::ETSGen *etsg) const { - auto lref = compiler::ETSLReference::Create(etsg, argument_, false); - - const auto argument_boxing_flags = - static_cast(argument_->GetBoxingUnboxingFlags() & BoxingUnboxingFlags::BOXING_FLAG); - const auto argument_unboxing_flags = - static_cast(argument_->GetBoxingUnboxingFlags() & BoxingUnboxingFlags::UNBOXING_FLAG); - - if (prefix_) { - lref.GetValue(); - argument_->SetBoxingUnboxingFlags(argument_unboxing_flags); - etsg->ApplyConversion(argument_, nullptr); - etsg->Update(this, operator_); - argument_->SetBoxingUnboxingFlags(argument_boxing_flags); - etsg->ApplyConversion(argument_, argument_->TsType()); - lref.SetValue(); - return; - } - - // workaround so argument_ does not get auto unboxed by lref.GetValue() - argument_->SetBoxingUnboxingFlags(BoxingUnboxingFlags::NONE); - lref.GetValue(); - - compiler::RegScope rs(etsg); - compiler::VReg original_value_reg = etsg->AllocReg(); - etsg->StoreAccumulator(argument_, original_value_reg); - - argument_->SetBoxingUnboxingFlags(argument_unboxing_flags); - etsg->ApplyConversion(argument_, nullptr); - etsg->Update(this, operator_); - - argument_->SetBoxingUnboxingFlags(argument_boxing_flags); - etsg->ApplyConversion(argument_, argument_->TsType()); - lref.SetValue(); - - etsg->LoadAccumulator(argument_, original_value_reg); + etsg->GetAstCompiler()->Compile(this); } checker::Type *UpdateExpression::Check(checker::TSChecker *checker) { - checker::Type *operand_type = argument_->Check(checker); - checker->CheckNonNullType(operand_type, Start()); - - if (!operand_type->HasTypeFlag(checker::TypeFlag::VALID_ARITHMETIC_TYPE)) { - checker->ThrowTypeError("An arithmetic operand must be of type 'any', 'number', 'bigint' or an enum type.", - Start()); - } - - checker->CheckReferenceExpression( - argument_, "The operand of an increment or decrement operator must be a variable or a property access", - "The operand of an increment or decrement operator may not be an optional property access"); - - return checker->GetUnaryResultType(operand_type); + return checker->GetAnalyzer()->Check(this); } checker::Type *UpdateExpression::Check(checker::ETSChecker *checker) { - if (TsType() != nullptr) { - return TsType(); - } - - checker::Type *operand_type = argument_->Check(checker); - if (argument_->IsIdentifier()) { - checker->ValidateUnaryOperatorOperand(argument_->AsIdentifier()->Variable()); - } else { - ASSERT(argument_->IsMemberExpression()); - varbinder::LocalVariable *prop_var = argument_->AsMemberExpression()->PropVar(); - if (prop_var != nullptr) { - checker->ValidateUnaryOperatorOperand(prop_var); - } - } - - auto unboxed_type = checker->ETSBuiltinTypeAsPrimitiveType(operand_type); - - if (unboxed_type == nullptr || !unboxed_type->HasTypeFlag(checker::TypeFlag::ETS_NUMERIC)) { - checker->ThrowTypeError("Bad operand type, the type of the operand must be numeric type.", argument_->Start()); - } - - if (operand_type->IsETSObjectType()) { - argument_->AddBoxingUnboxingFlag(checker->GetUnboxingFlag(unboxed_type) | checker->GetBoxingFlag(unboxed_type)); - } - - SetTsType(operand_type); - return TsType(); + return checker->GetAnalyzer()->Check(this); } // NOLINTNEXTLINE(google-default-arguments) diff --git a/ets2panda/ir/expressions/updateExpression.h b/ets2panda/ir/expressions/updateExpression.h index 34901b1845bbf46306de88a9c286b86845db85dd..aa908e434bc2be7ed1fa0663b05ea3cd08c98922 100644 --- a/ets2panda/ir/expressions/updateExpression.h +++ b/ets2panda/ir/expressions/updateExpression.h @@ -18,7 +18,10 @@ #include "ir/expression.h" #include "lexer/token/tokenType.h" - +namespace panda::es2panda::checker { +class TSAnalyzer; +class ETSAnalyzer; +} // namespace panda::es2panda::checker namespace panda::es2panda::ir { class UpdateExpression : public Expression { public: @@ -38,6 +41,10 @@ public: update_operator == lexer::TokenType::PUNCTUATOR_MINUS_MINUS); } + // TODO (vivienvoros): these friend relationships can be removed once there are getters for private fields + friend class checker::TSAnalyzer; + friend class checker::ETSAnalyzer; + [[nodiscard]] lexer::TokenType OperatorType() const noexcept { return operator_; diff --git a/ets2panda/ir/statements/variableDeclaration.cpp b/ets2panda/ir/statements/variableDeclaration.cpp index a8a79bc6d75392af96ed070c1f4b5b895c57d02a..205265a3dafd8785ea6f8598622548db1514b8cc 100644 --- a/ets2panda/ir/statements/variableDeclaration.cpp +++ b/ets2panda/ir/statements/variableDeclaration.cpp @@ -19,6 +19,8 @@ #include "varbinder/variable.h" #include "checker/TSchecker.h" #include "checker/ETSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "ir/base/decorator.h" #include "ir/expressions/arrayExpression.h" @@ -80,33 +82,21 @@ void VariableDeclaration::Dump(ir::AstDumper *dumper) const void VariableDeclaration::Compile(compiler::PandaGen *pg) const { - for (const auto *it : declarators_) { - it->Compile(pg); - } + pg->GetAstCompiler()->Compile(this); } void VariableDeclaration::Compile(compiler::ETSGen *etsg) const { - for (const auto *it : declarators_) { - it->Compile(etsg); - } + etsg->GetAstCompiler()->Compile(this); } checker::Type *VariableDeclaration::Check(checker::TSChecker *checker) { - for (auto *it : declarators_) { - it->Check(checker); - } - - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *VariableDeclaration::Check([[maybe_unused]] checker::ETSChecker *checker) { - for (auto *it : declarators_) { - it->Check(checker); - } - - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsAsExpression.cpp b/ets2panda/ir/ts/tsAsExpression.cpp index fc81c5a92071c89f233ebba004fb4ee84b027a0a..faeaf45c3cb25c776ed31810b459c97f56d78086 100644 --- a/ets2panda/ir/ts/tsAsExpression.cpp +++ b/ets2panda/ir/ts/tsAsExpression.cpp @@ -20,6 +20,7 @@ #include "checker/ets/castingContext.h" #include "checker/types/ets/etsUnionType.h" #include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/expressions/identifier.h" #include "ir/expressions/literal.h" #include "ir/expressions/memberExpression.h" @@ -57,179 +58,23 @@ void TSAsExpression::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSAsExpression"}, {"expression", expression_}, {"typeAnnotation", TypeAnnotation()}}); } -void TSAsExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} - -void TSAsExpression::Compile(compiler::ETSGen *etsg) const +void TSAsExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const { - auto ttctx = compiler::TargetTypeContext(etsg, nullptr); - if (!etsg->TryLoadConstantExpression(expression_)) { - expression_->Compile(etsg); - } - - etsg->ApplyConversion(expression_, nullptr); - - auto *target_type = TsType(); - if (target_type->IsETSUnionType()) { - target_type = target_type->AsETSUnionType()->FindTypeIsCastableToThis(expression_, etsg->Checker()->Relation(), - expression_->TsType()); - } - switch (checker::ETSChecker::TypeKind(target_type)) { - case checker::TypeFlag::ETS_BOOLEAN: { - etsg->CastToBoolean(this); - break; - } - case checker::TypeFlag::CHAR: { - etsg->CastToChar(this); - break; - } - case checker::TypeFlag::BYTE: { - etsg->CastToByte(this); - break; - } - case checker::TypeFlag::SHORT: { - etsg->CastToShort(this); - break; - } - case checker::TypeFlag::INT: { - etsg->CastToInt(this); - break; - } - case checker::TypeFlag::LONG: { - etsg->CastToLong(this); - break; - } - case checker::TypeFlag::FLOAT: { - etsg->CastToFloat(this); - break; - } - case checker::TypeFlag::DOUBLE: { - etsg->CastToDouble(this); - break; - } - case checker::TypeFlag::ETS_ARRAY: - case checker::TypeFlag::ETS_OBJECT: - case checker::TypeFlag::ETS_DYNAMIC_TYPE: { - etsg->CastToArrayOrObject(this, target_type, is_unchecked_cast_); - break; - } - case checker::TypeFlag::ETS_STRING_ENUM: - [[fallthrough]]; - case checker::TypeFlag::ETS_ENUM: { - auto *const signature = TsType()->IsETSEnumType() - ? TsType()->AsETSEnumType()->FromIntMethod().global_signature - : TsType()->AsETSStringEnumType()->FromIntMethod().global_signature; - ArenaVector arguments(etsg->Allocator()->Adapter()); - arguments.push_back(expression_); - etsg->CallStatic(this, signature, arguments); - etsg->SetAccumulatorType(signature->ReturnType()); - break; - } - default: { - UNREACHABLE(); - } - } + pg->GetAstCompiler()->Compile(this); } -static bool IsValidConstAssertionArgument(checker::Checker *checker, const ir::AstNode *arg) +void TSAsExpression::Compile(compiler::ETSGen *etsg) const { - switch (arg->Type()) { - case ir::AstNodeType::NUMBER_LITERAL: - case ir::AstNodeType::STRING_LITERAL: - case ir::AstNodeType::BIGINT_LITERAL: - case ir::AstNodeType::BOOLEAN_LITERAL: - case ir::AstNodeType::ARRAY_EXPRESSION: - case ir::AstNodeType::OBJECT_EXPRESSION: - case ir::AstNodeType::TEMPLATE_LITERAL: { - return true; - } - case ir::AstNodeType::UNARY_EXPRESSION: { - const ir::UnaryExpression *unary_expr = arg->AsUnaryExpression(); - lexer::TokenType op = unary_expr->OperatorType(); - const ir::Expression *unary_arg = unary_expr->Argument(); - return (op == lexer::TokenType::PUNCTUATOR_MINUS && unary_arg->IsLiteral() && - (unary_arg->AsLiteral()->IsNumberLiteral() || unary_arg->AsLiteral()->IsBigIntLiteral())) || - (op == lexer::TokenType::PUNCTUATOR_PLUS && unary_arg->IsLiteral() && - unary_arg->AsLiteral()->IsNumberLiteral()); - } - case ir::AstNodeType::MEMBER_EXPRESSION: { - const ir::MemberExpression *member_expr = arg->AsMemberExpression(); - if (member_expr->Object()->IsIdentifier()) { - auto result = checker->Scope()->Find(member_expr->Object()->AsIdentifier()->Name()); - constexpr auto ENUM_LITERAL_TYPE = checker::EnumLiteralType::EnumLiteralTypeKind::LITERAL; - if (result.variable != nullptr && - result.variable->TsType()->HasTypeFlag(checker::TypeFlag::ENUM_LITERAL) && - result.variable->TsType()->AsEnumLiteralType()->Kind() == ENUM_LITERAL_TYPE) { - return true; - } - } - return false; - } - default: - return false; - } + etsg->GetAstCompiler()->Compile(this); } checker::Type *TSAsExpression::Check([[maybe_unused]] checker::TSChecker *checker) { - if (is_const_) { - auto context = checker::SavedCheckerContext(checker, checker::CheckerStatus::IN_CONST_CONTEXT); - checker::Type *expr_type = expression_->Check(checker); - - if (!IsValidConstAssertionArgument(checker, expression_)) { - checker->ThrowTypeError( - "A 'const' assertions can only be applied to references to enum members, or string, number, " - "boolean, array, or object literals.", - expression_->Start()); - } - - return expr_type; - } - - auto context = checker::SavedCheckerContext(checker, checker::CheckerStatus::NO_OPTS); - - TypeAnnotation()->Check(checker); - checker::Type *expr_type = checker->GetBaseTypeOfLiteralType(expression_->Check(checker)); - checker::Type *target_type = TypeAnnotation()->GetType(checker); - - checker->IsTypeComparableTo( - target_type, expr_type, - {"Conversion of type '", expr_type, "' to type '", target_type, - "' may be a mistake because neither type sufficiently overlaps with the other. If this was ", - "intentional, convert the expression to 'unknown' first."}, - Start()); - - return target_type; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSAsExpression::Check(checker::ETSChecker *const checker) { - auto *const target_type = TypeAnnotation()->AsTypeNode()->GetType(checker); - // Object expression requires that its type be set by the context before checking. in this case, the target type - // provides that context. - if (expression_->IsObjectExpression()) { - expression_->AsObjectExpression()->SetPreferredType(target_type); - } - auto *const source_type = expression_->Check(checker); - - const checker::CastingContext ctx(checker->Relation(), expression_, source_type, target_type, expression_->Start(), - {"Cannot cast type '", source_type, "' to '", target_type, "'"}); - - if (source_type->IsETSDynamicType() && target_type->IsLambdaObject()) { - // NOTE: itrubachev. change target_type to created lambdaobject type. - // Now target_type is not changed, only construct signature is added to it - checker->BuildLambdaObjectClass(target_type->AsETSObjectType(), - TypeAnnotation()->AsETSFunctionType()->ReturnType()); - } - is_unchecked_cast_ = ctx.UncheckedCast(); - - // Make sure the array type symbol gets created for the assembler to be able to emit checkcast. - // Because it might not exist, if this particular array type was never created explicitly. - if (!is_unchecked_cast_ && target_type->IsETSArrayType()) { - auto *const target_array_type = target_type->AsETSArrayType(); - checker->CreateBuiltinArraySignature(target_array_type, target_array_type->Rank()); - } - - SetTsType(target_type); - return TsType(); + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsAsExpression.h b/ets2panda/ir/ts/tsAsExpression.h index 549851835e5e6a0daec1699118710ce22e24304a..07242c06dbead91bd73efeb41f9c9e7586e41310 100644 --- a/ets2panda/ir/ts/tsAsExpression.h +++ b/ets2panda/ir/ts/tsAsExpression.h @@ -18,7 +18,13 @@ #include "ir/astDump.h" #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 TSAsExpression : public AnnotatedExpression { public: @@ -28,7 +34,9 @@ public: is_const_(is_const) { } - + // TODO (vivienvoros): these friend relationships can be removed once there are getters for private fields + friend class checker::ETSAnalyzer; + friend class compiler::ETSCompiler; const Expression *Expr() const { return expression_; diff --git a/ets2panda/ir/ts/tsClassImplements.cpp b/ets2panda/ir/ts/tsClassImplements.cpp index 00ad11e2dfc0f4faa6749dbec51933a96da287b9..c3183cd25093eda04580e08ec958ed837f69c9dc 100644 --- a/ets2panda/ir/ts/tsClassImplements.cpp +++ b/ets2panda/ir/ts/tsClassImplements.cpp @@ -15,6 +15,9 @@ #include "tsClassImplements.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "ir/ts/tsTypeParameter.h" #include "ir/ts/tsTypeParameterInstantiation.h" @@ -41,15 +44,23 @@ void TSClassImplements::Dump(ir::AstDumper *dumper) const {"typeParameters", AstDumper::Optional(type_parameters_)}}); } -void TSClassImplements::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSClassImplements::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} + +void TSClassImplements::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSClassImplements::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSClassImplements::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsClassImplements.h b/ets2panda/ir/ts/tsClassImplements.h index 82b5510f923bdea31583e784ebc8f4bace2ca702..ca5e0ddd143bcd58309a9a31bba131f004a3e154 100644 --- a/ets2panda/ir/ts/tsClassImplements.h +++ b/ets2panda/ir/ts/tsClassImplements.h @@ -52,6 +52,7 @@ public: void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; diff --git a/ets2panda/ir/ts/tsInterfaceBody.cpp b/ets2panda/ir/ts/tsInterfaceBody.cpp index 369391dfbdb71c1376337f0346fcae4f2b1c13bf..418b66f22dfc2943db631cfbcaee60592f0be93f 100644 --- a/ets2panda/ir/ts/tsInterfaceBody.cpp +++ b/ets2panda/ir/ts/tsInterfaceBody.cpp @@ -15,6 +15,9 @@ #include "tsInterfaceBody.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" namespace panda::es2panda::ir { @@ -37,19 +40,23 @@ void TSInterfaceBody::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSInterfaceBody"}, {"body", body_}}); } -void TSInterfaceBody::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSInterfaceBody::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} -checker::Type *TSInterfaceBody::Check([[maybe_unused]] checker::TSChecker *checker) +void TSInterfaceBody::Compile(compiler::ETSGen *etsg) const { - for (auto *it : body_) { - it->Check(checker); - } + etsg->GetAstCompiler()->Compile(this); +} - return nullptr; +checker::Type *TSInterfaceBody::Check([[maybe_unused]] checker::TSChecker *checker) +{ + return checker->GetAnalyzer()->Check(this); } checker::Type *TSInterfaceBody::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsInterfaceBody.h b/ets2panda/ir/ts/tsInterfaceBody.h index 7197e7c2fc6e9440d469836e1fadbbede6fa9160..7124ef9192910c324c8d4087606d72aa45881516 100644 --- a/ets2panda/ir/ts/tsInterfaceBody.h +++ b/ets2panda/ir/ts/tsInterfaceBody.h @@ -45,6 +45,7 @@ public: void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; diff --git a/ets2panda/ir/ts/tsInterfaceHeritage.cpp b/ets2panda/ir/ts/tsInterfaceHeritage.cpp index fe81446c5cf6e7273f6e45febf853ef16a75a009..e14e86ecaac7651ee823177a00c40e4943f35bd6 100644 --- a/ets2panda/ir/ts/tsInterfaceHeritage.cpp +++ b/ets2panda/ir/ts/tsInterfaceHeritage.cpp @@ -17,6 +17,9 @@ #include "varbinder/scope.h" #include "checker/TSchecker.h" +#include "compiler/core/ETSCompiler.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "ir/expressions/identifier.h" #include "ir/ts/tsTypeParameterInstantiation.h" @@ -41,15 +44,23 @@ void TSInterfaceHeritage::Dump(ir::AstDumper *dumper) const }); } -void TSInterfaceHeritage::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSInterfaceHeritage::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} + +void TSInterfaceHeritage::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSInterfaceHeritage::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSInterfaceHeritage::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsInterfaceHeritage.h b/ets2panda/ir/ts/tsInterfaceHeritage.h index 3ce89c33f764892c9d96e7b3b075d9b962265118..c33615e5857cf1c43a4cd1a230ef90cf5f8cc5f8 100644 --- a/ets2panda/ir/ts/tsInterfaceHeritage.h +++ b/ets2panda/ir/ts/tsInterfaceHeritage.h @@ -40,6 +40,7 @@ public: void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; diff --git a/ets2panda/ir/ts/tsNamedTupleMember.cpp b/ets2panda/ir/ts/tsNamedTupleMember.cpp index e92c5787dd1c1560fff7125cae7888916bad6212..bfea9f07de9f9dc64e229988c6414918ffc43d4c 100644 --- a/ets2panda/ir/ts/tsNamedTupleMember.cpp +++ b/ets2panda/ir/ts/tsNamedTupleMember.cpp @@ -15,6 +15,10 @@ #include "tsNamedTupleMember.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 { @@ -38,16 +42,23 @@ void TSNamedTupleMember::Dump(ir::AstDumper *dumper) const {"optional", AstDumper::Optional(optional_)}}); } -void TSNamedTupleMember::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSNamedTupleMember::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} + +void TSNamedTupleMember::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSNamedTupleMember::Check([[maybe_unused]] checker::TSChecker *checker) { - element_type_->Check(checker); - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSNamedTupleMember::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsNamedTupleMember.h b/ets2panda/ir/ts/tsNamedTupleMember.h index a7266a6a42aa1137a9514a79f6ea3f38fb1bfcd0..47f8bda2ac430c5b4baac3a697a48a9f32379f37 100644 --- a/ets2panda/ir/ts/tsNamedTupleMember.h +++ b/ets2panda/ir/ts/tsNamedTupleMember.h @@ -50,6 +50,7 @@ public: void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; diff --git a/ets2panda/ir/ts/tsTupleType.cpp b/ets2panda/ir/ts/tsTupleType.cpp index ac326b46595d7ff437e9aa4800465bbfb93fc519..624d9582339de06f529aec7f65d22778c9842f6f 100644 --- a/ets2panda/ir/ts/tsTupleType.cpp +++ b/ets2panda/ir/ts/tsTupleType.cpp @@ -15,6 +15,8 @@ #include "tsTupleType.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "util/helpers.h" #include "varbinder/scope.h" #include "checker/TSchecker.h" @@ -43,7 +45,15 @@ void TSTupleType::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSTupleType"}, {"elementTypes", element_types_}}); } -void TSTupleType::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSTupleType::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} + +void TSTupleType::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSTupleType::GetType(checker::TSChecker *checker) { @@ -118,16 +128,11 @@ checker::Type *TSTupleType::GetType(checker::TSChecker *checker) checker::Type *TSTupleType::Check(checker::TSChecker *checker) { - for (auto *it : element_types_) { - it->Check(checker); - } - - GetType(checker); - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSTupleType::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsTupleType.h b/ets2panda/ir/ts/tsTupleType.h index 53a70353970122c2d6e396eb051fca12060a1630..b0a1d7012be1428f6cac661ab69de908726f8ca2 100644 --- a/ets2panda/ir/ts/tsTupleType.h +++ b/ets2panda/ir/ts/tsTupleType.h @@ -37,6 +37,7 @@ public: void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; diff --git a/ets2panda/ir/ts/tsTypeAssertion.cpp b/ets2panda/ir/ts/tsTypeAssertion.cpp index 7abafef59dd674c13b56afff9d9c3f9cf1db1f53..2c2bd745e3e9bed7029869145b56bc9578a8d54a 100644 --- a/ets2panda/ir/ts/tsTypeAssertion.cpp +++ b/ets2panda/ir/ts/tsTypeAssertion.cpp @@ -15,6 +15,9 @@ #include "tsTypeAssertion.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "ir/typeNode.h" @@ -36,15 +39,23 @@ void TSTypeAssertion::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSTypeAssertion"}, {"typeAnnotation", TypeAnnotation()}, {"expression", expression_}}); } -void TSTypeAssertion::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSTypeAssertion::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} + +void TSTypeAssertion::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSTypeAssertion::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSTypeAssertion::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsTypeAssertion.h b/ets2panda/ir/ts/tsTypeAssertion.h index e8a66171643a905828b5706ed661649c4cc7d29a..87794468398e73b7b6dcc55eebae56e06df2c9c8 100644 --- a/ets2panda/ir/ts/tsTypeAssertion.h +++ b/ets2panda/ir/ts/tsTypeAssertion.h @@ -35,6 +35,7 @@ public: void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; diff --git a/ets2panda/ir/ts/tsTypeQuery.cpp b/ets2panda/ir/ts/tsTypeQuery.cpp index 31752510bd7e9fe24b3430e04fd57fd37bdca930..cb45ace08c1db5708ae58ea18132dad7ba709cb1 100644 --- a/ets2panda/ir/ts/tsTypeQuery.cpp +++ b/ets2panda/ir/ts/tsTypeQuery.cpp @@ -15,6 +15,9 @@ #include "tsTypeQuery.h" +#include "checker/ETSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "checker/TSchecker.h" @@ -34,26 +37,28 @@ void TSTypeQuery::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSTypeQuery"}, {"exprName", expr_name_}}); } -void TSTypeQuery::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSTypeQuery::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} + +void TSTypeQuery::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSTypeQuery::Check([[maybe_unused]] checker::TSChecker *checker) { - GetType(checker); - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSTypeQuery::GetType([[maybe_unused]] checker::TSChecker *checker) { - if (TsType() != nullptr) { - return TsType(); - } - - SetTsType(expr_name_->Check(checker)); - return TsType(); + return checker->GetAnalyzer()->Check(this); } checker::Type *TSTypeQuery::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsTypeQuery.h b/ets2panda/ir/ts/tsTypeQuery.h index c4442a5902e46571a7151b9529613c0c94eebadd..b5a3a0d7b012b75d88d2378b3a93f605cca181eb 100644 --- a/ets2panda/ir/ts/tsTypeQuery.h +++ b/ets2panda/ir/ts/tsTypeQuery.h @@ -17,12 +17,16 @@ #define ES2PANDA_IR_TS_TYPE_QUERY_H #include "ir/typeNode.h" - +namespace panda::es2panda::checker { +class TSAnalyzer; +} // namespace panda::es2panda::checker namespace panda::es2panda::ir { class TSTypeQuery : public TypeNode { public: explicit TSTypeQuery(Expression *expr_name) : TypeNode(AstNodeType::TS_TYPE_QUERY), expr_name_(expr_name) {} + friend class checker::TSAnalyzer; + const Expression *ExprName() const { return expr_name_; @@ -32,6 +36,7 @@ public: void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override;